linux信号基本概念及如何产生信号

linux信号基本概念及如何产生信号

摘自:https://blog.csdn.net/summy_j/article/details/73199069

2017年06月14日 09:34:21 阅读数:4131 标签: linux信号 更多

个人分类: Linux

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/summy_J/article/details/73199069


阅前须知



本文的主要内容有:

1.信号的基本概念(包括进程对信号的3种处理方式)

2.特殊信号举例:写代码证明信号存在,并实现信号的简单捕捉

3.如何产生一个信号(代码举例:mykill的实现)

其中拓展知识有:

1.前台进程与后台进程(代码举例)

2.核心转储core dumped的概念及其在代码调试中的作用(代码举例)

——>全篇阅读大概需要5分钟<——


信号的基本概念



首先,我们可以用kill -l命令查看系统中定义的信号列表:

乍一看,好像有64种信号,但如果仔细观察,你就会发现并非如此。没有32和33号信号。一共只有62个信号。。。

说实话,你是不是和博主刚开始一样被骗了>.<

我们可以看到,每个信号都有一个编号和一个宏定义名称,这些宏定义可以在头文件signal.h中找到。

其中编号34以上的是实时信号,34以下的信号是普通信号。而这些信号各自在什么条件下产生,默认的处理动作是什么,在signal(7)中都有详细说明,在命令行上输入man 7 signal:

知道了什么是信号,那么为什么有信号,信号是谁发送给谁的呢,怎么发送?

答案很简单,想想我们在日常生活中也有很多信号,比如常见的红绿灯信号。所以linux中的信号也是类似的。它无非是想提供一个机制在需要的时候告诉某个进程该怎样做。是一种规定,便于系统操作。就像我们都知道”红灯停,绿灯行“一样。

信号的发送者有很多,比如终端驱动程序,进程,系统。而接收者大多是一个进程。

那么怎么做就是给某进程发送一个信号呢?事实上,给进程发一个信号就是修改目标进程pcb结构体中的关于信号的字段(让进程记录此信号),想一想,用什么数据结构可以解决这个问题呢?

答案也很简单,进程是否接收到信号本身是一个原子问题。它要么收到,要么没收到。所以可以用位图来表示进程是否收到信号,只需要修改一个比特位(操作系统完成):收到信号就置1。如果有小伙伴不了解位图的概念,可以戳这里:STL容器BitSet(位图)——1道腾讯笔试题的正确打开方式

进程收到信号后,其可选的处理动作有以下三种:

  1. 忽略此信号。
  2. 执?行该信号的默认处理动作(终止该信号)。
  3. 提供?个信号处理函数(自定义动作),要求内核在处理该信号时切换到用户态执行这个处理函数,这种方式称为捕捉(Catch)一个信号。

Code(特殊信号举例)



知道了信号的基本概念,接下来我们通过代码来感受信号的真实存在性。

以 2号信号SIGINT:Ctrl + C为例。

代码:写一个死循环程序,并用进程命令查看。观察输入Ctrl + C前后系统中的进程变化

可以看到,在终端按下Ctrl + C产生一个硬件中断,向进程发送了2号信号,系统中pid为4940的进程(sig)被终止。



知识拓展1:前台进程与后台进程

以上边程序为例,我们在运行程序时在命令后边加一个”&“符号,再用命令查看系统中的进程,就会变成这样:

图中我们可以看到,加”&“运行程序后,系统发送了一个编号,编号后是对应进程的pid。用命令查看发现系统中确实多了一个编号为pid的进程。而且无法用Ctrl + C终止它。

其实这就是后台进程,一个程序运行命令后面加个&可以放到后台运行。形成后台进程,对于前台进程与后台进程,我们需要知道以下几点:

1.用命令查看时,发现后台进程STAT状态栏是R,所以有+表示前台进程,无+表示后台进程。

2.Ctrl-C产生的信号只能发给前台进程。因为后台进程使Shell不必等待进程结束就可以接受新的命令,启动新的进程。而前台进程运行时占用SHELL,它运行的时候SHELL不能接受其他命令。

3.Shell可以同时运行一个前台进程和任意多个后台进程。

4.前台进程在运行过程中用户随时可能按下Ctrl-C而产生一个信号,也就是说该进程的用户空间代码执行到任何地方都有可能收到SIGINT信号而终止,所以信号相对于进程的控制流程来说是异步(Asynchronous)的。

后台进程也不是任一进程都能做,要看实际情况。一般来说,如果某进程不需从键盘输入输出(交互少的)或者执行所需时间较长的话,就比较合适做后台进程。



为了证明ctrl+c就对应2号信号,接下来利用信号捕捉函数来简单实现对2号信号的捕捉。

代码:加入signal函数,它是一个信号捕捉函数,包在signal.h头文件中。

执行结果:


信号的产生



首先明确信号的4种产生条件:

1.通过终端按键(组合键)产生信号

2.硬件异常产生的信号

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

4.由软件条件产生信号

接下来,详细说明每种产生条件的含义和方法。

————通过终端按键(组合键)产生信号————

其实这种方式上面已经讲过一种了,就是Ctrl+C组合键。并且其对应信号为2号SIGINT

