转载:http://blog.youkuaiyun.com/youkuxiaobin/article/details/7544347
在早期的UNIX中信号是不可靠的,不可靠在这里指的是:信号可能丢失,一个信号发生了,但进程却可能一直不知道这一点。
现在Linux 在SIGRTMIN实时信号之前的都叫不可靠信号,这里的不可靠主要是不支持信号队列,就是当多个信号发生在进程中的时候(收到信号的速度超过进程处理的速度的时候),这些没来的及处理的信号就会被丢掉,仅仅留下一个信号。
可靠信号是多个信号发送到进程的时候(收到信号的速度超过进程处理信号的速度的时候),这些没来的及处理的信号就会排入进程的队列。等进程有机会来处理的时候,依次再处理,信号不丢失。
同过一个实例来说明 不可靠信号(SIGUSR1(10)) 、可靠信号SIGRTMIN(ubuntu上是34)丢失的情况
test.cpp
- /*
- * =====================================================================================
- *
- * Filename: test.cpp
- *
- * Description: reliable and unreliable signal test
- *
- * Version: 1.0
- * Created: 2012年05月07日 22时52分40秒
- * Revision: none
- * Compiler: gcc
- *
- * Author: LeoK,
- * Organization:
- *
- * =====================================================================================
- */
- #include <stdlib.h>
- #include <iostream>
- #include <signal.h>
- #include <stdio.h>
- #include <errno.h>
- using namespace std;
- int g_unreliable = 0;
- int g_reliable = 0;
- void signal_dispath(int signo)
- {
- if(signo == SIGUSR1)
- {
- cout<<"receving signal SIGUSR1"<<endl;
- g_unreliable++;
- }
- else if(signo == SIGRTMIN)
- {
- cout<<"receving signal SIGRTMIN"<<endl;
- g_reliable++;
- }
- }
- void output_myself()
- {
- cout<<"^^^^^^^^^^^^^^^^^^^^^^^^^^^"<<endl;
- cout<<"^^^^^^^ Hello World ^^^^^^^"<<endl;
- cout<<"^^^^^^^ I'm LeoK ^^^^^^^"<<endl;
- cout<<"^^^^^^^^^^^^^^^^^^^^^^^^^^^"<<endl;
- }
- int main(int argc, char** argv)
- {
- if(argc != 1)
- {
- cout<<"this program need not paramter"<<endl;
- return 0;
- }
- /* 每个程序的信息需要打印*/
- output_myself();
- if(signal(SIGUSR1, signal_dispath) == SIG_ERR)
- {
- perror("register SIGUSR1 signal failed");
- return -1;
- }
- if(signal(SIGRTMIN, signal_dispath) == SIG_ERR)
- {
- perror("register SIGRTMIN signal failed");
- return -1;
- }
- sigset_t set;
- sigset_t oset;
- /* 清除set中的信号,把这个set置为空 */
- sigemptyset(&set);
- /* 往set中添加SIGUSR1信号 */
- sigaddset(&set, SIGUSR1);
- /* 往set中添加SIGRTMIN信号 */
- sigaddset(&set, SIGRTMIN);
- if(sigprocmask(SIG_BLOCK, &set, &oset) == -1)
- {
- perror("set process signal to be set failed");
- return -1;
- }
- sleep(10);
- if(sigpending(&set) == -1)
- {
- perror("sigpending get signal mask failed");
- return -1;
- }
- /* 判断信号是不是在信号屏蔽字中 */
- /* SIGUSR1 */
- int ret = -1;
- if((ret = sigismember(&set, SIGUSR1)) == -1)
- {
- perror("sigismember test SIGUSR1 failed");
- return -1;
- }
- else if(ret == 0)
- {
- cout<<"SIGUSR1 signal exist not signal mask"<<endl;
- }
- else
- {
- cout<<"SIGUSR1 signal exist signal mask"<<endl;
- }
- /* SIGRTMIN */
- if((ret = sigismember(&set, SIGRTMIN)) == -1)
- {
- perror("sigismember test SIGRTMIN failed");
- return -1;
- }
- else if(ret == 0)
- {
- cout<<"SIGRTMIN signal exist not signal mask"<<endl;
- }
- else
- {
- cout<<"SIGRTMIN signal exist signal mask"<<endl;
- }
- /* 休眠100s */
- sleep(30);
- if(sigprocmask(SIG_SETMASK, &oset, NULL) == -1)
- {
- perror("set oldset failed");
- return -1;
- }
- cout<<"SIGUSR1: "<<g_unreliable<<endl;
- cout<<"SIGRTMIN: "<<g_reliable<<endl;
- output_myself();
- return 0;
- }
首先把信号SIGUSR1和SIGRTMIN这两个信号通过sigaddset这个函数加入是使用的set(类型sigset_t)这个信号集合中,通过sigprocmask把进程的信号屏蔽字设置为set这个集合,这个时候让进程睡眠(在这个时候对于SIGUSR1、SIGRTMIN这两个信号是阻塞的,来达到进程处理的速度低于信号发送的速度),在睡眠的时候,通过脚本如下:
usr.sh
- #/bin/bash
- i=0;
- for((i=0;i<20;i++));
- do kill -10 `pidof a.out`;done
- #/bin/bash
- i=0;
- for((i=0;i<20;i++));
- do kill -34 `pidof a.out`;done
最后的输出如下:
- leok@LeoK:~/APUE/10_test$ ./a.out
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- ^^^^^^^ Hello World ^^^^^^^
- ^^^^^^^ I'm LeoK ^^^^^^^
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- SIGUSR1 signal exist signal mask
- SIGRTMIN signal exist signal mask
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGRTMIN
- receving signal SIGUSR1
- SIGUSR1: 1
- SIGRTMIN: 20
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- ^^^^^^^ Hello World ^^^^^^^
- ^^^^^^^ I'm LeoK ^^^^^^^
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^