Linux 之常见信号与处理

本文介绍Linux信号这一进程间异步通信机制,它是软中断,可使运行进程中断处理突发事件。阐述了信号基本概念、常见处理方式及术语,还介绍了信号产生(如kill、raise等函数)、安装(signal、sigaction函数)和信号集处理(sigprocmask函数)等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

Linux信号是一种进程间异步的通信机制,在实现上是一种软中断,信号可以导致一个正在运行的进程被中断,进而处理一个突发事件。Linux在/usr/include/asm-generic/signal.h中详细定义了信号的信号值,其内容如下:

1、信号的基本概念

#define SIGHUP		 1      //连接断开   
#define SIGINT		 2      //终端中断符
#define SIGQUIT		 3      //终端退出符
#define SIGILL		 4      //非法硬件指令
#define SIGTRAP		 5      //硬件故障
#define SIGABRT		 6      //异常终止
#define SIGIOT		 6      //硬件故障 
#define SIGBUS		 7      //硬件故障
#define SIGFPE		 8      //算术异常
#define SIGKILL		 9      //终止
#define SIGUSR1		10      //紧急情况
#define SIGSEGV		11      //无效存储访问
#define SIGUSR2		12      //用户自定义信号
#define SIGPIPE		13      //写至无读进程的管道
#define SIGALRM		14      //超时
#define SIGTERM		15      //终止进程
#define SIGSTKFLT	16      
#define SIGCHLD		17      //子进程改变工作状态
#define SIGCONT		18      //使暂定状态的进程继续工作
#define SIGSTOP		19      //使进程暂停工作
#define SIGTSTP		20      //终端挂起符作业
#define SIGTTIN		21      //后台从控制tty读作业
#define SIGTTOU		22      //后台从控制tty写作业
#define SIGURG		23      //紧急情况
#define SIGXCPU		24      //超过CPU限制
#define SIGXFSZ		25      //超出文件长度限制
#define SIGVTALRM	26      //虚拟时间闹钟
#define SIGPROF		27      //时间超时
#define SIGWINCH	28      //终端窗口大小改变
#define SIGIO		29      //异步I/O
#define SIGPOLL		SIGIO**
/*
#define SIGLOST		29
*/
#define SIGPWR		30       //电源失效/再启动
#define SIGSYS		31       //无效系统调用
#define	SIGUNUSED	31
/* These should not be considered constants from userland.  */
#define SIGRTMIN	32
#ifndef SIGRTMAX
#define SIGRTMAX	_NSIG
#endif

下面介绍几中常见信号处理方式:
(1)SIGCHLD在子进程退出时,将发送该信号给父进程,父进程可根据该信号完成对子进程PCB资源的回收。
(2)SIGSTOP、SIGKILL不能被屏蔽、安装。
(3)SIGSTOP和SIGCOUNT是配对的,一个进程收到SIGSTOP后会暂停执行,并屏蔽除SIGKILL外所有信号,在收到SIGCOUNT后,才会继续执行
(4)信号可以唤醒处于sleep()的进程

信号的基本术语:

  1. 发送信号:产生信号,并将信号发送出去。
  2. 安装中断:设置信号到来时,不是执行默认操作,而是执行自己自定义的代码。
  3. 递送信号:一个信号被操作系统发送到目标进程。
  4. 捕获信号:被递送的信号在目标进程中引起某段代码的执行。
  5. 屏蔽信号:进程告诉操作系统暂时不接收某些信号。
  6. 忽略信号:进程被递送到目标进程,但目标进程不做任何操作,直接丢弃
  7. 未决信号:信号已经产生,但目标进程暂时屏蔽了该信号,从而导致不能被目标进程捕获的信号。
  8. 可靠信号:信号值大于32的为信号
  9. 不可靠信号:信号值小于32的信号

2、信号的产生
(1)、使用kill()函数向指定进程发送一个信号,函数声明如下:

//from /usr/include/asm-generic/signal.h
int kill(pid_t pid,int sig);

可以使用kill(pid_t pid,0)来检测指定进程是否存在。成功返回0,失败返回-1。

(2)、 使用raise()函数给当前进程发送一个信号,函数声明如下:

//from /usr/include/asm-generic/signal.h
int raise(int sig);