其实还有很多种通过组合键产生的信号,比如:Ctrl+\ 它对应的是3号信号SIGQUIT:

那么2号信号和3号信号都是终止进程的,他们有什么不同呢?区别就在这里:

如果去掉信号捕捉,键入Ctrl+\就会发现后边多了一个core dumped,这是什么鬼?

所以SIGINT的默认处理动作是终止进程,而SIGQUIT的默认处理动作是终止进程并且Cor Dump。下面解释什么是 Core Dump。



知识拓展2:核心转储core dumped

概念:当?个进程要异常终止时,可以选择把进程的用户空间内存数据全部保存到磁盘上,文件名通常是core,这叫做Core Dump。也叫核心转储,帮助开发者进行调试,在程序崩溃时把内存数据dump到硬盘上,让gdb识别 

一个进程允许产生多大的core文件取决于进程的 Resource Limit(这个信息保存在PCB中)。默认是不允许产生core文件的,因为core文件中可能包含用户密码等敏感信息,不安全。

用ulimit -a命令查看系统中的软硬件资源限制

 
其中core file size = 0,也就印证了上边的说法. 
上边还有其他资源的限制,比如: 
硬盘swap分区:用于内存数据换入换出的分区 
max locked memory:不允许换出的内存数据,就被锁住

但我们在开发调试阶段可以用ulimit命令改变这个限制, 允许产生core文件:ulimit -c 1024,允许core?件最大为1024K

更改后再次运行程序就可以看到core文件,其文件名后边的数字就是进程的pid号。

进程异常终止通常是因为有 Bug,比如非法内存访问导致段错误,事后可以用调试器检查core文件以查清错误原因,这叫做 Post-mortem Debug(事后调试)。

如图,输入命令就可以直接定位到是SIGQUIT信号引起的进程退出。



这里只讲这一种,有兴趣的小伙伴可以再百度下其他组合键产生的信号。

————-硬件异常产生的信号————

硬件异常产生信号是由硬件检测到并通知内核,然后内核向当前进程发送的信号。

例如当前进程执行了除以0的指令,CPU的运算单元会产生异常。内核将这个异常解释为SIGFPE信号发送给进程。

再?如当前进程访问了非法内存地址,MMU会产?生异常。内核将这个异常解释为SIGSEGV信号(11号)发送给进程:

加入引起段错误的代码:

运行:

这种硬件异常同样会引起核心转储:

所以我们可以知道:windows下程序崩溃也是因为进程收到了信号

而且有了信号的概念就可以很好理解C++中的异常了。

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

系统中定义了3个函数来给进程发送信号。

1.Kill命令(用kill函数实现):可以给任意进程发送任意信号(功能很强大)

比如继续运行刚才的死循环程序,用kill命令也可以向其发送3号SIGQUIT信号终止它。 

命令行上输入指令man 2 kill就可以看到函数kill(系统调用接口)的实现:

下面是它两个参数不同值所表示的含义:

下来利用kill函数实现仿kill命令的mykill命令::

step1:利用kill函数实现mykill.c 

step2:写一个进程 

用mykill向进程发送信号: 

这里可以发现,9号信号是不能被捕捉的。。

2.raise函数:给当前进程发送指定的信号(?己给?己发信号)。

函数原型: 

执行效果:

3.abort函数(stdlib.h):自己给自己发送signal abort(6)号信号(终止进程)

函数原型:void abort(void)

执行效果:

捕捉后进程会终止掉,不会频繁打印get a singal

————由软件条件产生信号 ————

SIGPIPE和SIGALRM信号都是由软件条件产生的信号。以alarm函数 和SIGALRM信号为例。

函数原型: unsigned int alarm(unsigned int seconds),在头文件unistd.h中。

作用机制:调用alarm函数可以设定?个闹钟,也就是告诉内核在seconds秒之后给当前进程发SIGALRM信号, 该信号的默认处理动作是终?当前进程。这个函数的返回值是0或者是以前设定的闹钟时间还余下的秒数。

举个栗子:

某人要小睡一觉,设定闹钟为30分钟之后响,20分钟后被别人吵醒了,但还想多睡一会儿。于是重新设定闹钟为15分钟之后响,“以前设定的闹钟时间还余下的时间”就是10分钟。

如果seconds值为0,表示取消以前设定的闹钟,函数的返回值仍然是以前设定的闹钟时间还余下的秒数

闹钟:在一段时间之后才产生的信号(这个机制是不是和sleep函数有点像呢。。。)

代码:

执行结果:


The End



信号产生后,在进程pcb中如何组织存储也是值得研究的问题。博主的下一篇博客中也会有介绍,敬请期待。

原文地址:https://www.cnblogs.com/LiuYanYGZ/p/9567092.html

时间: 2024-10-13 11:01:26

linux信号基本概念及如何产生信号的相关文章

10.2信号的概念

