--------------------------------------------------------------
信号概念
<signal.h>
每个信号都有一个名字,这些名字都以三个字符SIG开头。
信号处理动作:
1)忽略此信号
2)捕捉信号
3)执行系统默认动作
“终止+core”表示在该进程当前工作目录的core文件中复制该进程的存储映像。
不产生core文件条件:
1)进程是设置用户ID的,而且当前用户并非程序文件的所有者
2)进程是设置组ID的,而且当前用户并非该程序文件的组所有者。
3)用户没有写当前工作目录的权限
4)文件已存在,而且用户对该文件设有写权限
5)文件太大
-----------------------------------------------------------------------------
#include<signal.h>
void (*signal(int signo, void (*func)(int)))(int)
signo是信号名。
func的值是常量SIG_IGN,常量SIG_DFL或当接到此信号后要调用的函数的地址。
SIG_IGN表示忽略此信号。
SIG_DFL表示接到此信号后的动作是系统默认的动作。
当指定函数地址时,则在信号发生时,调用此函数,称为“捕捉”该信号。
函数指针所指向的函数需要一个整型参数,无返回值。
signal的返回值是一个函数地址,该函数有一个整型参数(最后的int)。
signal的返回值则是指向之前的信号处理程序的指针。
typedef void Sigfunc(int)
Sigfunc *signal(int, Sigfunc*)
当执行一个程序时,所有信号的状态都是系统默认或忽略。通常所有信号都被设置为它们的默认动作,除非调用exec的进程忽略该信号。exec函数将原先设置为要捕捉的信号都更改为它们的默认动作,其他信号的状态则不变。
当一个进程调用fork时,其子进程继承父进程的信号处理方式。因为子进程在开始时复制了父进程的存储映像,所以信号捕捉函数的地址在子进程中是有意义的。
-------------------------------------------------------
10.5中断的系统调用
如果进程在执行一个低速系统调用而阻塞期间捕捉到一个信号,则该系统调用就被中断不再继续执行。该系统调用返回出错,其errno被设置为EINTR。这样处理的理由是:因为一个信号发生了,进程捕捉到了它,这意味着已经发生了某种事情,所以是个应当唤醒阻塞的系统调用的好机会。
系统调用分为低速系统调用和其他系统调用。
为了帮助应用程序使其不必处理被终端的系统调用,4.2BSD引入了某些被终端系统调用的自动重启动。自动重启动的系统调用包括ioctl,read,readv,write,writev,wait和waitpid。其中前5个函数只有对低速设备进行操作时才会被信号中断。而wait和waitpid在捕捉到信号时总是被中断。因为这种自动重启动的处理方式也会带来问题,所以某些应用程序并不希望这些函数被中断后重启动。为此4.3BSD允许进程基于每个信号禁用此功能。
-----------------------------------------------------
可重入函数
进程捕捉到信号并对其进行处理时,进程正在执行的指令序列就被信号处理程序临时中断,它首先执行该信号处理程序中的指令。如果从信号处理程序返回,则继续执行在捕捉到信号时进程正在执行的正常指令序列。但在信号处理程序中,不能判断捕捉到信号时进程在何处执行。
不可重入:
a)已知它们使用静态数据结构。
b)它们调用malloc或free。
c)它们是标准I/O函数。
当在信号处理程序中调用可重入函数时,应当在其前保存,在其后恢复errno。
---------------------------------------------------------------------------
10.7SIGCLD语义
SIGCLD是系统V的一个信号名,其语义与名为SIGCHLD的BSD信号不同。子进程状态改变后产生此信号,父进程需要调用一个wait函数以确定发生了什么。
--------------------------------------------------------------
10.8可靠信号术语和语义
在产生了信号时,内核通常在进程表中设置一个某种形式的标志。
当对信号采取了这种动作时,我们说向进程递送了一个信号。在信号产生和递送之间的时间间隔内,称信号是未决的。
进程可以选用信号递送阻塞。如果为进程产生了一个选择为阻塞的信号,而且对该信号的动作是系统默认动作或捕捉该信号,则为该进程将此信号保持为为决状态,直到该进程(a)对此信号解除了阻塞,或者(b)将对此信号的动作更改为忽略。内核在递送一个原来被阻塞的信号给进程时,才决定对它的处理方式。于是进程在信号递送给它之前仍可改变对该信号的动作。