unix信号的问题

早期unix信号的问题
1. 信号可能会丢失:信号发生了进程却不知道
2. 信号控制力弱:
比如有时用户希望通知内核阻塞信号(不要忽略该信号,而是在其发生时记住它,然后在进程作好了准备时再恢复之)这种 阻塞信号的能力当时并不具备。
3. 信号被抓获的时候,信号处理程序会被重置为DFL。
4. 慢性系统调用被中断时,必须手工重启之。下面的代码便是个例子:
again:
if ( (n = read(fd, buff, BUFFSIZE)) < 0) {
if (errno == EINTR)
goto again; /* just an interrupted system call */
/* handle other errors */
}

注意:
1. 中断的是系统调用,绝非函数;只有由内核执行的系统调用才会被中断
2. 慢性系统调用: 指的是可能使进程永远阻塞的系统调用.
较新的Posix.1兼容的sigaction并不使它们自动再起动。但可以使用SA_RESTART选项,使内核再起动由该信号中断的系统调用。

信号被捕捉时执行的动作
进程捕捉到信号并继续执行时,它首先执行该信号处理函数中的指令。如果从信号处理
函数 返回(例如没有调用exit或longjmp),则继续执行在捕捉到信号时进程正在执行的正常指令序列(这类似于硬件中断发生时所做的)。

unix信号的问题

信号处理程序中对于errno的处理
考虑一个信号处理
函数 ,它恰好在main刚设置errno之后被调用。如果该信号处理程序调用read,则它可能更改errno的值,从而取代了刚由main设置的值。
作为一个通用规则,当在信号处理
函数 中调用上面列出的函数时,应当在其前保存,在其后恢复errno。(要了解经常被捕捉到的信号是SIGCHLD,其信号处理 函数 通常要调用一种wait函数,而各种wait函数都能改变errno)

可靠信号原语
1. 信号递送(delivery):
执行 信号处理函数(take action)
2. 信号未决(pending) :从信号产生(generation)到信号递送之间的时间间隔
3. 信号阻塞(blocked) :信号发生时不被递送,而是暂存并于稍后递送。(SIGKILL,SIGSTOP无法被阻塞)

信号被解除阻塞
1. 当一个被设定为阻塞的信号发生多次时,当该信号被解除
阻塞 时,大多数UNIX系统采用的动作是只递送该信号一次(虽然Posix.1允许系统递送该信号一次或多次。如果递送该信号多次,则称这些信号排了队)。
2. 多个被阻塞的不同信号发生,当信号被解除
阻塞 时,Posix.1并没有规定这些信号的递送顺序。但是Posix.1建议:与进程当前状态有关的信号,例如SIGSEGV在其他信号之前递送。

你可能感兴趣的:(unix)