信号的生命周期

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>

void sig_quit(int signo);

int main() {
	if (signal(SIGQUIT, sig_quit) == SIG_ERR) {
		printf("can't catch sigquit\n");
		exit(0);
	}
	sigset_t newset, oldset, curset;
	sigfillset(&newset);
	if (sigprocmask(SIG_SETMASK, &newset, &oldset) < 0) {
		printf("call sigprocmask error\n");
		exit(0);
	}
	sleep(5);
	if (sigpending(&curset) < 0) {
		printf("call sigpending error\n");
		exit(0);
	}
	if (sigismember(&curset, SIGQUIT)) {
		printf("SIGQUIT is pending\n");
	} else {
		printf("wrong\n");
	}
	if (sigprocmask(SIG_SETMASK, &oldset, NULL) < 0) {
		printf("call sigpromask error\n");
		exit(0);
	}
	sleep(5);
	exit(0);
}

void sig_quit(int signo) {
	printf("sig_quit run\n");
	if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) {
		printf("can't catch SIG_QUIT\n");
		exit(0);
	}
}


信号生命周期:
    对于一个完整的信号生命周期(从信号发送到相应的处理函数执行完毕)来说,可以分为三个重要的阶段,这三个阶段由四个重要事件来刻画:1.信号诞生;2. 信号在进程中注册完毕;3.信号在进程中的注销完毕;4.信号处理函数执行完毕。相邻两个事件的时间间隔构成信号生命周期的一个阶段。
    下面阐述四个事件的实际意义:
1.信号"诞生"。信号的诞生指的是触发信号的事件发生(如检测到硬件异常、定时器超时以及调用信号发送函数kill()或sigqueue()等)。

2.信号在目标进程中"注册";
    进程的task_struct结构中有关于本进程中未决信号的数据成员:
struct sigpending pending;
struct sigpending
{
    struct sigqueue *head, **tail;
    sigset_t signal;
};
第一、第二个成员分别指向一个sigqueue类型的结构链(称之为"未决信号信息链")的首尾,第三个成员是进程中所有未决信号集,信息链中的每个sigqueue结构体刻画一个特定信号所携带的信息,并指向下一个sigqueue结构:
struct sigqueue
{
    struct sigqueue *next;
    siginfo_t info;
};
    信号在进程中注册指的就是信号值加入到进程的未决信号集中(sigpending结构的第二个成员sigset_t signal),并且信号所携带的信息被保留到未决信号信息链的某个sigqueue结构中。只要信号在进程的未决信号集中,表明进程已经知道这些信号的存在,但还没来得及处理,或者该信号被进程阻塞。
注:
    当一个实时信号发送给一个进程时,不管该信号是否已经在进程中注册,都会被再注册一次,因此,信号不会丢失,因此,实时信号又叫做"可靠信号"。这意味着同一个实时信号可以在同一个进程的未决信号信息链中占有多个sigqueue结构(进程每收到一个实时信号,都会为它分配一个结构来登记该信号信息,并把该结构添加在未决信号链尾,即所有诞生的实时信号都会在目标进程中注册);
当一个非实时信号发送给一个进程时,如果该信号已经在进程中注册,则该信号将被丢弃,造成信号丢失。因此,非实时信号又叫做"不可靠信号"。这意味着同一个非实时信号在进程的未决信号信息链中,至多占有一个sigqueue结构(一个非实时信号诞生后,(1)、如果发现相同的信号已经在目标结构中注册,则不再注册,对于进程来说,相当于不知道本次信号发生,信号丢失;(2)、如果进程的未决信号中没有相同信号,则在进程中注册自己)。

3.信号在进程中的注销。在目标进程执行过程中,会检测是否有信号等待处理(每次从系统空间返回到用户空间时都做这样的检查)。如果存在未决信号等待处理且该信号没有被进程阻塞,则在运行相应的信号处理函数前,进程会把信号在未决信号链中占有的结构卸掉。是否将信号从进程未决信号集中删除对于实时与非实时信号是不同的。对于非实时信号来说,由于在未决信号信息链中最多只占用一个sigqueue结构,因此该结构被释放后,应该把信号在进程未决信号集中删除(信号注销完毕);而对于实时信号来说,可能在未决信号信息链中占用多个sigqueue结构,因此应该针对占用gqueue结构的数目区别对待:如果只占用一个sigqueue结构(进程只收到该信号一次),则应该把信号在进程的未决信号集中删除(信号注销完毕)。否则,不在进程的未决信号集中删除该信号(信号注销完毕)。进程在执行信号相应处理函数之前,首先要把信号在进程中注销。

4.信号生命终止。进程注销信号后,立即执行相应的信号处理函数,执行完毕后,信号的本次发送对进程的影响彻底结束。

 

 


posted on 2012-06-25 20:40  java课程设计  阅读(292)  评论(0编辑  收藏  举报

导航