Linux可靠信号和不可靠信号

转载:http://blog.csdn.net/youkuxiaobin/article/details/7544347

在早期的UNIX中信号是不可靠的,不可靠在这里指的是:信号可能丢失,一个信号发生了,但进程却可能一直不知道这一点。

现在Linux 在SIGRTMIN实时信号之前的都叫不可靠信号,这里的不可靠主要是不支持信号队列,就是当多个信号发生在进程中的时候(收到信号的速度超过进程处理的速度的时候),这些没来的及处理的信号就会被丢掉,仅仅留下一个信号。

可靠信号是多个信号发送到进程的时候(收到信号的速度超过进程处理信号的速度的时候),这些没来的及处理的信号就会排入进程的队列。等进程有机会来处理的时候,依次再处理,信号不丢失。

同过一个实例来说明 不可靠信号(SIGUSR1(10)) 、可靠信号SIGRTMIN(ubuntu上是34)丢失的情况

test.cpp

[cpp]  view plain copy
  1. /* 
  2.  * ===================================================================================== 
  3.  * 
  4.  *       Filename:  test.cpp 
  5.  * 
  6.  *    Description:  reliable and unreliable signal test  
  7.  * 
  8.  *        Version:  1.0 
  9.  *        Created:  2012年05月07日 22时52分40秒 
  10.  *       Revision:  none 
  11.  *       Compiler:  gcc 
  12.  * 
  13.  *         Author:  LeoK,  
  14.  *   Organization:   
  15.  * 
  16.  * ===================================================================================== 
  17.  */  
  18. #include <stdlib.h>  
  19. #include <iostream>  
  20. #include <signal.h>  
  21. #include <stdio.h>  
  22. #include <errno.h>  
  23. using namespace std;  
  24. int g_unreliable = 0;  
  25. int g_reliable = 0;  
  26. void signal_dispath(int signo)  
  27. {  
  28.     if(signo == SIGUSR1)  
  29.     {  
  30.         cout<<"receving signal SIGUSR1"<<endl;  
  31.         g_unreliable++;  
  32.     }  
  33.     else if(signo == SIGRTMIN)  
  34.     {  
  35.         cout<<"receving signal SIGRTMIN"<<endl;  
  36.         g_reliable++;  
  37.     }  
  38. }  
  39. void output_myself()  
  40. {  
  41.     cout<<"^^^^^^^^^^^^^^^^^^^^^^^^^^^"<<endl;  
  42.     cout<<"^^^^^^^ Hello World ^^^^^^^"<<endl;  
  43.     cout<<"^^^^^^^ I'm  LeoK   ^^^^^^^"<<endl;  
  44.     cout<<"^^^^^^^^^^^^^^^^^^^^^^^^^^^"<<endl;  
  45. }  
  46. int main(int argc, char** argv)  
  47. {  
  48.     if(argc != 1)  
  49.     {  
  50.         cout<<"this program need not paramter"<<endl;  
  51.         return 0;  
  52.     }  
  53.     /* 每个程序的信息需要打印*/  
  54.     output_myself();  
  55.     if(signal(SIGUSR1, signal_dispath) == SIG_ERR)  
  56.     {  
  57.         perror("register SIGUSR1 signal failed");  
  58.         return -1;  
  59.     }  
  60.     if(signal(SIGRTMIN, signal_dispath) == SIG_ERR)  
  61.     {  
  62.         perror("register SIGRTMIN signal failed");  
  63.         return -1;  
  64.     }  
  65.   
  66.     sigset_t set;  
  67.     sigset_t oset;  
  68.     /*  清除set中的信号,把这个set置为空 */  
  69.     sigemptyset(&set);  
  70.     /*  往set中添加SIGUSR1信号 */  
  71.     sigaddset(&set, SIGUSR1);  
  72.     /*  往set中添加SIGRTMIN信号 */  
  73.     sigaddset(&set, SIGRTMIN);  
  74.     if(sigprocmask(SIG_BLOCK, &set, &oset) == -1)  
  75.     {  
  76.         perror("set process signal to be set failed");  
  77.         return -1;  
  78.     }  
  79.     sleep(10);  
  80.     if(sigpending(&set) == -1)  
  81.     {  
  82.         perror("sigpending get signal mask failed");  
  83.         return -1;  
  84.     }  
  85.     /*  判断信号是不是在信号屏蔽字中 */  
  86.     /*  SIGUSR1 */  
  87.     int ret = -1;  
  88.     if((ret = sigismember(&set, SIGUSR1)) == -1)  
  89.     {  
  90.         perror("sigismember test SIGUSR1 failed");  
  91.         return -1;  
  92.     }  
  93.     else if(ret == 0)  
  94.     {  
  95.         cout<<"SIGUSR1 signal exist not signal mask"<<endl;  
  96.     }  
  97.     else  
  98.     {  
  99.         cout<<"SIGUSR1 signal exist signal mask"<<endl;  
  100.     }  
  101.   
  102.     /*  SIGRTMIN */  
  103.     if((ret = sigismember(&set, SIGRTMIN)) == -1)  
  104.     {  
  105.         perror("sigismember test SIGRTMIN failed");  
  106.         return -1;  
  107.     }  
  108.     else if(ret == 0)  
  109.     {  
  110.         cout<<"SIGRTMIN signal exist not signal mask"<<endl;  
  111.     }  
  112.     else  
  113.     {  
  114.         cout<<"SIGRTMIN signal exist signal mask"<<endl;  
  115.     }  
  116.     /*  休眠100s */  
  117.     sleep(30);  
  118.     if(sigprocmask(SIG_SETMASK, &oset, NULL) == -1)  
  119.     {  
  120.         perror("set oldset failed");  
  121.         return -1;  
  122.     }  
  123.     cout<<"SIGUSR1:      "<<g_unreliable<<endl;  
  124.     cout<<"SIGRTMIN:     "<<g_reliable<<endl;  
  125.     output_myself();  
  126.     return 0;  
  127. }  
