在生活中就有许多常见的信号,如红绿灯就是最常见的信号。
红绿灯信号没有产生,我们就已经知道如何处理这个信号,
红绿灯信号的产生相对于我们的工作是异步的,
红绿灯信号的产生,我们不一定会去立马执行,总是挑选最优时刻执行,因此能够被保存
信号就是向目标进程发送通知消息的一种机制。
它的产生是异步的,并且我们知道如何处理,会选择在合适的时候处理。
因为信号需要知道如何处理,所以必然会有标志认识信号,并有对应的方式处理。
kill -l
信号的形式是宏定义,既可以通过编号,也可以通过名称标识。
信号不是从0号位置而是从1号开始
是因为 0被设为进程正常退出时的状态码
从 1到 31是普通信号,本文主要介绍的就是普通信号。
信号本质就是用软件 来模拟中断行为
比如说OS发送了信号2 ,那么就会在 中断向量表中,找到函数指针,调用对应的方方法处理信号
这里有个简单的认识,后面会具体介绍。
信号的合适处理
就有三种情况:
1.立即处理2.忽略
3.用户自定义处理
必要知识:
Linux中,程序运行时,前台只能有一个进程,后台可以有许多进程。
bash也是进程,所以在进程启动时,默认会将bash切换到后台,那么在键盘输入,bash也不会识别。
比如说 进程 ./myfile 是启动前台进程
./myfile &是启动后台进程。
没有能力接收用户输入的是后台进程。
CTRL +c 是终止前台进程 CTRL + Z是暂停
因为前台进程不能被暂停,所以要立即被放到后台上
用于对信号重定向方法
本质就是将中断信号表上的函数指针替换
参数说明:
signum :信号标志
handler : 是一个函数指针 该函数指针的返回值是void 参数是int
举例使用:
组合按键CTRL+ c 是向发送 2 号信号,目的是终止前台进程
就对2号信号 重新写入方法
每隔一秒打印 I am running pid
CTRL +c 无法终止掉进程
OS如何知道键盘有数据输入?
这就涉及到中断,OS不可能一直轮询等待键盘的输入
CPU是有许多的引脚,每一个引脚通过中断控制器连接外设。
中断控制器上有编号,代表一个外设。
当键盘输入时,比如说2号引脚亮了,就会识别到是键盘输入,然后将数据传入OS
OS会识别是否为那32的特殊的信号,是的话将位图上的对应编号的0变为1 ,然后回调函数。
有了上面知识的铺垫,就来看一看信号产生的方式
首先就是最常见的键盘输出信号
ctrl+ z是暂停程序 ctrl+\是终止程序。
CPU通过中断的方式读取到键盘输入,交由OS识别是否为特点的信号,如CTRL+C 被识别为2号信号,然后交由函数指针的数组,回调对应的方法,终止进程。
对于普通信号来说,进程接收到某个信号,需要标识自己接收到。
标志的方式是位图
32个比特位 1--31标识信号
如果 6号进程被识别到
那么位图上第7位 就要从0-》1
所以
查看kill指令
man 2 kill
#include
#include
int kill(pid_t pid, int sig);
kill函数是系统调用
参数:
pid 是需要发送信号的进程sig 是信号编号
返回值
成功返回0
失败返回-1
举例使用kill:
下面设计一个简单的系统调用
main函数的可变参数
第二个参数是指针数组,里面放着是字符串的地址
第一个参数argc是字符串的个数
进程运行跟上pid 和信号
创建myfile.cc
创建一个简单的死循环,利用系统调用终止进程
进程被终止,就像我们常用的指令 kill -9 5690
raise向该进程发送
#include
int raise(int sig);
谁调用raise,就向谁发送信号
用户自定信号2函数的方法
五秒后,会调用信号2
输出get a signo:2
abort( )
#include
void abort(void);
向该进程发送信号6
一般来说,SIGABRT信号(信号6)通常表示程序中存在某种严重错误,如内存损坏、无效的参数或逻辑错误等,导致程序无法继续执行。 当程序接收到SIGABRT信号时,它会立即终止,并且不会执行任何清理操作(如关闭文件、释放内存等)。
是由硬件引起的。当我们的进程出现除0,和野指针,越界等等,程序会崩溃。本质上就是进程接收到OS发来的信号终止程序。那么OS是如何识别到,并触发信号。
除0异常
CPU是有寄存器,通常一个寄存器会维护一个变量。当我们进行算术运算时,将操作数放在俩个寄存器中,并将结果放到另一个寄存器中。此外cpu还有一组维护寄存器来维护寄存器状态(status),记录寄存器的移位,溢出等等。如果OS发现寄存器的状态被标记,则会识别出问题(比如除0溢出等)。OS会立刻发送硬件错误的信号给进程。将task_struct位图上的对应位置为1,调用指针数组的方法。
野指针
访问变量必须通过页表,建立地址空间和物理内存的映射关系。
而实际上在这个映射过程还必须通过MMU硬件的处理,来完成映射访问。
要进行访问时,会给出地址空间的地址,通过MMU计算内存地址。
既然MMU是硬件单元,必要会记录硬件状态,当我们要访问不属于我们的虚拟地址时,MMU的转化会失败,并写入状态信息。OS会识别到,并发送信号。
介绍alarm闹钟函数
unsigned int alarm(unsigned int seconds);
指定时间后,OS向进程发送一个信号SIGALRM
操作系统就是一个进程,C如何理解OS的执行
OS本身就是一个死循环,操作系统的执行是基于中断的。
在硬件的底层 有CMOS,CMOS是高频率的,周期性的,向CPU发送时钟中断
OS通过COMS向CPU发送高频的闹钟信号,每一次接收到信号,CPU通过中断信号向量表 调度执行方法,所以只要调度得好,就能完成所有任务。
所以alarm函数就是最基本的软件产生信号。
有些信号的Action是Core核心
对于Core行为的信号,OS会将核心代码进行核心转储(将内存中的数据,全部dump到磁盘中)
会在当前路径下生成core.pid的二进制文件。
ulimit -a //查看特定的资源
设置core资源的大小
ulimit -c 4096 //设置大小
core只针对当前的shall端,且云服务器默认不开启
因为核心转储会消耗太多的空间。
常用于gdb的异常调试