进程处理信号的方式
1.默认动作
2.忽略
3.自定义动作,通过signal接口捕捉信号
键盘数据是如何输入给内核的?OS怎么知道键盘上有数据了?ctrl+c是如何变成信号的?
键盘会通过中断单元给操作系统发送中断信号,然后操作系统会从中断向量表中查找对应的中断信号(中断向量),就会知道读取键盘的方法,接着操作系统会对读取的数据进行判断,控制ctrl+c转换成为2号信号发送给进程。
除零错误
每一个进程的上下文都包括cpu中各种寄存器的状态,因此进程切换也会改变cpu中寄存器的状态。
进程中的除零错误会导致cpu中的状态寄存器的溢出标志位改变,cpu也是硬件,此时操作系统就能收到信号,进而给进程发送信号。
野指针
野指针是指虚拟地址到物理地址的转化失败,而页表中虚拟地址到物理地址得转化是由MMU(内存管理单元控制得,也是一个硬件),因此一旦地址转化失败操作系统就会知道,进而给进程发送野指针信号。
为什么服务器上面的core功能是关闭的?
一般服务器出现异常会有自动程序重启服务器,但有的程序异常终止后再重启还会立刻异常终止,这就会导致很多core.pid文件疯狂写入磁盘,导致更严重的问题。
信号的保存与捕捉
重入函数
volatile 关键字
volatile int flag = 0;
void handler(int signo)
{
cout << "catch a signal: " << signo << endl;
flag = 1;
}
int main()
{
signal(2, handler);
// 在优化条件下, flag变量可能被直接优化到CPU内的寄存器中
while(!flag); // flag 0, !falg 真
cout << "process quit normal" << endl;
return 0;
}
以上述代码为例,若flag不是关键字,在捕捉到2号信号进行自定义处理时,会把flag置为1,但是之后while循环还是没有结束,因为为了提高效率,编译器可能直接把初始的flag(0),直接放入到cpu中进行while判断,不会每次判断的时候都从内存中读取flag。这样即使已经更改了flag的值,cpu中记录的还是flag的初始值。而volatile的作用就是让cpu再次看到内存中更新后的flag的值。