原子操作
原子操作是由多个步骤组成的操作。如果该操作原子的执行,则要么执行完所有的操作,要么一步也不执行。
可重入函数
在实时系统的设计中,经常会出现多个任务调用同一个函数的情况。如果这个函数不幸被设计成为不可重入的函数的话,那么不同任务调用这个函数时可能修改其他任务调用这个函数的数据,从而导致不可预料的后果。那么什么是可重入函数呢?一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误;
所谓可重入是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会出错。不可重入函数在实时系统设计中被视为不安全函数。
重入即表示重复进入,首先它意味着这个函数可以被中断,其次意味着它除了使用自己栈上的变量以外不依赖于任何环境(包括static),这样的函数就是purecode(纯代码)可重入,可以允许有该函数的多个副本在运行,由于它们使用的是分离的栈,所以不会互相干扰。如果确实需要访问全局变量(包括static),一定要注意实施互斥手段。可重入函数在并行运行环境中非常重要,但是一般要为访问全局变量付出一些性能代价。
可重入函数编写规范为:
1. 不在函数内部使用静态或全局数据
2. 不返回静态或全局数据,所有数据都由函数的调用者提供。
3. 使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据。
4. 不调用不可重入函数。
5. ……
线程安全函数
线程安全函数:一般说来,一个函数被称为线程安全的,当且仅当被多个并发线程反复调用时,它会一直产生正确的结果。
编写安全的异步信号处理函数
信号的产生可以是:
用户从控制终端终止程序运行,如 Ctrk + C 产生 SIGINT;
程序运行出错时由硬件产生信号,如访问非法地址产生 SIGSEGV;
程序运行逻辑需要,如调用kill、raise 产生信号。
因为信号是异步事件,即信号处理函数执行的上下文背景是不确定的,譬如一个线程在调用某个库函数时可能会被信号中断,库函数提前出错返回,转而去执行信号处理函数。对于上述第三种信号的产生,信号在产生、处理后,应用程序不会终止,还是会继续正常运行,在编写此类信号处理函数时尤其需要小心,以免破坏应用程序的正常运行。关于编写安全的信号处理函数主要有以下一些规则:
1. 信号处理函数尽量只执行简单的操作,譬如只是设置一个外部变量,其它复杂的操作留在信号处理函数之外执行;
2. errno 是线程安全,即每个线程有自己的 errno,但不是异步信号安全。如果信号处理函数比较复杂,且调用了可能会改变 errno 值的库函数,必须考虑在信号处理函数开始时保存、结束的时候恢复被中断线程的 errno 值;
3. 信号处理函数只能调用可以重入的 C 库函数;譬如不能调用malloc(),free()以及标准 I/O 库函数等;
4. 信号处理函数如果需要访问全局变量,在定义此全局变量时须将其声明为 volatile,以避免编译器不恰当的优化。
http://www.ibm.com/developerworks/cn/linux/l-cn-signalsec/