系统相关
首页 > 系统相关> > 【Linux从青铜到王者】第十一篇:Linux进程间信号第一篇

【Linux从青铜到王者】第十一篇:Linux进程间信号第一篇

作者:互联网

在这里插入图片描述

系列文章目录


文章目录


前言


在这里插入图片描述

一、信号入门

1.生活角度的信号

2. 技术应用角度的信号

     1	#include<iostream>
     2	#include<unistd.h>
     3	int main()
     4	{
     5	    while(1)
     6	    {
     7	        std::cout<<"i am process,i am waiting signal!"<<std::endl;
     8	        sleep(1);
     9	    }
    10	    return 0;
    11	}

3. 进程的注意事项

4. 信号概念

信号是进程之间事件异步通知的一种方式,属于软中断。
在这里插入图片描述

5. 用kill -l命令可以察看系统定义的信号列表

在这里插入图片描述

6. 信号处理常见方式概览

二、信号产生

代码如下(示例):

1. 通过终端按键产生信号

在这里插入图片描述
SIGINT的默认处理动作是终止进程,SIGQUIT的默认处理动作是终止进程并且Core Dump,现在我们来验证一下。

首先解释什么是Core Dump。当一个进程要异常终止时,可以选择把进程的用户空间内存数据全部 保存到磁盘上,文件名通常是core,这叫做Core Dump。进程异常终止通常是因为有Bug,比如非法内存访问导致段错误,事后可以用调试器检查core文件以查清错误原因,这叫做Post-mortem Debug(事后调试)。一个进程允许产生多大的core文件取决于进程的Resource Limit(这个信息保存 在PCB中)。默认是不允许产生core文件的,因为core文件中可能包含用户密码等敏感信息,不安全。在开发调试阶段可以用ulimit命令改变这个限制,允许产生core文件。
首先用ulimit命令改变Shell进程的Resource Limit,允许core文件最大为1024K: $ ulimit -c 1024
在这里插入图片描述

     1	#include<iostream>
     2	int main()
     3	{
     4		std::cout<<"hhh----Core Dump"<<std::endl;
     5		while(1);
     6		return 0;
     7	}

在这里插入图片描述
ulimit命令改变了Shell进程的Resource Limit,test进程的PCB由Shell进程复制而来,所以也具 有和Shell进程相同的Resource Limit值,这样就可以产生Core Dump了。 使用core文件:
在这里插入图片描述
在这里插入图片描述

2. 调用系统函数向进程发信号

首先在后台执行死循环程序,然后用kill命令给它发SIGSEGV信号。
在这里插入图片描述

kill命令是调用kill函数实现的。kill函数可以给一个指定的进程发送指定的信号。
在这里插入图片描述

     1	#include<iostream>
     2	#include<stdlib.h>
     3	#include<signal.h>
     4	
     5	
     6	int main(int argc,char* argv[])
     7	{
     8	    if(argc==3)
     9	    {
    10	        kill(atoi(argv[1]),atoi(argv[2]));
    11	    }
    12	    return 0;
    13	}

在这里插入图片描述
raise函数可以给当前进程发送指定的信号(自己给自己发信号)。
在这里插入图片描述

     1	#include<iostream>
     2	#include<stdlib.h>
     3	#include<signal.h>
     4	#include<unistd.h>
     5	void handler(int signo)
     6	{
     7	    std::cout<<"catch a signal:"<<signo<<std::endl;
     8	}
     9	int main(int argc,char* argv[])
    10	{
    11	    signal(9,handler);//捕捉信号
    12	    while(1)
    13	    {
    14	        sleep(1);
    15	        raise(9);
    16	    }
    17	    return 0;
    18	}

在这里插入图片描述
其他信号可以捕捉例如2号:

     1	#include<iostream>
     2	#include<stdlib.h>
     3	#include<signal.h>
     4	#include<unistd.h>
     5	void handler(int signo)
     6	{
     7	    std::cout<<"catch a signal:"<<signo<<std::endl;
     8	}
     9	int main(int argc,char* argv[])
    10	{
    11	    signal(2,handler);//捕捉信号
    12	    while(1)
    13	    {
    14	        sleep(1);
    15	        raise(2);
    16	    }
    17	    return 0;
    18	}

在这里插入图片描述
abort函数使当前进程接收到信号而异常终止。

#include <stdlib.h>
void abort(void);
就像exit函数一样,abort函数总是会成功的,所以没有返回值。

在这里插入图片描述
在这里插入图片描述

     1	#include<iostream>
     2	#include<stdlib.h>
     3	#include<signal.h>
     4	#include<unistd.h>
     5	void handler(int signo)
     6	{
     7	    std::cout<<"catch a signal:"<<signo<<std::endl;
     8	}
     9	int main(int argc,char* argv[])
    10	{
    11	    signal(6,handler);//捕捉信号
    12	    while(1)
    13	    {
    14	        sleep(1);
    15	        abort();
    16	    }
    17	    return 0;
    18	}

在这里插入图片描述

