【Linux系统】万字解析,进程间的信号

【Linux系统】万字解析,进程间的信号 信号概念信号是OS发送给进程的异步机制所谓异步指的是发送信息这个动作并不会干扰进程本身对于信号的基本认识1.什么样的信号应该如何处理是在信号产生之前早就得知了的2.信号的处理并不是立即处理而是等待合适的时间去处理3.对于进程来说其内部是以及内置了对于信号的识别以及处理方式4.产生信号的方式很多也就是说信号源非常多信号的产生信号的产生有很多方式1.键盘产生信号之前我们常见的Ctrl c就是信号用于终止进程信号都有那些其中我们只需要关注信号1~31普通信号信号的名字本身是宏其真正的值就是前面的编号。处理信号进程收到信号之后进程会在合适的时候进程处理其中处理的方式有三种1.执行默认的处理动作相当一部分的信号默认动作都是终止进程2.执行自定义动作3.忽略信号继续做自己的事自定义处理代码语言javascriptAI代码解释#include signal.h typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);代码语言javascriptAI代码解释#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) { } }代码语言javascriptAI代码解释hychyc-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接口代码语言javascriptAI代码解释#include signal.h int kill(pid_t pid, int sig); 作用向指定的进程发送信号 pid 参数 pid 0向指定进程 ID 的进程发送信号 pid 0向与调用进程同进程组的所有进程发送信号 sig 参数 代表信号编号看看效果代码语言javascriptAI代码解释#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来验证一下上面说的“并不是所有信号都可以被自定义”代码语言javascriptAI代码解释#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还有其他信号也不能被自定义。