该程序的解释是

首先把信号SIGUSR1和SIGRTMIN这两个信号通过sigaddset这个函数加入是使用的set(类型sigset_t)这个信号集合中,通过sigprocmask把进程的信号屏蔽字设置为set这个集合,这个时候让进程睡眠(在这个时候对于SIGUSR1、SIGRTMIN这两个信号是阻塞的,来达到进程处理的速度低于信号发送的速度),在睡眠的时候,通过脚本如下:

usr.sh

[cpp]  view plain copy
  1. #/bin/bash  
  2. i=0;  
  3. for((i=0;i<20;i++));  
  4.     do kill -10 `pidof a.out`;done  
min.sh

[cpp]  view plain copy
  1. #/bin/bash  
  2. i=0;  
  3. for((i=0;i<20;i++));  
  4.     do kill -34 `pidof a.out`;done  
发送信号SIGUSR1 和SIGRTMIN给进程a.out(test.cpp编译后的可执行程序)

最后的输出如下:

[cpp]  view plain copy
  1. leok@LeoK:~/APUE/10_test$ ./a.out   
  2. ^^^^^^^^^^^^^^^^^^^^^^^^^^^  
  3. ^^^^^^^ Hello World ^^^^^^^  
  4. ^^^^^^^ I'm  LeoK   ^^^^^^^  
  5. ^^^^^^^^^^^^^^^^^^^^^^^^^^^  
  6. SIGUSR1 signal exist signal mask  
  7. SIGRTMIN signal exist signal mask  
  8. receving signal SIGRTMIN  
  9. receving signal SIGRTMIN  
  10. receving signal SIGRTMIN  
  11. receving signal SIGRTMIN  
  12. receving signal SIGRTMIN  
  13. receving signal SIGRTMIN  
  14. receving signal SIGRTMIN  
  15. receving signal SIGRTMIN  
  16. receving signal SIGRTMIN  
  17. receving signal SIGRTMIN  
  18. receving signal SIGRTMIN  
  19. receving signal SIGRTMIN  
  20. receving signal SIGRTMIN  
  21. receving signal SIGRTMIN  
  22. receving signal SIGRTMIN  
  23. receving signal SIGRTMIN  
  24. receving signal SIGRTMIN  
  25. receving signal SIGRTMIN  
  26. receving signal SIGRTMIN  
  27. receving signal SIGRTMIN  
  28. receving signal SIGUSR1  
  29. SIGUSR1:      1  
  30. SIGRTMIN:     20  
  31. ^^^^^^^^^^^^^^^^^^^^^^^^^^^  
  32. ^^^^^^^ Hello World ^^^^^^^  
  33. ^^^^^^^ I'm  LeoK   ^^^^^^^  
  34. ^^^^^^^^^^^^^^^^^^^^^^^^^^^  
来说明Linux可靠信号和不可靠信号的区别,不要认为不可靠的东西部能用,仅仅是不支持信号队列而已。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值