1_信号常常被叫做软中断,而且都是异步的。信号是可以在进程之间,内核与进程之间产生。
2_通过sigaction来设置一个信号的处理办法,通常有三种选择:
·信号发生时调用信号处理程序(signal handler),其中,有SIGKILL,SIGSTOP两个信号无法被捕捉。
·通过设置信号处理办法为SIG_ING来忽略信号,同样的,SIGKILL,SIGSTOP无法被忽略。
·通过设置信号处理办法为SIG_DFL来设置信号的缺省处理办法。
3_处理僵尸进程:设置僵尸进程的目的是维护子进程信息,以备父进程取回,僵尸子进程的父进程ID为1(init进程),init进程将称为这些僵尸进程的继父并负责清除。
建立一个信号处理程序来捕获SIGCHLD:
#include "unp.h"
void sig_chld(int signo)
{
pid_t pid;
int stat;
pid = wait(&stat);
printf("child %d terminated\n",pid);
return;
}
void sig_chld(int signo)
{
pid_t pid;
int stat;
pid = wait(&stat);
printf("child %d terminated\n",pid);
return;
}
这样,子进程终止,SIGCHLD递交到父进程时,父进程正阻塞于accept调用,函数sig_chld被调用,然后返回。由于该信号是在父进程处于慢系统调用(accept)时被捕获的,所以内核将使accept返回一个EINTR错误(被中断地系统调用),而父进程不处理此错误,所以终止。
4_当我们编写一个信号处理函数时,往往需要考虑在一个慢系统调用中捕获到该信号,当处理函数返回时,会遇到EINTR错误,我们需要对此有所准备。其中内核自动能够重启被中断地系统调用虽然可以但也会带来移植性的问题,因此我们往往用自己的方案完成这个工作:
for(;;)
{
clilen = sizeof(cliaddr);
if((connfd = accept(listenfd, (SA *)&cliaddr, &clilen)) < 0)
if(errno = EINTR)
continue;
else
err_sys("accept error");
}
{
clilen = sizeof(cliaddr);
if((connfd = accept(listenfd, (SA *)&cliaddr, &clilen)) < 0)
if(errno = EINTR)
continue;
else
err_sys("accept error");
}
注意我们调用的是accept而非Accept,这是由于我们需要自己的失败处理。