(一)不可靠信号
对前面说的信号,是不可靠的,不可靠指的是信号可能会丢失:一个信号发生了,但进程却可能一直不知道这一点。另外,进程对信号的控制能力有限,只能捕捉信号或忽略它。有时用户希望通知内核阻塞一个信号:不要忽略它,在其发生时记住它,然后在进程做好准备时再通知它。这种阻塞信号的能力并不具备。
之前的版本中村咋一个问题:在进程每次接到信号对其进行处理时,随即将该信号动作复位为默认值。另一个问题是,在进程不希望某种信号发生时,它不能关闭该信号。进程能做的一切就是忽略该信号。
(二)中断的系统调用
如果进程在执行一个低速系统调用而阻塞期间捕捉到一个信号,则该系统调用就被中断不再继续执行。该系统调用返回出错,其errno被设置为EINTR。这样处理的理由是:因为一个信号发生了,进程捕捉到了它,这意味着已经发生了某种事情,所以是个应当唤醒阻塞的系统调用的好机会。
为了支持这种特性,将系统调用分成两类:低速系统调用和其他系统调用。低速系统调用时可能会使进程永远阻塞的一类系统调用。与被中断的系统调用相关的问题是必须显示地处理出错返回。典型的代码如下:
again:为了帮助应用程序使其不必处理被中断的系统调用,引入了某些被中断系统调用的自动重启动。引入自动重启动的一个理由是:有时用户并不知道所使用的输入、输出设备时否是低速设备。如果我们编写的程序可以用交互方式运行,则它可能读写低速终端设备。如果在程序中捕捉信号,而且系统并不提供重启动功能,则对每次读、写系统调用都要进行是否出错返回的测试,如果是被中断的,则再调用读、写系统调用。
if((n = read(fd, buf, BUFFSIZE)) < 0){
if(errno == EINTR)
goto again;
}
(三)可重入函数
进程捕捉到信号并对其进行处理时,进程正在执行的指令序列就被信号处理程序临时中断,它首先执行该信号处理程序中的指令。如果从信号处理程序返回,则继续执行在捕捉到信号时进程正在执行的正常指令序列。