【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 号信号
- 如:
- [硬件]异常产生
- 如:
- 如: