Linux信号
Linux系列文章目录Linux系列前言一、背景知识铺垫1.1 信号的基本概念1.2 进程对信号的处理二、信号的产生2.1 前台进程和后台进程2.2 键盘组合键2.3 kill 命令2.4 系统调用2.4.1 signal()接口前言Linux中信号Signal是一种进程间通信IPC的机制它用来通知进程发生了特定的事件。进程接受到信号后会根据信号的类型结合自己的处理方式做出相应的处理。一、背景知识铺垫1.1 信号的基本概念Linux信号是一种异步通信机制用于在进程之间传递事件或在系统于进程之间进行交互。当发生某个特定事件时如用户输入特定组合建Ctrlc等、进程异常终止系统就会向相关进程发送信号。1.2 进程对信号的处理进程在被设计时就内置了识别信号的方法以及默认处理不同信号方式当进程接收到信号时并不一定会立即处理这也就要求进程需要具有保存信号的能力当等到合适的时候进程会根据信号的类型结合自己的处理方式法做出处理。进程在处理信号的方式默认处理方式进程内置的忽略信号自定义处理方式捕捉信号后使用用户设定的方法二、信号的产生穿插了一部分拓展知识2.1 前台进程和后台进程首先我们先来看下面这个程序#includeiostream#includeunistd.husing namespace std;intmain(){while(true){coutIm a crazy processPIDgetpid()endl;sleep(1);}return0;}当我们执行该程序后再输入ls、pwd可以看到指令并不会执行进程则一直运行当我们使用Ctrlc就可以将进程终止这样的进程就是前台进程。再次执行该程序这次我们以后台进程的形式执行该进程./可执行程序 ,可以发现当进程执行后我们再输入指令此时指令是可以成功执行的当我们使用Ctrlc时无法终止进程。这种进程为后台进程。Linux中一次登录一个终端一般配有一个bash而每个终端只允许有一个前台进程可有多个后台进程当我们执行./process时前台进程就由bash变为了./process而键盘输入是优先被前台进程获取的所以指令无法被执行但前台进程./peocess接收到Ctrlc信号时就会终止。这样我们再来理解第二个现象当我们以后台进程运行./process是此时bash仍被视为前台进程当用户输入指令是仍可被接收并执行此时再输入Ctrlc信号./process进程并没有接收所以没有终止。前台进程会独占终端直到进程执行完成或者被挂起在这期间终端无法接受其他命令输入用户只能与该进程进行交互。后台进程不会占用终端终端可以继续接受用户输入的其他命令用户可以在同一个终端中同时启动多个后台进程。前台进程其执行过程会受到用户操作的直接影响比如用户可以通过键盘输入来中断或暂停进程。如果终端关闭前台进程通常会被终止除非进行了特殊的设置。后台进程通常是长时间运行的不受终端关闭的影响除非明确地对其进行停止或重启操作。它按照自身的逻辑和任务需求在后台持续运行不会因为用户的一些常规操作而中断Ctrlc本质会解释为2号信号后面我们会验证2.2 键盘组合键这是我们在学习Linux过程中比较常用的一种向进程发送信号的方式它通过一些特定的键盘组合键来发送一些特殊的信号如Ctrlc终止进程。组合有很多种都比较简单这里我们想要介绍的是Ctrlc这类组合键是如何被转换为信号又是如何被进程接收的我们可以确定的意见事是CPU不能直接从键盘读取数据冯诺依曼体系结构那么这个工作只能交由操作系统来完成操作系统又是如何得知键盘有数据了呢我们根据下图来回答CPU上有很多针脚每个针脚对应一个硬件设备键盘、网卡当用户按下Ctrlc组合键时键盘发生硬件中断产生中断号通过对于针脚发送(充放电)给CPU通知CPU进行相关处理操作系统从CPU读取到中断号通过中断号在自己的中断向量表中索引到对应方法地址执行该方法读取键盘操作系统识别如果是数据直接读取如果是组合键就将他解释成对应信号如ctrlc解释为2号信号并将它读入键盘缓冲区一切皆文件再拷贝至用户缓冲区被进程接收进程执行对应处理方法。我们的信号处理方式异步通知、事件驱动等就是模拟的硬件中断因此信号又被叫做软件中断。2.3 kill 命令对于上面的后台进程我们可以通过kill指令的形式给它发送信号终止它可以通过kill -l查看信号种类0~31为普通信号34~64为实时信号我们不研究这里有多种信号来都能达到终止后台进程的要求如2号终止进程9号杀掉进程。使用格式kill -信号编号 进程PID.常用信号信号编号信号名称触发方式作用2SIGINTCtrlC终止前台进程3SIGQUITCtrl\终止进程并生成core文件9SIGKILLkill -9 pid强制终止进程不可被捕获或忽略15SIGTERMkill -15 pid正常终止进程进程可捕获并进行清理1SIGHUP终端连接断开等让进程重新初始化或终止18SIGCONTkill -18 pid继续执行暂停的进程19SIGSTOPkill -19 pid暂停进程不可被捕获或忽略20SIGTSTPCtrlZ暂停前台进程将其放入后台10SIGUSR1kill -10 pid用户自定义信号用于特定程序逻辑12SIGUSR2kill -12 pid用户自定义信号用于特定程序逻辑2.4 系统调用2.4.1 signal()接口#includesignal.htypedefvoid(*sighandler_t)(int);sighandler_tsignal(intsignum,sighandler_thandler);功能捕捉指定信号执行自定义功能参数signum: 要捕捉信号编号handler函数指针用互自定义的方法下面的程序我们使用signal函数捕捉二号信号执行我们自定义的方法。#includeiostream#includeunistd.h#includesignal.husing namespace std;voidhandler(intnum){coutI captured Signal No.numendl;return;}intmain(){sighandler_t_handlersignal(2,handler);while(true){coutIm a crazy process,PID:getpid()endl;sleep(1);}return0;}可以看到此时我们再使用Ctrlc信号程序就不会终止而是执行我们的自定义方法。上面的场景也完美的呈现了信号的异步性程序先调用singnl,但是此时进程没有收到信号所以这个函数不会执行当进程接收到信号后就会执行对于方法。需要注意的是并不是所有信号都可以被捕捉的我们可以通过下面的方式来验证