3. 由软件条件产生信号

在这里插入图片描述
SIGPIPE是一种由软件条件产生的信号,在“管道”中已经介绍过了。本节主要介绍alarm函数 和SIGALRM信号。
在这里插入图片描述

#include <unistd.h>
unsigned int alarm(unsigned int seconds);
调用alarm函数可以设定一个闹钟,也就是告诉内核在seconds秒之后给当前进程发SIGALRM信号, 该信号的默认处理动作是终止当前进程。

这个函数的返回值是0或者是以前设定的闹钟时间还余下的秒数。打个比方,某人要小睡一觉,设定闹钟为30分钟之后响,20分钟后被人吵醒了,还想多睡一会儿,于是重新设定闹钟为15分钟之后响,“以前设定的闹钟时间还余下的时间”就是10分钟。如果seconds值为0,表示取消以前设定的闹钟,函数的返回值仍然是以前设定的闹钟时间还余下的秒数(自己验证一下?)

     1	#include<iostream>
     2	#include<stdlib.h>
     3	#include<signal.h>
     4	#include<unistd.h>
     5	
     6	int main(int argc,char* argv[])
     7	{
     8	    int count=0;
     9	    alarm(1);
    10	    while(1)
    11	    {
    12	        std::cout<<"count:"<<count++<<std::endl;
    13	    }
    14	    return 0;
    15	}

在这里插入图片描述
由图知道1S中count打印了2W次左右,这个程序的作用是1秒钟之内不停地数数,1秒钟到了就被SIGALRM信号终止。

思考:为啥打印出来只有2W。换种代码试下

     1	#include<iostream>
     2	#include<stdlib.h>
     3	#include<signal.h>
     4	#include<unistd.h>
     5	int count=0;
     6	void handler(int signo)
     7	{
     8	    std::cout<<"count:"<<count<<std::endl;
     9	    exit(1);
    10	}
    11	int main(int argc,char* argv[])
    12	{
    13	    signal(14,handler);
    14	    alarm(1);
    15	    while(1)
    16	    {
    17	        count++;
    18	    }
    19	    return 0;
    20	}

这里的结果变成了4亿,为什么?
因为上面改的程序不往IO上面去输出,往IO上输出会影响效率。
在这里插入图片描述

4. 硬件异常产生信号

硬件异常被硬件以某种方式被硬件检测到并通知内核,然后内核向当前进程发送适当的信号。例如当前进程执行了除以0的指令,CPU的运算单元会产生异常,内核将这个异常解释 为SIGFPE信号发送给进程。再比如当前进程访问了非法内存地址,MMU会产生异常,内核将这个异常解释为SIGSEGV信号发送给进程。

1.信号捕捉初识

     1	#include<iostream>
     2	#include<signal.h>
     3	void handler(int signo)
     4	{
     5	    std::cout<<"catch a signal:"<<signo<<std::endl;
     6	}
     7	int main()
     8	{
     9	    signal(2,handler);//捕捉2号信号
    10	    while(1);
    11	    return 0;
    12	}

在这里插入图片描述

2.模拟一下野指针异常

     1	#include<iostream>
     2	#include<signal.h>
     3	#include<unistd.h>
     4	void handler(int signo)
     5	{
     6	    std::cout<<"catch a signal:"<<signo<<std::endl;
     7	}
     8	int main()
     9	{
    10	    signal(2,handler);//捕捉2号信号
    11	    sleep(1);
    12	    int* p=NULL;
    13	    *p=100;
    14	    while(1);
    15	    return 0;
    16	}

在这里插入图片描述
段错误是11号信号:
在这里插入图片描述
所以这里可以捕捉11号信号:

     1	#include<iostream>
     2	#include<signal.h>
     3	#include<unistd.h>
     4	void handler(int signo)
     5	{
     6	    std::cout<<"catch a signal:"<<signo<<std::endl;
     7	}
     8	int main()
     9	{
    10	    signal(11,handler);//捕捉2号信号
    11	    sleep(1);
    12	    int* p=NULL;
    13	    *p=100;
    14	    while(1);
    15	    sleep(1);
    16	    return 0;
    17	}

在这里插入图片描述
由此可以确认,我们在C/C++当中除零,内存越界等异常,在系统层面上,是被当成信号处理的。


总结

以上就是今天要讲的内容,本文仅仅简单介绍了Linux进程间信号前半部分的使用,而信号让我们知道C/C++当中除零,内存越界等异常,在系统层面上,是被当成信号处理的。而后半部分中阻塞信号和捕捉信号等在下一篇文章提及,希望大家多多支持!另外如果上述有任何问题,请懂哥指教,不过没关系,主要是自己能坚持,更希望有一起学习的同学可以帮我指正,但是如果可以请温柔一点跟我讲,爱与和平是永远的主题,爱各位了。
在这里插入图片描述

标签:第一篇,第十一篇,快递,int,handler,信号,Linux,进程,include
来源: https://blog.csdn.net/qq_44918090/article/details/118445124