一、信号处理

信号的处理,不是立即处理,而是可以等一会在处理,在合适的时候,进行信号的处理。
合适的时候处理->进程从内核态,返回用户态的时候!(信号检查)
如果信号是默认或者忽略?比自定义捕捉更简单
我们在执行自定义方法(用户写的)->OS必须以用户身份执行
sigreturn是通过在两个函数栈帧中间修改地址来达到的。
特别注意:进程只要会被调度,代码一定会进入内核,因为时间片耗尽,操作系统就要把进程从cpu上剥离下来,就要进入内核代码。
内核态和用户态
硬件话题:
外设就绪->发送中断到中断控制器,中断控制器记录中断号->中断控制器通知CPU->CPU得知中断,获取中断号(如此一来哪一个外设准备好了,CPU就知道了)
软件话题:
CPU保护现场->CPU得知中断号,执行中断处理例程->把中断号当下标,索引中断向量表中找到对应的终端处理方法,执行->执行完毕,恢复现场,处理完毕中断,执行之前的工作。
OS怎么知道键盘上有数据了?硬件中断
信号纯软件,本质是用软件,来模拟硬件中断的。
发中断---发信号,保存中断号---保存信号,中断号---信号编号,中断处理方法---自定义捕捉
OS是怎么运行的,硬件中断
当没有中断到来的时候,OS是暂停的。
由外部设备触发的,中断系统流程,叫做硬件中断。
操作系统就是基于中断,进行工作的软件。
CPU内置时钟源,时钟源可以持续触发时钟中断(以固定的,特定的频率,向CPU发送特定的中断),操作系统就在硬件时钟中断的驱动下,进行调度了。
在时间片轮转调度中,时钟中断减少当前进程的剩余时间片。当时间片耗尽时,触发调度器切换进程。
时钟中断是操作系统的"心跳",其功能涵盖进程管理、时间同步、资源监控、网络协议等多个层面。
软中断
软中断举例:
除0,CPU中存在EFLAGS标志位用来判断溢出,规定成为一种CPU内部触发的中断。除0归结为处理异常的中断方法。野指针,指针重复释放,缺页中断属于CPU内存管理,也是CPU内部触发的中断。
CPU内部自己可以让软件触发中断 -> CPU的指令集,x86:int,x86_64:syscall->C/C++代码本质就是编译成了指令集+数据
指令集int,syscall可以自动让CPU触发一次中断。
中断需要OS内置 中断处理方法 和 获取中断号。
以1.0版本的linux内核举例,0x80为 int 和 syscall 的中断处理方法的地址,中断处理方法主要做两件事:1.获取系统调用号n;2.调用系统调用方法(当然,肯定要做安全检测)sys_call_table[n]()
OS会内置系统调用表,每一个系统调用,都有一个唯一的下标,这个下标叫做 系统调用号
open和fork不是OS提供的,OS不提供任何系统调用接口,OS只提供系统调用号。
open可以简单理解成:
int open()
{
move eax 5; //将系统调用号存到寄存器
syscall or int 80; //让CPU主动进行软中断,执行中断处理方法,进而执行系统调用
}
总结:
- 操作系统就是躺在中断处理例程上的代码块!
- CPU内部的软中断,比如int 0x80或者syscall,我们叫做 陷阱(主动)。
- CPU内部的软中断,比如除零/野指针等,我们叫做 异常(被动)。
- 用户层怎么把系统调用号给操作系统? - 寄存器(比如EAX)
- 操作系统怎么把返回值给用户?- 寄存器或者用户传入的缓冲区地址
- 系统调用的过程,其实就是先int 0x80、syscall陷⼊内核,本质就是触发软中断,CPU就会自动执行系统调用的处理方法,而这个方法会根据系统调用号,自动查表,执行对应的方法
- 系统调用号的本质:数组下标