可重入函数与线程安全

来源:互联网 发布:网络教育录取查询 编辑:程序博客网 时间:2024/04/28 06:09

可重入函数:

进程捕捉到信号并对其进行处理时,进程正在执行的指令序列就被信号处理程序临时中断,她首先执行该信号处理程序中的指令。如果信号处理程序返回(例如没有调用exit或longjmp),则继续执行在捕捉到信号时正在执行的正常指令序列(这类似于发生硬件中断时所做的)。如果此时进程还能无差错地执行,说明信号处理程序中调用的函数并没有破坏掉进程在捕捉到信号时正在执行的指令序列的正常执行。也就是说,一个程序被中断后中断处理程序调用的函数对被中断程序的继续正常执行并没有什么影响。

对于不可重入函数的主要原因有一下几点:

a) 已知它们使用静态数据结构;

例如:如果进程正在执行将结果存放在静态存储单元中的函数时,期间插入执行信号处理程序,它又调用这样的函数,这时返回给正常调用者的信息可能被返回给信号处理程序的信息覆盖掉。

b) 它们调用malloc或free;

例如:如果进程正在执行malloc,在其堆中分配另外的存储空间,而此时由于捕捉到信号而插入信号处理程序,其中又调用malloc,这时可能就会对进程造成破坏。因为malloc通常为它所分配的存储区维护一个链表,而插入执行信号处理程序时,进程可能正在更改此链表。

c) 它们是标准I/O函数;

标准I/O库的很多实现都以不可重入方式使用全局数据结构。

注意:即使信号处理程序调用的是可重入函数,但是由于每个线程只有一个errno变量,所以信号处理程序可能会修改其原先值。因此,作为一个通用的原则,当信号处理程序调用可重入函数时,应当在其前保存,在其后回复errno。


线程安全:

如果一个函数在同一时刻被多个线程安全的调用,就称该函数是线程安全的。也就是说,当多个线程同时调用同一个函数时,每个线程都能够正确无误的执行,就像自己在独自调用这个函数一样,这就说明这个被调用的函数是线程安全的。

对于将返回数据存放在静态的内存缓冲区的函数,它们就不是线程安全的。我们可以通过修改接口,要求调用者自己提供缓冲区可以是函数变成线程安全的,见《apue》表12-6。

如果一个函数对多个线程来说是可重入的,则说这个函数是线程安全的,但这并不能说明对信号处理程序来说是该函数是可重入的。(红色部分如何解释,请高手指点)


参考:《apue》Second Edition 10.6节与12.5节

0 0