unix环境高级编程-信号(1)

信号是软件中断,信号提供了一种处理异步事件的方法

每个信号都有一个名字,这些名字都以3个字符SIG开头,例如SIGABRT是夭折信号,当进程调用abort函数时产生这种信号。在头文件中,信号名都被定义为正整数常量。不存在编号为0的信号,这种信号叫做空信号。

很多条件会产生信号:

1.当用户按某些终端键时,引发终端产生的信号,比如delete键,通常产生中断信号(SIGINT)

2.硬件异常产生信号:除数为0,无效的内存引用,这些条件通常由硬件检测到。并通知内核。

3.进程调用kill(2)函数可将任意信号发送给另一个进程或进程组。

4.用户可用kill(1)命令将信号发送给其他进程。

信号是异步事件的经典实例,产生信号的事件对进程而言是随机出现的。

当信号出现时,内核按三种方式之一处理:

1.忽略此信号,大多数信号都可这样处理,除了两种信号,SIGKILL和SIGSTOP,因为它们向内核提供进程总之的可靠办法。

2.捕捉信号

3.执行系统默认动作,对大多数信号的默认动作都是终止该进程

unix环境高级编程-信号(1)_第1张图片

SIGABRT:调用abort函数时产生此信号,进程异常终止

SIGALRM 当用alarm函数设置的定时器超时,产生此信号

SIGBUS:指示一个实现定义的硬件故障


函数signal

signo参数是上表的信号名,func的值是常量SIG_IGN、常量SIG_DFL或当接到此信号后要调用的函数的地址。如果指定SIG_IGN,则向内核表示忽略此信号,如果指定SIG_DFL,则表示接到此信号后的动作是系统默认动作,当指定函数地址时,在信号发生时,调用该函数,也就是捕捉该信号。


程序启动:当执行一个程序时,所有信号的状态都是系统默认或忽略,通常所有信号都被设置为它们的默认动作,除非调用exec进程忽略该信号。一个具体的例子就是交互shell如果处理后台进程的中断和退出信号,比如cc main.c &,在后台执行,shell自动将后台进程对中断和退出信号的处理方式设置为忽略,于是当按下中断字符时,就不会影响到后台进程。


中断系统的调用:

如果系统在执行一个低速系统调用而阻塞期间捕捉到一个信号,则该系统调用就被中断不再执行,系统调用返回出错,为了支持这种特性,将系统调用分为两类:低速系统调用和其他系统调用,低速系统调用是可鞥会是进程永远阻塞的一类系统调用如:

1.某类型文件(如读管道,终端设备)的数据不存在,读操作可能会使调用者永远阻塞

2.数据不能被相同的类型文件立即接受,写操作可能使调用者永远阻塞

3.在某种条件发生之前打打开某些wenjiaN,会发生阻塞

4.pause函数和wait函数


可重入函数:

进程捕捉到信号并对齐进行处理时,进程正常执行的正常指令序列就被信号处理程序临时中断,首先执行该信号处理程序中的指令,如果从信号处理程序返回,则继续执行之前中断的正常指令序列。但在信号处理程序中,不能判断进程执行到何处,如果进程正在执行malloc,中断后,又执行malloc可能会发生错误。

在信号处理程序中保证调用安全的函数,这些函数是可重入的并被称为是异步信号安全的。

unix环境高级编程-信号(1)_第2张图片

上表就是这些可重入函数。要注意的是,即使信号处理程序调用的是上表的函数,但是由于每个线程只有一个errno变量,所以信号处理程序可能会修改其原先值。比如一个信号处理程序,刚好在main刚设置errno后被调用,如果该信号处理程序调用read这类函数,则可能更改errno的值,从而取代了由main设置的值。因此一个通用的规则,当信号处理程序调用上表的函数时,应当在调用前保存errno,在调用后恢复errno。

你可能感兴趣的:(Linux)