华晨宇谈许晴变黑脸:在linux进程中的信号屏蔽

来源:百度文库 编辑:中财网 时间:2024/05/03 10:41:07

在linux进程中的信号屏蔽

分类: linux 2010-01-11 14:28 900人阅读 评论(0) 收藏 举报

       原创文章,转载请注明出处,谢谢!       
       作者:清林,博客名:飞空静渡

 

在linux的进程中可以接收到各种的信号,并且如果你不对信号进行处理,linux中的进程就会采用默认的处理方式处理,比如ctrl-c的信号,进程对它的处理就是终止进程的执行。

在linux中,我们也可以在进程中屏蔽掉某些信号,使进程不去处理这些信号,但其中的SIGKILL和SIGSTOP是不能被阻塞的。

在这里先介绍几个信号的函数:

 

    int sigempty(sigset_t *set);                 // 清空信号集set

    int sigfillset(sigset_t *set);                   // 填满信号集,即让set包含所有的信号

 

    int sigaddset(sigset_t *set, int signo);  // 在set中增加signo信号

 

    int sigdelset(sigset_t *set, int signo);   // 在set中去掉signo信号

    int sigismember(sigset_t *set, int signo); // 信号signo是否在信号集set中

    int sigprocmask(int how, const sigset_t set, sigset_t oset); // 若oset非空,则进程的当前信号屏蔽字通过oset返回,若set是一个非空指针,着参数how指示如何修改当前信号的屏蔽字,how可以取三个值:

    SIG_BLOCK:增加一个信号。

    SIG_UNBLOCK:解除一个信号。

    SIG_SETMASK:该进程的信号将被set信号集取代。

 

    int sigpengding(sigset_t *set);  // 该函数返回信号集,该信号通过set参数返回。

以上函数都在#include 头文件中。

 

下面用《unix环境高级编程》里的一个例子说明一下,代码有所修改,先看代码(main.c,里面有个人对代码的注释):

view plaincopy to clipboardprint?

  1. #include    
  2. #include    
  3. #include    
  4. static void sig_quit(int);  
  5. int   
  6. main(void)  
  7. {  
  8.     sigset_t newmask, oldmask, pendingmask;  
  9.     //设置对信号SIGQUIT的处理函数   
  10.     if (signal(SIGQUIT, sig_quit) == SIG_ERR)  
  11.     {  
  12.         fprintf(stderr, "can't catch SIGQUIT/n");  
  13.         exit(1);  
  14.     }  
  15.     //设置一个空的信号集   
  16.     sigemptyset(&newmask);  
  17.     sigaddset(&newmask, SIGQUIT); // 在这个信号集中增加SIGQUIT信号   
  18.       
  19.     //在当前进程中增加newmask信号集作为屏蔽信号集,oldmask返回当前进程的信号集   
  20.     if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)   
  21.     {  
  22.         fprintf(stderr, "SIG_BLOCK error/n");  
  23.         exit(1);  
  24.     }  
  25.     sleep(5);  
  26.     //返回当前进程信号集   
  27.     if (sigpending(&pendingmask) < 0)  
  28.     {  
  29.         fprintf(stderr, "sigpending error/n");  
  30.         exit(1);  
  31.     }  
  32.     //检查SIGQUIT信号是否在当前信号集中   
  33.     if (sigismember(&pendingmask, SIGQUIT))  
  34.         printf("/nSIGQUIT pending/n");  
  35.     //恢复进程的信号集   
  36.     if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)  
  37.     {  
  38.         fprintf(stderr, "SIG_SETMASK error/n");  
  39.         exit(1);  
  40.     }  
  41.     printf("SIGQUIT unblocked/n");  
  42.     sleep(5);  
  43.     exit(0);  
  44. }  
  45. static void sig_quit(int signo)  
  46. {  
  47.     printf("caught SIGQUIT/n");  
  48.     //恢复进程对SIGQUIT的默认处理   
  49.     if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)  
  50.     {  
  51.         fprintf(stderr, "can't reset SIGQUIT/n");  
  52.         exit(0);  
  53.     }  
  54. }  

 

编译: gcc main.c

生成:a.out

运行:./a.out

输出如下(ubuntu9.10):

^/                          
SIGQUIT pending    
caught SIGQUIT      
SIGQUIT unblocked
^/退出                   

 

下面解释一下输出:

^/                                在第一次sleep(5)的5秒中内产生信号一次(按ctrl+/)
SIGQUIT pending          从sleep返回后
caught SIGQUIT           在信号处理函数中
SIGQUIT unblocked       从sigprocmask返回后
^/退出                          再次产生信号

我们对着程序来看下输出。

在我们设置SIGQUIT屏蔽字和恢复进程的信号集这段时间,我们产生的SIGQUIT信号,我们的进程并没去处理,所以输出了SIGQUIT pending 。

在我们恢复进程的信号集后,我们进程就扑捉到了我们刚才产生的信号,因而就输出了caught SIGQUIT,在sig_quit函数中,我们恢复了SIGQUIT的默认处理方式(即终止进程运行),进程当我们再次产生SIGQUIT信号,进程就退出了。

 

当我们产生进程时,一些unix系统会对进程中要处理的信号进行排队,我们的进程会对信号队列中的信号进行处理。我们再运行一下刚才的程序,在第一次sleep(5)的5秒中内产生信号10次信号,看下会怎么样,下面是我的输出:

^/^/^/^/^/^/^/^/^/^/     
SIGQUIT pending                  
caught SIGQUIT                  
SIGQUIT unblocked               
^/退出                              

 

下面解释一下输出:

^/^/^/^/^/^/^/^/^/^/   在第一次sleep(5)的5秒中内产生信号10次信号
SIGQUIT pending               从sleep返回后
caught SIGQUIT                从sigprocmask返回后 
SIGQUIT unblocked           从sigprocmask返回后
^/退出                              再次产生信号

 

这里可以看到linux系统对没有对信号进行排队,产生10次信号,只处理一次。

 

在上面的例子中,我们用signal函数来指定信号的处理函数,用sigprocmask来指定信号屏蔽字,其实这些都可以在一个函数中解决,它就是sigaction,推荐使用sigaction函数。

 

 http://blog.csdn.net/fjb2080/article/details/5174306