Linux下的信号以及信号的处理

本文详细介绍了Linux下的信号机制,包括信号的产生(硬件中断、系统调用、软件产生、程序异常)、阻塞信号的概念及信号集操作函数的使用。重点讨论了信号捕捉与处理,如signal和sigaction函数,以及SIGCHLD信号在处理子进程退出中的作用。通过对信号的全面解析,帮助读者深入理解Linux进程间的通信和控制。

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

认识信号

根据生活中的经验,信号就是向一个事物传递某些信息,在Shell下启动一个前台进程,用户输入Ctrl+c,这个过程就相当于是再给内核传递一个进程取消的信号。
那么用户按下Ctrl+c后,发生了什么?

  • 如果CPU当前正在执行某个进程的代码,接收到Ctrl+c信号之后用户空间的代码暂停执行,CPU从用户态切换到内核态处理该信号
  • 终端驱动程序将Ctrl+c解释成一个SIGINT信号,记在进程的PCB中
  • 当某个时刻从内核态返回用户态时,首先要处理PCB中记录的信号,发现有一个SIGINT信号需要处理,这个信号的默认处理动作就是终止进程,所以直接终止进程而不返回用户空间执行代码。
    使用kill -l来查看Linux中的信号
    在这里插入图片描述
    Linux下一共有62个信号,每个信号都有一个编号和一个宏定义名称,例如#define SIGINT 2,前31个为不可靠信号,后面31个为可靠信号。

信号产生

硬件中断

在键盘上按下Ctrl+c等来产生信号

使用系统调用

  • 在后台执行死循环程序,使用kill命令给进程发送SIGSEGV信号
    在这里插入图片描述
    在发送信号之后我们需要多按一次回车才会显示Segmentation fault,这是因为在后台进程终止之前已经回到Shell提示符等待用户输入命令,Shell不希望Segmentation fault信息和用户输入交错在一起,所以等待用户输入命令之后才显示。
    kill命令是基于系统调用kill函数实现的,kill函数可以给一个指定的进程发送指定的信号
#include <signal.h>
int kill(pid_t pid, int signo);
// 成功返回0,错误返回-1

软件产生

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
//调用alarm函数可以设定一个闹钟,告诉内核在second秒之后给当前进程发送SIGALRM信号,该信号默认处理方式为终止当前进程
//second为0表示取消之前设定的闹钟

程序异常

在当前进程执行了除以0的指令,CPU的运算单元会产生异常,内核将这个异常解释为SIGFPE信号发送给进程,或者当前进程访问了非法内存地址,MMU产生异常,内核将这个异常解释为SIGSEGV信号发送给程序

阻塞信号

实际执行信号处理的动作称作信号递达
信号从产生到递达之间的状态称为信号未决
进程可以选择阻塞某一个信号,被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞才执行递达动作

  • 每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个指针表示该信号的处理动作。
  • 信号产生时,内核在PCB中设置该信号的未决标志,直到信号递达才清除该标志在这里插入图片描述

如上如所示,SIGHUP信号未产生,SIGINT信号已经产生但是正在被阻塞,所以暂时不能递达,SIGQUIT信号从未产生,但是一旦产生它将会被阻塞。

进程在解除某一个信号的阻塞之前,这个信号产生过多次,如果是不可靠信号,产生多次会当做一次处理,而对于可靠信号来说,产生的信号会依次放在一个队列里,将来一一处理。

信号集操作函数

每个信号都有一个未决状态的标志,不记录该信号产生了多少次,可以用sigset_t来存储,sigset_t就称作为信号集,这个类型可以表示信号的有效或无效状态。

#include <signal.h>
int sigemptyset
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值