Linux信号的使用

it2022-05-05  142

概要

信号时软件中断,一种处理异步事件的方法,每个信号都有一个名字,这些名字都是以SIG开头。产生信号的条件有很多种: 1、当用户按下终端按键时,引发终端产生的信号。Ctrl+C等。 2、 硬件产生信号,除了0、无效内存。 3、进程被调用了kill函数。 4、检测到了某个软件条件。比如SIGURG(网络链接传来数据)、SIGPIPE(在管道读进程已经终止)、SIGALRM(设置的定时器超时)。

信号的使用

最简单的接口是singnal,但signal的函数原型太复杂,可以使用下面的typedef,可以更简单一些。第一个参数signo是信号名,是接收到此信号的时候,要调用的函数地址(包括:SIG_IGN :忽略系统动作,SIG_DFL :系统默认动作, ):

#include <signal.h> typedef void Sigfunc(int); Sigfunc * signal(int , Sigfunc *); //信号处理函数 static void sig_usr(int); int main(void ){ if(signal(SIGUSR1,sig_usr) == SIG_ERR){ err_sys("can't catch err!"); } pause(); }

我们在在终端使用:kill USR1 (pid) 进程就会接收到SIG_USR1信号。 signal的缺点:不改变信号的处理方式,就不能确定信号的当前处理方式。而sigaction函数则可以确定一个信号的处理方式,无需改变它。

在早期的时候进程信号可能存在丢失的情况,同时,系统对信号的控制能力也很差,系统通常不具备信号的阻塞能力。后来通过捕捉到信号后,设置信号已经发生的标志位的方式,来进行判断信号是否丢失。

当产生一个信号时,事件可以时硬件异常(除以0)、软件异常(定时器超时)、终端信号、kill函数的发生,内核会在进程中以某种形式设置一个标志。当信号传递过程中,我么称之为信号是未决的。如果有多个信号传给一个进程,PoSIX并没有规定它的顺序。

发送信号相关的函数

kill和raise。kill将信号发送给进程和进程组,raise函数允许进程向着自身发送信号。 //调用 raise(signo ); //等同于调用,pid > 0 ,信号给到ID为pid的进程;pid==0,信号给到同组所有进程。 kill(getpid(), signo); alarm和pause,alarm函数可设置一个定时器,产生SIGALRM信号,pause函数会使得进程一直挂起,直到捕捉到一个信号。longjmp无法很好的处理信号间的竞争,可选择select和poll函数。sigaction函数是检查或者修改与指定信号相关的处理动作。sigsetjmp和siglongjmp用于非局部转移,常调用longjmp回到主循环中。sigsuspend:用于解除信号阻塞后,被推迟响应的情况。先恢复被屏蔽字,然后重新进入休眠。abort:使得程序异常的终止。

最新回复(0)