可重入
编辑在计算中,如果多个调用可以在多个处理器或单处理器系统上安全地并发运行,则计算机程序或子例程被称为可重入,其中可重入过程可以在其执行过程中被中断,然后安全地再次调用(重新 -entered) 在其先前的调用完成执行之前。 中断可能是由内部操作(例如跳转或调用)或外部操作(例如中断或信号)引起的,这与递归不同,在递归中,新调用只能由内部调用引起。
该定义源自多道程序设计环境,在该环境中,多个进程可能同时处于活动状态,并且控制流可能会被中断中断并转移到中断服务例程 (ISR) 或处理程序子例程。 处理程序使用的任何可能在触发中断时执行的子程序都应该是可重入的。 同样,访问共享数据的两个处理器共享的代码应该是可重入的。 通常,可通过操作系统内核访问的子例程是不可重入的。 因此,中断服务程序在它们可以执行的操作上是有限的; 例如,它们通常无法访问文件系统,有时甚至无法分配内存。
这种重入的定义不同于多线程环境中的线程安全。 可重入子例程可以实现线程安全,但仅可重入可能不足以在所有情况下都是线程安全的。 相反,线程安全代码不一定是可重入的。
用于可重入程序的其他术语包括可共享代码。 可重入子例程有时在参考资料中标记为信号安全。 可重入程序通常是纯程序。
背景
编辑可重入性与幂等性不同,在幂等性中,函数可以被调用不止一次,但生成的输出与只被调用一次完全相同。 一般来说,一个函数根据一些输入数据产生输出数据(尽管通常两者都是可选的)。 任何功能都可以随时访问共享数据。 如果任何功能都可以更改数据(并且没有人跟踪这些更改),则无法向共享数据的那些人保证该数据与之前的任何时间相同。
数据有一个特性叫做作用域,它描述了数据在程序中的什么地方可以被使用。 数据范围是全局的(在任何函数的范围之外并且具有不确定的范围)或局部的(每次调用函数时创建并在退出时销毁)。
本地数据不被任何例程共享,无论是否重新进入; 因此,它不影响重新进入。 全局数据在函数外部定义,可以被多个函数访问,可以是全局变量的形式(所有函数之间共享的数据),也可以是静态变量(同一函数的所有调用共享的数据)。 在面向对象的编程中,全局数据在类的范围内定义并且可以是私有的,使其只能被该类的函数访问。 还有实例变量的概念,其中类变量绑定到类实例。 由于这些原因,在面向对象的编程中,这种区别通常保留给类外部可访问的数据(公共),以及独立于类实例的数据(静态)。
可重入不同于线程安全,但与线程安全密切相关。 函数可以是线程安全的,但仍然不可重入。 例如,一个函数可以用互斥锁包裹起来(这避免了多线程环境中的问题),但是,如果在中断服务例程中使用该函数,它可能会饿死等待xxx次执行以释放互斥锁。 避免混淆的关键是可重入是指只有一个线程在执行。 这是一个从不存在多任务操作系统的时代开始的概念。
重入规则
编辑可重入代码不能在没有同步的情况下保存任何静态或全局非常量数据。可重入函数可以使用全局数据。 例如,可重入中断服务例程可以获取一块硬件状态(例如,串行端口读取缓冲区),这不仅是全局的,而且是易变的。 不过,不建议典型地使用静态变量和全局数据,在某种意义上,除了同步的代码部分,在这些变量中只应使用原子读-修改-写指令(对于一个 在执行此类指令期间中断或发出信号)。 请注意,在 C 中,即使是读或写也不能保证是原子的; 它可能被分成几个读或写。
内容由匿名用户提供,本内容不代表vibaike.com立场,内容投诉举报请联系vibaike.com客服。如若转载,请注明出处:https://vibaike.com/198041/