【Linux系统】万字解析,进程间的信号
代码语言:javascriptAI代码解释。
信号概念
信号是OS发送给进程的异步机制!所谓异步指的是,发送信息这个动作,并不会干扰进程本身!
对于信号的基本认识:
|
1.什么样的信号应该如何处理,是在信号产生之前早就得知了的 |
|---|
|
2.信号的处理并不是立即处理,而是等待合适的时间去处理 |
|
3.对于进程来说,其内部是以及内置了对于信号的识别以及处理方式 |
|
4.产生信号的方式很多,也就是说信号源非常多 |
信号的产生
信号的产生有很多方式
1.键盘产生信号
之前我们常见的:Ctrl + c就是信号,用于终止进程!
信号都有那些:

其中,我们只需要关注信号1~31(普通信号),信号的名字本身是宏,其真正的值就是前面的编号。
处理信号
进程收到信号之后,进程会在合适的时候,进程处理!其中处理的方式有三种
|
1.执行默认的处理动作!(相当一部分的信号默认动作都是终止进程) |
|---|
|
2.执行自定义动作! |
|
3.忽略信号,继续做自己的事! |
自定义处理
代码语言:javascript
AI代码解释
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
代码语言:javascript
AI代码解释
#include <signal.h>
#include <iostream>
using namespace std;
void sighandler(int i)
{
cout << "收到一个信号:" << i << endl;
}
int main()
{
// 将1~31的信号全部自定义
for (int i = 0; i < 32; i++)
{
signal(i, sighandler);
}
while (1)
{
}
}
代码语言:javascript
AI代码解释
hyc@hyc-alicloud:~/linux/进程信号$ ./test
^C收到一个信号:2
^C收到一个信号:2
^C收到一个信号:2
^C收到一个信号:2
^C收到一个信号:2
可以看到,我们发送了多次的Ctrl + c信号,可见Ctrl + c信号发送的就是2号信号:SIGINT
当然并不是说有的信号都可以被自定义,那不然进程就无法停止了!
前后台

当我们运行可执行程序时,我们发现Linux指令不起作用了?!这就是前后台的问题了
|
在OS中,进程分为:前台进程、后台进程 |
|---|
|
前台进程:有且仅有一个!并且只有前台进程才能接收输入的数据! |
|
后台进程:可以有多个! |
|
虽然输入的数据只有前台进程可以接收,但是输出的数据可以由前后台共同进行的! |
所以,当我们运行我们的程序时,当前这个程序就处于前台了!那么负责接收解析指令的shell程序就会退出前台!而后台程序是不能接收输入进来的数据的,所以这才导致我们输入的指令没有反应!
发送信号的本质
信号发送给进程后,进程需要在合适的时间再进行处理!那么这就意味着进程需要先将信号保存下来!后续再读取执行。
那么保存在哪里呢?答案是保存在task_struct的sigs变量中!其中sigs采用的是位图结构!比特位的位置表示信号的编号,比特位的内容(1表示收到、0表示没有收到)表示是否收到。
所以,发送信号的本质就是,向目标进程写信号 -> 修改位图!
但是task_struct中的数据属于OS内核数据!所以想要修改其数据,就只能让OS自己来修改!所以信号只能让OS来发送!
2.系统调用产生信号
kill接口
代码语言:javascript
AI代码解释
#include <signal.h>
int kill(pid_t pid, int sig);
作用:向指定的进程发送信号!
pid 参数:
pid > 0:向指定进程 ID 的进程发送信号
pid = 0:向与调用进程同进程组的所有进程发送信号
sig 参数:
代表信号编号
看看效果:
代码语言:javascript
AI代码解释
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
using namespace std;
void sighandler(int i)
{
cout << "收到一个信号:" << i << endl;
}
int main()
{
// 将1~31的信号全部自定义
for (int i = 0; i < 32; i++)
{
signal(i, sighandler);
}
kill(getpid(), 2);
}

也可以通过kill来验证一下,上面说的“并不是所有信号都可以被自定义!”
代码语言:javascript
AI代码解释
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>
using namespace std;
void sighandler(int i)
{
cout << "收到一个信号:" << i << endl;
}
int main()
{
// 将1~31的信号全部自定义
for (int i = 0; i < 32; i++)
{
signal(i, sighandler);
}
for (int i = 1; i < 32; i++)
{
kill(getpid(), i);
}
}

可见,信号9并不能被“自定义”!当然不仅仅编号9,还有其他信号也不能被自定义。
更多推荐

所有评论(0)