信号之可重入函数

  为了增强程序的稳定性,在信号处理函数中应使用可重入函数。

  可重入函数:指的是一个可以被多个任务调度的过程,任务在调度中不必担心数据是否出错。因为进程在收到信号后,就将跳转到信号处理程序去执行。如果信号处理程序中使用了不可重入函数,那么信号处理函数可能会修改原进程中不应被修改的数据,这样进程从信号处理函数中返回接着执行时,可能会出现不可预料后果。不可重入函数在信号处理程序中被视为不安全函数。

  可重入函数主要用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误;而不可重入的函数由于使用了一些系统资源,比如全局变量区,中断向量表等,所以它如果被中断的话,可能会出现问题,这类函数是不能运行在多任务环境下的。

man 7 signal查看可重入。

满足下列条件的函数多数是不可再入的:
1、使用静态数据结构或者全局变量,如getlogin(),gmtime(),getgrgid(),getgrnam()等;
2、函数实现时,调用了malloc()或者free()函数等;
3、实现时使用了标准IO函数。

 1 #include<unistd.h>
 2 #include<sys/types.h>
 3 #include<sys/stat.h>
 4 #include<fcntl.h>
 5 #include<stdlib.h>
 6 #include<stdio.h>
 7 #include<errno.h>
 8 #include<string.h>
 9 
10 #include<signal.h>
11 #define ERR_EXIT(m)\
12     do\
13     {\
14         perror(m);\
15         exit(EXIT_FAILURE);\
16     }while(0)  //宏要求一条语句
17 typedef struct{
18     int a;
19     int b;
20 }TEST;
21 TEST g_data;
22 void handler(int sig);
23 int main(int argc,char*argv[])
24 {
25     
26     TEST zeros={0,0};
27     TEST ones={1,1};
28     if(signal(SIGALRM,handler)==SIG_ERR)
29         ERR_EXIT("signal error");
30     g_data=zeros;
31     alarm(1);//过一秒发送一个SIGALRM信号
32     for(;;)
33     {
34         g_data=zeros;
35         g_data=ones;
36     }
37     return 0;
38 }
//正常想法:要么输出 0 0 ;要么输出 1 1.m
39 void unsafe_fun()//导致不可重入原因:访问全局变量(程序与信号处理函数共享) 40 { 41 printf("%d %d\n",g_data.a,g_data.b);//输出结果可能为0 1或 1 0 可能在for循环中g_data.a=zeros.a g_data.b=zeros.b之间1秒到了,不是原子操作 42 } 43 void handler(int sig)//sig是signum 44 { 45 unsafe_fun(); 46 alarm(1);//每隔一秒发送一次。,间接递归 han-alrm-han 47 }

 

posted on 2018-01-27 16:49  wsw_seu  阅读(222)  评论(0编辑  收藏  举报

导航