【Linux】进程信号(一):信号的产生与信号的保存
📝前言:
这篇文章我们来讲讲Linux——进程信号:
🎬个人简介:努力学习ing
📋个人专栏:Linux
🎀CSDN主页 愚润求学
🌄其他专栏:C++学习笔记,C语言入门基础,python入门基础,C++刷题专栏
目录
- 一,认识信号
- 1. 查看信号
- 2. 信号处理动作
- 2.1 默认处理动作
- term 和 core 的区别
- 2.2 自定义处理动作
- signal
- 示例
- 3. 前台进程和后台进程
- 区别
- 切换
- 二,信号的产生
- 1. 四种方式基本介绍
- 1. 异常产生信号
- 2. 软件条件产生信号
- 三,信号的保存
- 1. 基本概念
- 阻塞
- 2. pending表
- 3. block表
- 3.1 sigset_t
- 信号集操作函数
- 信号集“上传”函数
- 3.2 . 自定义处理动作sigaction
- 4. handler表
一,认识信号
1. 查看信号
kill -l查看信号:

- 每个信号都有⼀个编号和⼀个宏定义名称:左边是信号编号,右边是对应的宏
- 其中
1-31号信号是普通信号,34 - 64为实时信号 - 普通信号:可以不立即处理
- 实时信号:立即处理
signal.h中可以看到:编号和宏对应

2. 信号处理动作
按下 Ctrl + c 组合键会向当前前台进程发送 SIGINT(2 号信号),此时进程会终止。让进程终止是该2号信号的默认处理动作。
信号处理的动作有三种:默认、自定义和忽略
2.1 默认处理动作
man 7 signal我们可以去杂项章节看一下信号的具体描述:

Action是信号的默认处理动作
term / core→ 终止(但有区别)Ign→ 忽略Cont→ 继续Stop→ 暂停
term 和 core 的区别
core在term的基础上多了一个核心转储功能,会生成核心转储文件(Core Dump)。- 用途:用于后续
debug,分析程序崩溃原因- 如,
test1崩了,我们gdb ./test1 core就可以直接定位到崩溃的位置
- 如,
- 生产环境上(如:云服务器),
core dump会被禁止,因为容易产生大量core文件占据磁盘空间
waitpid()的输出型参数的wstatus里面就有一个core dump标记位记录,当前信号是否是core终止的,是否生成core文件
ulimit -a可以查看允许生成的core文件的大小:

可以看到默认core文件的大小是0个blocks,即:禁止
ulimit -c <数字>:可以重新设置大小
2.2 自定义处理动作
signal
signal用来自定义信号处理动作

signum:要自定义的信号的编号(也可以传对应的宏,本质都是数字)handler:自定义函数的指针- 同时要求我们的自定义函数
- 返回值
void - 一个参数:接受信号编号
- 返回值
示例
void handler(int signum)
{
cout << "我收到了 " << signum << " 号信号" << endl;
}
int main()
{
signal(2, handler);
while (true)
{
cout << "进程PID: " << getpid() << endl;
sleep(1);
}
return 0;
}

这时候可以killed -9 8968把这个进程杀掉,因为9号是强杀信号,不能被自定义动作,类似的不能被自定义的还有19…
3. 前台进程和后台进程
在可执行程序执行后面带 &,运行的就是后台进程。
区别
- 前台进程可以从标准输入中获取数据,但是后台进程不行(即:我们的键盘输入没办法发给后台)
- 前后台进程都可以往标准输出打印
- 在一个
bash下:某一时刻,只能有一个前台进程,后台进程可以有多个(因为标准输入只有一个,不能同时有多个进程抢着读,会乱) - 每个
bash进程都有自己独立的作业列表,不同的bash进程之间的作业是相互隔离的 bash本身是前台进程,当我们执行前台进程的时候,bash就会被切换后台
示例:
./test1 &把test1放到后台运行

可见键盘输入Ctrl + c,test1就收不到了,但是ls命令bash还可以收到,最后我们kill -9 9193就可以把这个进程杀掉
切换
jobs可以看当前bash的后台进程fg + 任务号:把后台进程切换到前台Ctrl + z:暂停前台进程,并把前台进程切换到后台bg + 任务号:恢复暂停的后台进程,重新运行
二,信号的产生
1. 四种方式基本介绍
一个信号,要经历三个阶段:

信号的产生方式有多种:
- 键盘产生
- 如:
ctrl + c给前台进程发信号
- 如:
- 系统调用(命令)产生
- 如:
int kill(pid_t pid, int sig),给pid进程发一个sig信号(命令kill就是调这个的) - 如:
int raise(int sig),自己给自己发sig信号 - 如:
abort():给自己发 6 号信号
- 如:
- [硬件]异常产生
- 如:
- 如:

