这两天看了apue有关进程信号的部分,觉得未决状态这个词很是不一般,呵呵。一开始当我看到这个词,我不理解,什么意思呢,读了好几遍。不知道是书里面讲的晦涩难懂,还是脑子越来越不行了,就是没有搞明白。后来看到后面的例子,然后再回想一下,终于清楚了!下面记录一下吧。
定义:信号产生和传递之间的时间间隔内,称此信号是未决的;
简单的说就是:一个已经产生的信号,但是还没有传递给任何进程,此时该信号的状态就称为未决状态。
未决状态信号的产生主要是因为进程对此信号的阻塞。例如为进程产生一个选择为阻塞的信号,而且对该信号的动作是系统默认动作或捕捉该信号,则为该进程将此信号保持为未决状态,直到该进程对此信号解除了阻塞或者对此信号的动作改为忽略。
我们知道,进程的信号屏蔽字规定了要阻塞传送到该进程的信号集。当产生了一个该进程已阻塞的信号,系统会为该进程生成一个信号集(其实该信号集是一直存在的,不是产生阻塞信号时才生成的),并将该阻塞的信号保存在此信号集中即将此信号集对应的信号置为未决状态。可以通过调用sigpending()来返回该信号集。
下面看一个apue上的例子:
#include <stdio.h> #include <signal.h> #include <unistd.h> //信号处理函数 static void sig_quit(int sigo) { printf("caught SIGQUIT...\n"); //将SIGQUIT信号的处理方式恢复成系统默认的处理动作 if(signal(SIGQUIT, SIG_DFL) == SIG_ERR) printf("can't reset SIGQUIT"); } int main() { sigset_t newmask, oldmask, pendmask; //定义对信号SIGQUIT的捕捉 if(signal(SIGQUIT, sig_quit) == SIG_ERR) { printf("can't catch SIGQUIT...\n"); return 0; } sigemptyset(&newmask);//清空信号集中所有要屏蔽的信号 sigaddset(&newmask, SIGQUIT);//将信号集中SIGQUIT信号设置为屏蔽 //保存进程旧的信号屏蔽字,并设置新的信号屏蔽字即使进程屏蔽SIGQUIT信号 if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) { printf("SIG_BLOCK error...\n"); return 0; } sleep(5); //返回阻塞的未决状态信号集 if(sigpending(&pendmask) < 0) { printf("sigpending error...\n"); return 0; } //判断在sleep期间是否有未决状态信号SIGQUIT产生 if(sigismember(&pendmask, SIGQUIT)) printf("\nSIGQUIT pending\n"); //恢复进程的信号屏蔽字 if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) { printf("SIG_SETMASK error...\n"); return 0; } printf("SIGQUIT unblocked\n"); sleep(5); return 0; }
执行上面的程序:
$ ./program ^\ \\按下ctrl+\ SIGQUIT pending caught SIGQUIT... SIGQUIT unblocked ^\ \\再次按下ctrl+\ 退出
由上面程序的执行结果可以知道,当第一次sleep时,按下ctrl+\时产生SIGQUIT信号,由于进程对该信号已屏蔽,所以不会响应该信号,系统会把该信号保存起来,所以在调用sigpending()时,其中会有未决状态信号SIGQUIT。当对恢复进程的信号屏蔽字时,系统会把该未决信号发送给该进程,所以此时进程会调用信号处理函数输出:caught SIGQUIT。调用信号处理函数时,会终止进程的执行,当信号处理函数结束返回后,唤醒进程,最后输出:SIGQUIT unblocked。在最后sleep时,我又输入ctrl+\,因为上次捕捉到该信号时,已将此信号的处理方式设置成默认动作,所以这一次会直接退出。
Oct 4, 2012 21:31 @library