Linux 实时信号 非实时信号
实时信号之所以是可靠的,因为在进程阻塞该信号的时间内,发给该进程的所有实时信号会排队,而非实时信号则会合并为一个信号。早期的kill函数只能向特定的进程发送一个特定的信号,并且早期的信号处理函数也不能接受附加数据。siqueue和sigaction解决了这个问题。平时没有有机会使用实时信号,所以想体验下它的排队特性。 下面这个例子中,进程先屏蔽SIGINT和SIGRTMIN两个
实时信号之所以是可靠的,因为在进程阻塞该信号的时间内,发给该进程的所有实时信号会排队,而非实时信号则会合并为一个信号。
早期的kill函数只能向特定的进程发送一个特定的信号,并且早期的信号处理函数也不能接受附加数据。siqueue和sigaction解决了这个问题。平时没有有机会使用实时信号,所以想体验下它的排队特性。
下面这个例子中,进程先屏蔽SIGINT和SIGRTMIN两个信号,其中SIGINT是非实时信号,而SIGRTMIN为实时信号,接着进程睡眠,睡眠完成之后再接触对这两个信号的屏蔽,此时可以比较对两种信号的处理方式是否一样。
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
void sig_handler(int,siginfo_t*,void*);
int main(int argc,char**argv)
{
struct sigaction act;
sigset_t newmask, oldmask;
int rc;
sigemptyset(&newmask);
//往信号集中添加一个非实时信号
sigaddset(&newmask, SIGINT);
//往信号集中添加一个实时信号
sigaddset(&newmask, SIGRTMIN);
//屏蔽实时信号SIGRTMIN
sigprocmask(SIG_BLOCK, &newmask, &oldmask);
act.sa_sigaction = sig_handler;
act.sa_flags = SA_SIGINFO;
if(sigaction(SIGINT, &act, NULL) < 0)
{
printf("install sigal error\n");
}
if(sigaction(SIGRTMIN, &act, NULL) < 0)
{
printf("install sigal error\n");
}
printf("pid = %d\n", getpid());
//进程睡眠,在此时间内的发给该进程的所有实时信号
//将排队,不会有信号丢失
sleep(20);
//解除对SIGRTMIN信号的屏蔽
//信号处理函数将会被调用
sigprocmask(SIG_SETMASK, &oldmask, NULL);
return 0;
}
void sig_handler(int signum,siginfo_t *info,void *myact)
{
if(signum == SIGINT)
printf("Got a common signal\n");
else
printf("Got a real time signal\n");
}
将程序编译好之后,再开一个终端用于发送实时信号。
ecy@ecy-geek:~/pthreads$ ./sigqueue_receive
pid = 8871
进程开始睡眠……
在新的终端输入:
ecy@ecy-geek:~/pthreads$ kill -SIGRTMIN 8871
ecy@ecy-geek:~/pthreads$ kill -SIGRTMIN 8871
ecy@ecy-geek:~/pthreads$ kill -SIGRTMIN 8871
ecy@ecy-geek:~/pthreads$ kill -SIGRTMIN 8871
连续发送四个SIGRTMIN,接着回到之前的终端,连续四次按下"ctrl+c"。
^C^C^C^C
最后进程终于醒来,整个输出如下:
pid = 8871
^C^C^C^CGot a real time signal
Got a real time signal
Got a real time signal
Got a real time signal
Got a common signal
果然接受到四个实时信号,并且四次调用了信号处理函数,而对于SIGINT,虽然也按下了四次"ctrl+c",但是进程对其只做一次处理。我发现这儿有个细节有点意思,这个例子中是先发实时信号后发非实时信号,所以信号处理函数先处理实时信号,如果只是按照顺序注册信号的话,这很好理解,但是换一下,先按下了四次"ctrl+c"然后使用kill发四次实时信号,结果发现输出的结果仍然一样,这就有点怪了,这说明实时信号的优先级比非实时信号要高,内核每个进程的信号组成一个双向链表,实时信号插入的时候就不是随便插在尾部了。哎,不懂内核什么都要靠猜测,不爽~~在网上找到这样一段话:
更多推荐
所有评论(0)