我们需要先定义一些在讨论信号时会用到的术语。首先,当造成信号的事件发生时,为进程产生一个信号(或向一个进程发送一个信号)。事件可以是硬件异常(如除以 0)、软件条件(如alarm 定时器超时)、终端产生的信号或调用kill 函数。当一个信号产生时,内核通常在进程表中以某种形式设置一个标志。

当对信号采取了这种动作时,我们说向进程递送了一个信号。在信号产生(generation)和递送(delivery)之间的时间间隔内,称信号是未决的(pending)。

进程可以选用“阻塞信号递送”。

如果为进程产生了一个阻塞的信号,而且对该信号的动作是系统默认动作或捕捉该信号,则为该进程将此信号保持为未决状态,直到该进程对此信号解除了阻塞,或者将对此信号的动作更改为忽略。

内核在递送一个原来被阻塞的信号给进程时(而不是在产生该信号时),才决定对它的处理方式。

于是进程在信号递送给它之前仍可改变对该信号的动作。进程调用sigpending函数(见10.13节)来判定哪些信号是设置为阻塞并处于未决状态的。

如果在进程解除对某个信号的阻塞之前,这种信号发生了多次,那么将如何呢?POSIX.1允许系统递送该信号一次或多次。如果递送该信号多次,则称这些信号进行了排队。但是除非支持POSIX.1实时扩展,否则大多数UNIX并不对信号排队,而是只递送这种信号一次。

SUSv4 中,实时信号功能已经移至基础规范的实时扩展部分。随着时间的推移,更多的系统即使不支持实时扩展,也会支持信号排队。我们将在10.20节中进一步讨论排队信号。

SVR2 的手册页称,在进程执行 SIGCLD 信号处理程序期间,该信号是用排队方式处理的,虽然在概念层次这可能是真的,但实际并非如此。内核是按照 10.7 节中所述方式产生此信号。SVR3的手册页对此做了修改,它指明在进程执行SIGCLD信号处理程序期间,忽略SIGCLD信号。SVR4手册页删除了有关部分。

AT&T[1990e]中的SVR4 sigaction(2)手册页称SA_SIG-INFO标志(见图10-16)使信号可靠地排队,这是不正确的。表面上内核部分地实现了此功能,但在 SVR4 中并不起作用。令人不可思议的是,SVID(System V接口定义)对这种可靠队列并未做同样的声明。

如果有多个信号要递送给一个进程,那将如何呢?POSIX.1并没有规定这些信号的递送顺序。但是POSIX.1基础部分建议:在其他信号之前递送与进程当前状态有关的信号,如SIGSEGV。

每个进程都有一个信号屏蔽字(signal mask),它规定了当前要阻塞递送到该进程的信号集。对于每种可能的信号,该屏蔽字中都有一位与之对应。对于某种信号,若其对应位已设置,则它当前是被阻塞的。进程可以调用sigprocmask(在10.12节中说明)来检测和更改其当前信号屏蔽字。

信号编号可能会超过一个整型所包含的二进制位数,因此POSIX.1 定义了一个新数据类型sigset_t,它可以容纳一个信号集。例如,信号屏蔽字就存放在其中一个信号集中。10.11节将说明对信号集进行操作的5个函数。

results matching ""

    No results matching ""