函数执行成功,返回0,失败返回-1。

(3)、使用alarm()函数可以持续的按照一定间隔发送一个SIGALARM信号,并不会信产生信号给当前进程,函数声明如下:

//from /usr/include/asm-generic/signal.h
unsigned int alarm(unsigned int seconds);

函数使用时,若seconds值为0,则表示取消先前发出的信号。
函数第一次调用时,执行成功返回0,失败返回-1。
若之前已有调用,再次调用alarm()则表示重置时间间隔,执行成功则返回距上次信号发送,剩余间隔时间。
另外需要强调的是,子进程并不会继承父进程的alarm信号,但在调用exec()函数执行新代码时,原来的设置的信号仍然有效。

(4)、 使用ualarm()持续产生SIGALARM信号,函数声明如下:

//from /usr/include/asm-generic/signal.h
__useconds_t ualarm(__useconds_t value,__useconds_t interval);

函数将在value 微妙内产生SIGALARM信号,并在之后每interval微妙时,再次产生该信号。

3、安装信号
(1)、 signal()安装信号,函数声明如下:

//from /usr/include/asm-generic/signal.h
__sighandler_t signal(int sig,__sighandler_t handler);

函数第1参数为收到的信号,第2个参数为接收此信号后的处理代码入口或以下几个宏:

 #define SIG_ERR  ((__sighandler_t  )  -1)   //返回错误
 #define SIG_DEF  ((__sighandler_t  )  0)    //执行信号默认参数
 #define SIG_IGN  ((__sighandler_t  )  1)    //忽略信号

2、sigaction()安装信号
sigaction()函数相对于signal()函数来说,更为安全可靠,获取的信息更多,函数声明如下:

//from /usr/include/asm-generic/signal.h
struct sigaction
{
	union
	{
		/*SIGDFL,SIG_IGN,类似于signal*/
		__sighandler_t sa_handler; 
		
		/*当sa_flags为SA_SIGINFO时,使用此变量设置信号处理函数,并将获取信号发送时的信息保存在结构体info中,包括信号发送进程ID*/
		void (*sa_sigaction)(int sig,struct siginfo_t* info,void*);
	}
	sigset_t sa_mask;   //屏蔽的信号集
	unsigned long sa_flags;  //特殊标志
	...
};
int sigaction(int sig,struct sigaction* act,struct sigaction* oact);

函数的第1个参数为信号值,第2个参数为欲设置的信号处理方式,第3个参数为原先的信号处理方式信息。
另外sa_flags可以设置为以下值:

  • SA_NOCLDSTOP:表示子进程在退出时,不生成SIGCHLD信号
  • SA_RESTART:将指定的可中断函数将失败
  • SA_RESETHAND:信号的处理方法将被重置为默认处理方式,即SIG_DFL

4、信号集处理
函数sigprocmask()用来设置当前进程屏蔽的信号集合,函数声明如下:

int sigprocmask(int how,sigset_t* set,sigset_t* oset);

函数的第1个参数为更改信号集的方式,可以使用以下几个值:

#define  SIG_BLOCK  0  //第2个参数代表的信号集添加到当前进程屏蔽的信号集中
#define  SIG_UNBLOCK 1 //第2个参数代表的信号集从当前进程屏蔽的信号集中删除
#define  SIG_SETMASK 2 //设置第2个参数代表的信号集为当前进程屏蔽的信号集

函数执行成功返回0,否则返回-1

除了sigprocmask()函数,还有其他方式,例如:

/*清空set代表的信号集*/
int sigemptyset(sigset_t* set)

/*添加信号sig到信号集set中*/
int sigaddset(sigset_t* set,int sig);

/*从信号集set中删除信号sig*/
int sigdelset(sigset_t* set,int sig);

/*检测信号sig是否在信号集set中*/
int sigismember(sigset_t* set,int sig);

/*检测信号集set是否为空信号集*/
int sigisemptyset(sigset_t* set);

/*将信号集left与信号集right按照逻辑与的方式合并到信号集set中*/
int sigandset(sigset_t* set,sigset_t* left,sigset_t* right);

/*将信号集left与信号集right按照逻辑或的方式合并到信号集set中*/
int sigandset(sigset_t* set,sigset_t* left,sigset_t* right);

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chiang木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值