liunx中可重入和不可重入函数
2013-11-06 08:32
288 查看
可重入函数
可重入函数(即可以被中断的函数)可以被一个以上的任务调用,而不担心数据破坏。可重入函数在任何时候都可以被中断,而一段时间之后又可以恢复运行,而相应的数据不会破坏或者丢失。
可重入函数使用的变量有两种情况:
1.使用局部变量,变量保存在CPU寄存器中或者堆栈中;
2.使用全局变量,但是这时候要注意保护全局变量(防止任务中断后被其它任务改变变量)。
分析:上面的函数用于字符串复制,而参数是存放在堆栈中的,故而改函数可以被多任务调用,而不必担心各个任务调用期间会互相破坏对方的指针。
基本上下面的函数都是不可重入的:
1.函数内使用了静态的数据。
2.函数内使用了malloc()或者free()函数的。
3.函数内调用了标准的I/O函数的。
分析:该函数中的全局变量temp是的函数变成了一个不可重入的函数,因为在多任务系统中,假如在任务1中调用swap函数,而程序执行到(1)处时被中断,进而执行其它的任务2,而刚好任务2也调用了swap函数,则temp里存的值则会被任务2改变。从而回到任务1被中断处继续执行的时候,temp里存的值已经不再是原来存的temp值了,进而产生了错误。 常用的可重入函数的方法有:1.不要使用全局变量,防止别的代码覆盖这些变量的值。2.调用这类函数之前先关掉中断,调用完之后马上打开中断。防止函数执行期间被中断进入别的任务执行。3.使用信号量(互斥条件)。总之:要保证中断是安全的
不可重入函数
在多任务系统下,中断可能在任务执行的任何时间发生;如果一个函数的执行期间被中断后,到重新恢复到断点进行执行的过程中,函数所依赖的环境没有发生改变,那么这个函数就是可重入的,否则就不可重入。
在中断前后不都要保存和恢复上下文吗,怎么会出现函数所依赖的环境发生改变了呢?
我们知道中断时确实保存一些上下文,但是仅限于返回地址,cpu寄存器等之类的少量上下文,而函数内部使用的诸如全局或静态变量,buffer等并不在保护之列,所以如果这些值在函数被中断期间发生了改变,那么当函数回到断点继续执行时,其结果就不可预料了。
满足下面条件之一的多数是不可重入函数:
(1)使用了静态数据结构;
(2)调用了malloc或free;
(3)调用了标准I/O函数;
(4)进行了浮点运算.
malloc/free是不可重入的,它们使用了全局变量来指向空闲区;标准I/O库的很多实现都使用了全局数据结构; 许多的处理器/编译器中,浮点一般都是不可重入的 (浮点运算大多使用协处理器或者软件模拟来实现)。
在信号处理程序及多线程编程时,要特别注意。
考虑这种情况:
1) 信号处理程序A内外都调用了同一个不可重入函数B;B在执行期间被信号打断,进入A (A中调用了B),完事之后返回B被中断点继续执行,这时B函数的环境可能改变,其结果就不可预料了。
2) 多线程共享进程内部的资源,如果两个线程A,B调用同一个不可重入函数F,A线程进入F后,线程调度,切换到B,B也执行了F,那么当再次切换到线程A时,其调用F的结果也是不可预料的。
在信号处理程序中即使调用可重入函数也有问题要注意。作为一个通用的规则,当在信号处理程序中调用可重
入函数时,应当在其前保存errno,并在其后恢复errno。(要了解经常被捕捉到的信号是SIGCHLD,其信号处理程序通常要调用一种wait函数,而各种wait函数都能改变errno。)
下面稍微写一个具体的例子来区别可重入函数和不可重入函数:
可重入函数(即可以被中断的函数)可以被一个以上的任务调用,而不担心数据破坏。可重入函数在任何时候都可以被中断,而一段时间之后又可以恢复运行,而相应的数据不会破坏或者丢失。
可重入函数使用的变量有两种情况:
1.使用局部变量,变量保存在CPU寄存器中或者堆栈中;
2.使用全局变量,但是这时候要注意保护全局变量(防止任务中断后被其它任务改变变量)。
void strcpy(*dest,*src) { while(* dest++ = *src ++){;} *dest = NUL; }
分析:上面的函数用于字符串复制,而参数是存放在堆栈中的,故而改函数可以被多任务调用,而不必担心各个任务调用期间会互相破坏对方的指针。
基本上下面的函数都是不可重入的:
1.函数内使用了静态的数据。
2.函数内使用了malloc()或者free()函数的。
3.函数内调用了标准的I/O函数的。
int temp; void swap(int *ex1,int *ex2) { temp = *ex1; //(1) *ex1 = *ex2; *ex2 = temp; }
分析:该函数中的全局变量temp是的函数变成了一个不可重入的函数,因为在多任务系统中,假如在任务1中调用swap函数,而程序执行到(1)处时被中断,进而执行其它的任务2,而刚好任务2也调用了swap函数,则temp里存的值则会被任务2改变。从而回到任务1被中断处继续执行的时候,temp里存的值已经不再是原来存的temp值了,进而产生了错误。 常用的可重入函数的方法有:1.不要使用全局变量,防止别的代码覆盖这些变量的值。2.调用这类函数之前先关掉中断,调用完之后马上打开中断。防止函数执行期间被中断进入别的任务执行。3.使用信号量(互斥条件)。总之:要保证中断是安全的
不可重入函数
在多任务系统下,中断可能在任务执行的任何时间发生;如果一个函数的执行期间被中断后,到重新恢复到断点进行执行的过程中,函数所依赖的环境没有发生改变,那么这个函数就是可重入的,否则就不可重入。
在中断前后不都要保存和恢复上下文吗,怎么会出现函数所依赖的环境发生改变了呢?
我们知道中断时确实保存一些上下文,但是仅限于返回地址,cpu寄存器等之类的少量上下文,而函数内部使用的诸如全局或静态变量,buffer等并不在保护之列,所以如果这些值在函数被中断期间发生了改变,那么当函数回到断点继续执行时,其结果就不可预料了。
满足下面条件之一的多数是不可重入函数:
(1)使用了静态数据结构;
(2)调用了malloc或free;
(3)调用了标准I/O函数;
(4)进行了浮点运算.
malloc/free是不可重入的,它们使用了全局变量来指向空闲区;标准I/O库的很多实现都使用了全局数据结构; 许多的处理器/编译器中,浮点一般都是不可重入的 (浮点运算大多使用协处理器或者软件模拟来实现)。
在信号处理程序及多线程编程时,要特别注意。
考虑这种情况:
1) 信号处理程序A内外都调用了同一个不可重入函数B;B在执行期间被信号打断,进入A (A中调用了B),完事之后返回B被中断点继续执行,这时B函数的环境可能改变,其结果就不可预料了。
2) 多线程共享进程内部的资源,如果两个线程A,B调用同一个不可重入函数F,A线程进入F后,线程调度,切换到B,B也执行了F,那么当再次切换到线程A时,其调用F的结果也是不可预料的。
在信号处理程序中即使调用可重入函数也有问题要注意。作为一个通用的规则,当在信号处理程序中调用可重
入函数时,应当在其前保存errno,并在其后恢复errno。(要了解经常被捕捉到的信号是SIGCHLD,其信号处理程序通常要调用一种wait函数,而各种wait函数都能改变errno。)
下面稍微写一个具体的例子来区别可重入函数和不可重入函数:
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <string.h> #include <unistd.h> #include <sys/types.h> int a=0; void handler1(int num,siginfo_t * info,void *no_used) { a=5; printf("before a is %d\n",a); kill(getpid(),6); printf("after a is %d\n",a); return ; } void handler2(int num,siginfo_t * info,void *no_used) { printf("set a is 6\n"); a=6; return ; } int main() { struct sigaction act; memset(&act,0x00,sizeof(act)); alarm(3); act.sa_handler=handler1; sigaction(SIGALRM,&act,NULL); act.sa_handler=handler2; sigaction(6,&act,NULL); printf("%d wait a signal....\n",getpid()); getchar(); return 0; } 在这里一直等待着时间信号触发,其输出结果为 [2771]wait a signal.... before kill a = 5 set a to 6 after kill a = 6
相关文章推荐
- 重入与不可重入函数
- [学习笔记]信号处理函数遇上可重入和不可重入函数
- 不可重入函数和线程安全
- 操作系统--可重入函数和不可重入函数
- 什么是可重入函数和不可重入函数
- 【Linux系统编程】可重入函数和不可重入函数
- 不可重入的函数
- 信号编程之信号发送及信号处理函数遇到不可重入函数
- 什么是可重入函数和不可重入函数
- 可重入函数和不可重入函数
- 重入和不可重入函数概念浅析
- 不可重入函数与线程安全函数
- 多线程使用不可重入函数localtime要互斥
- 可重入函数和不可重入函数
- 什么是可重入函数和不可重入函数(转)
- 什么是可重入函数和不可重入函数
- 可重入和不可重入函数
- 不可重入函数getpwnam的问题
- Linux中的可重入函数和不可重入函数
- 再次深入分析不可重入函数---请小心使用localtime函数