信号概念

信号是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,还有其他信号也不能被自定义。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