1)什么是可重入性? 可重入(reentrant)函数可以由多于一个任务并发使用,而不必担心数据错误。相反, 不可重入(non-reentrant)函数不能由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在代码的关键部分禁用中断)。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据。可重入函数要么使用本地变量,要么在使用全局变量时保护自己的数据。 2)可重入函数: 不为连续的调用持有静态数据。 不返回指向静态数据的指针;所有数据都由函数的调用者提供。 使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据。 如果必须访问全局变量,记住利用互斥信号量来保护全局变量。 绝不调用任何不可重入函数。 3)不可重入函数: 函数中使用了静态变量,无论是全局静态变量还是局部静态变量。 函数返回静态变量。 函数中调用了不可重入函数。 函数体内使用了静态的数据结构; 函数体内调用了malloc()或者free()函数; 函数体内调用了其他标准I/O函数。 函数是singleton中的成员函数而且使用了不使用线程独立存储的成员变量 。 总的来说,如果一个函数在重入条件下使用了未受保护的共享的资源,那么它是不可重入的。 4)示例 在多线程条件下,函数应当是线程安全的,进一步,更强的条件是可重入的。可重入函数保证了在多线程条件下,函数的状态不会出现错误。以下分别是一个不可重入和可重入函数的示例:
//c code static int tmp;
void func1(int* x, int* y){ tmp=*x; *x=*y; *y=tmp; }
void func2(int* x, int* y){ int tmp; tmp=*x; *x=*y; *y=tmp; }
func1是不可重入的,func2是可重入的。因为在多线程条件下,操作系统会在func1还没有执行完的情况下,切换到另一个线程中,那个线程可能再次调用func1,这样状态就错了。两者之间的关系:1、一个函数对于多个线程是可重入的,则这个函数是线程安全的。2、一个函数是线程安全的,但并不一定是可重入的。3、可重入性要强于线程安全性。比如:strtok函数是既不可重入的,也不是线程安全的。加锁的strtok不是可重入的,但线程安全。而strtok_r既是可重入的,也是线程安全的。(具体可以查看man手册)
可重入函数,是线程安全函数的一种。特点:当它们被多个线程调用时,不会引用任何共享数据,也就是不引用静态或全局变量。
在信号处理函数中,也要考虑函数可重入的情况。考虑到这样一种情况:如果进程正在执行malloc,在堆中分配了另外的存储空间,而此时由于捕捉到信号而执行信号处理程序,其中又调用了malloc,这时候可能会造成破坏,因为malloc通常为它分配的存储区维护一个链接表,而插入执行信号处理程序时,进程可能正在更改此链表。
函数不可重入,大多是因为:(1)使用了静态数据结构,(2)它们调用malloc()或free,(3)它们是标准I/O函数。标准I/O库的很多实现都以不可重入的方式使用全局数据结构(如errno变量)。
下图是信号处理中可以调用的重入函数。(来自<<UNIX环境高级编程>>)
至少要满足下面几条:
1、不在函数内部使用静态或全局数据2、不返回静态或全局数据,所有数据都由函数的调用者提供。3、使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据。4、如果必须访问全局变量,利用互斥机制来保护全局变量。5、不调用不可重入函数,malloc()或者free()函数,或者一些标准I/O函数。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
暂无简介
文章 0 评论 0
接受
发布评论
评论(3)
1)什么是可重入性?
可重入(reentrant)函数可以由多于一个任务并发使用,而不必担心数据错误。相反, 不可重入(non-reentrant)函数不能由超过一个任务所共享,除非能确保函数的互斥(或者使用信号量,或者在代码的关键部分禁用中断)。可重入函数可以在任意时刻被中断,稍后再继续运行,不会丢失数据。可重入函数要么使用本地变量,要么在使用全局变量时保护自己的数据。
2)可重入函数:
不为连续的调用持有静态数据。
不返回指向静态数据的指针;所有数据都由函数的调用者提供。
使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据。
如果必须访问全局变量,记住利用互斥信号量来保护全局变量。
绝不调用任何不可重入函数。
3)不可重入函数:
函数中使用了静态变量,无论是全局静态变量还是局部静态变量。
函数返回静态变量。
函数中调用了不可重入函数。
函数体内使用了静态的数据结构;
函数体内调用了malloc()或者free()函数;
函数体内调用了其他标准I/O函数。
函数是singleton中的成员函数而且使用了不使用线程独立存储的成员变量 。
总的来说,如果一个函数在重入条件下使用了未受保护的共享的资源,那么它是不可重入的。
4)示例
在多线程条件下,函数应当是线程安全的,进一步,更强的条件是可重入的。可重入函数保证了在多线程条件下,函数的状态不会出现错误。以下分别是一个不可重入和可重入函数的示例:
//c code
static int tmp;
void func1(int* x, int* y)
{
tmp=*x;
*x=*y;
*y=tmp;
}
void func2(int* x, int* y)
{
int tmp;
tmp=*x;
*x=*y;
*y=tmp;
}
func1是不可重入的,func2是可重入的。因为在多线程条件下,操作系统会在func1还没有执行完的情况下,切换到另一个线程中,那个线程可能再次调用func1,这样状态就错了。
两者之间的关系:
1、一个函数对于多个线程是可重入的,则这个函数是线程安全的。
2、一个函数是线程安全的,但并不一定是可重入的。
3、可重入性要强于线程安全性。
比如:strtok函数是既不可重入的,也不是线程安全的。加锁的strtok不是可重入的,但线程安全。而strtok_r既是可重入的,也是线程安全的。(具体可以查看man手册)
可重入函数,是线程安全函数的一种。特点:当它们被多个线程调用时,不会引用任何共享数据,也就是不引用静态或全局变量。
在信号处理函数中,也要考虑函数可重入的情况。
考虑到这样一种情况:如果进程正在执行malloc,在堆中分配了另外的存储空间,而此时由于捕捉到信号而执行信号处理程序,其中又调用了malloc,这时候可能会造成破坏,因为malloc通常为它分配的存储区维护一个链接表,而插入执行信号处理程序时,进程可能正在更改此链表。
函数不可重入,大多是因为:(1)使用了静态数据结构,(2)它们调用malloc()或free,(3)它们是标准I/O函数。标准I/O库的很多实现都以不可重入的方式使用全局数据结构(如errno变量)。
下图是信号处理中可以调用的重入函数。(来自<<UNIX环境高级编程>>)
至少要满足下面几条:
1、不在函数内部使用静态或全局数据
2、不返回静态或全局数据,所有数据都由函数的调用者提供。
3、使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据。
4、如果必须访问全局变量,利用互斥机制来保护全局变量。
5、不调用不可重入函数,malloc()或者free()函数,或者一些标准I/O函数。