首先,每一个信号都有一个名字,这些名字都是使用相同的三个字母SIG 开始的.举例来说,SIGABRT是当进程调用数abort的时候生成的终止信号.SIGALRM是当函数alaram设置的定时时间到的时候生成的alarm信号.版本7已经有了15中信号:SVR4以及4.4BSD有31种不同的信号,FreBSD 8.0支持32中不同的信号:Mac OS X10.6.8以及Linux3.2.0各支持31中不同的信号:同时Solaris 10支持40中不同的信号.此外,FreeBSD,Linux以及Sol

信号的概念

信号的概念 信号(signal)--     进程之间通讯的方式,是一种软件中断.一个进程一旦接收到信号就会打断原来的程序执行流程来处理信号. 几个常用信号: SIGINT     终止进程  中断进程  (control+c) SIGTERM   终止进程     软件终止信号 SIGKILL   终止进程     杀死进程 SIGALRM 闹钟信号 进程结束信号 SIGTERM和SIGKILL的区别 SIGTERM比较友好,进程能捕捉这个信号,根据您的需要来关闭程序.在关闭程序之前,您可以结

[学习笔记]信号基本概念(中断和信号)/名称及常用信号/信号处理/signal函数实践

1基本概念 中断 q  中断是系统对于异步事件的响应 q  中断信号 q  中断源 q  现场信息 q  中断处理程序 q  中断向量表 异步事件的响应:进程执行代码的过程中可以随时被打断,然后去执行异常处理程序 生活中的中断和计算机系统中的中断 1)  无中断生活场景 张三看书,厨房烧水 2)有中断的生活场景 张三看书,设置闹钟,厨房烧水. 闹钟发出中断信号,张三把书合好(第20页),去厨房把开水事情处理好,张三重新打开20页进行阅读. 3)计算机系统的中断场景 中断源发出中断信号,CPU判断

一、进程与信号之信号的概念

信号:进程与进程之间通讯机制 信号是软件中断 信号是异步事件 信号来源:内核产生,常用信号kill(),raise(),alarm(),settimer()等 kill -l 查看linux所有 信号共64个 1-31 非实时信号发送信号可能回丢失,不支持信号排队 32-64实时信号 进程处理信号: 忽略信号 SIGKILL和SIGSTOP永远不能被忽略 忽略硬件异常 进程启动时SIGUSER1和SIGUSER2两个信号被忽略 执行默认操作 每个信号都有默认动作,大部分信号动作是终止信号 捕获信

信号(一)---信号的概念

信号是进程间可以用来相互通信的一种低级方法,是Linux系统中非常重要的内容.每个信号都有一个信号名,信号名的本质就是一个整型值,所有的信号名对应的信号值都定义在头文件<signal.h>中或者可以通过 kill 命令加上 -l 选项来查看.Linux系统中支持31种不同的信号,编号从 1 到 31 (信号编号为0有特殊意义,Linux中称为空信号),每种信号都有其不同的意义,如下图所示 注意:在使用信号的时候尽量使用信号名,而不要使用信号编号,这是因为有些信号在不同的系统中的编号可能是不同的

Linux signal 那些事儿(4)信号的deliver顺序【转】

转自:http://blog.chinaunix.net/uid-24774106-id-4084864.html 上一篇博文提到了,如果同时有多个不同的信号处于挂起状态,kernel如何选择deliver那个信号.          next_signal 负责从挂起信号中选择deliver的signo:当然,有线程显存私有的penging,有线程组共有的pending,对于线程而言,先从自己私有的pending中选,处理完毕私有的才会去处理线程组共有的pending,这个逻辑的代码在: in

linux中的两个非常重要的信号:SIGALRM信号和SIGCHID信号

在进行阻塞式系统调用时,为避免进程陷入无限期的等待,可以为这些阻塞式系统调用设置定时器.Linux提供了alarm系统调用和SIGALRM信号实现这个功能. 要使用定时器,首先要安装SIGALRM信号.如果不安装SIGALRM信号,则进程收到SIGALRM信号后,缺省的动作就是终止当前进程.SIGALRM信号安装成功后,在什么情况下进程会收到该信号呢?这就要依赖于Linux提供的定时器功能.在Linux系统下,每个进程都有惟一的一个定时器,该定时器提供了以秒为单位的定时功能.在定时器设置的超时时

2信号处理之:信号产生原因,进程处理信号行为,信号集处理函数,PCB的信号集,sigprocmask()和sigpending(),信号捕捉设定,sigaction,C标准库信号处理函数,可重入函数,

 1信号产生原因 2.进程处理信号行为 manpage里信号3中处理方式: SIG_IGN SIG_DFL                                            默认Term动作 a signal handling function 进程处理信号 A默认处理动作 term   中断 core    core(调试的时候产生) gcc –g file.c ulimit –c 1024 gdb a.out core ign      忽略 stop     停止

Linux HTTP 基本概念 (1)

APACHE的简介 APACHE是世界上最流行的Web服务器软件之一,当然,提供WWW服务的还有微软的IIS,它是由微软开发的,只能用在微软的操作系统上,而APACHE是一个自由软件.说到APACHE,还要联想到LAMP,这个近年来也是应用得非常广泛,LAMP就是:linux+apache+mysql+php.Apache的特点是简单.速度快.性能稳定. APACHE端口: TCP     80 HTTP相关的配置文件 服务目录                # /etc/httpd/ 主配置文