Linux环境编程之信号(二):不可靠信号、中断的系统调用、可重入函数

时间:2021-11-29 14:45:08

(一)不可靠信号

对前面说的信号,是不可靠的,不可靠指的是信号可能会丢失:一个信号发生了,但进程却可能一直不知道这一点。另外,进程对信号的控制能力有限,只能捕捉信号或忽略它。有时用户希望通知内核阻塞一个信号:不要忽略它,在其发生时记住它,然后在进程做好准备时再通知它。这种阻塞信号的能力并不具备。

之前的版本中村咋一个问题:在进程每次接到信号对其进行处理时,随即将该信号动作复位为默认值。另一个问题是,在进程不希望某种信号发生时,它不能关闭该信号。进程能做的一切就是忽略该信号。

(二)中断的系统调用

如果进程在执行一个低速系统调用而阻塞期间捕捉到一个信号,则该系统调用就被中断不再继续执行。该系统调用返回出错,其errno被设置为EINTR。这样处理的理由是:因为一个信号发生了,进程捕捉到了它,这意味着已经发生了某种事情,所以是个应当唤醒阻塞的系统调用的好机会。

为了支持这种特性,将系统调用分成两类:低速系统调用和其他系统调用。低速系统调用时可能会使进程永远阻塞的一类系统调用。与被中断的系统调用相关的问题是必须显示地处理出错返回。典型的代码如下:

again:
if((n = read(fd, buf, BUFFSIZE)) < 0){
if(errno == EINTR)
goto again;
}
为了帮助应用程序使其不必处理被中断的系统调用,引入了某些被中断系统调用的自动重启动。引入自动重启动的一个理由是:有时用户并不知道所使用的输入、输出设备时否是低速设备。如果我们编写的程序可以用交互方式运行,则它可能读写低速终端设备。如果在程序中捕捉信号,而且系统并不提供重启动功能,则对每次读、写系统调用都要进行是否出错返回的测试,如果是被中断的,则再调用读、写系统调用。

(三)可重入函数

进程捕捉到信号并对其进行处理时,进程正在执行的指令序列就被信号处理程序临时中断,它首先执行该信号处理程序中的指令。如果从信号处理程序返回,则继续执行在捕捉到信号时进程正在执行的正常指令序列。