ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

操作系统中的信号神经 —— 中断与异常(2)

操作系统中的信号神经 —— 中断与异常(2) 为何要有中断中断是操作系统中相当核心的功能任何操作系统都包含了对于硬件设备的有效管理。处理器的素的和外围的硬件设备的速度不在一个数量级上因此如果让内核采用让处理器向硬件发出请求然后专门去等回应显然是差强人意。那么内核就应该在此期间去完成其他的事情等硬件完成了请求再回过头去处理。中断机制就让内核主动变为硬件主动。那么此时就有两种处理方法第一个就是轮询内核定期的对硬件设备进行状态查询作出处理。这样的话也会导致内核做太多的无用功。更好的方法是另一个机制让硬件在需要的时候向内核发出信号这就是中断机制对于中断的处理也同样软硬结合。中断、终止、陷阱、故障区分异常分为四类中断终止陷阱故障。中断他是有外部设备硬件发出的是异步发生的因为CPU也不知道这个中断什么时候发生处理完中断之后CPU会继续执行代码。故障CPU 执行当前指令内部产生同步执行某条指令的时候才触发。修复完故障之后重新执行刚才出错的那条指令。例如缺页异常。陷阱CPU 执行当前指令内部产生同步。主动触发故意触发指令执行成功后才跳入处理。陷阱处理完毕执行下一条指令不会重复执行触发陷阱的那条指令。终止同步严重硬件错误无法修复。会直接杀死进程。以上是根据英特尔CPU的具体异常分类。内核态与用户态内核态用户态是对当前进程或者说是CPU的状态描述而状态的转化也与中断有关联。同时还与虚拟地址空间有关虚拟地址空间页表是由虚拟到物理的桥梁。内核态无非就是对内核地址空间的访问用户态是对用户地址空间的访问通过页表的权限认定后才可访问。在CPU内部有寄存器存储了CPU的状态例如CS寄存器。要想对于这两种状态的理解更加深入必须具体到实际场景当中。硬件中断当用户从键盘输入数据网卡从网络当中读取数据的时候CPU会从中断控制器获取相应的中断号之后CPU由用户态转换到内核态陷入内核当中去中断向量表(IDT)当中查找对应的中断处理程序一个设备的中断处理程序是它的驱动程序的一部分——设备驱动程序是用于对设备进行管理的内核代码。 CPU停止执行当前进程的代码指令转而去执行操作系统的代码。在这之前CPU需要对原有的进程的硬件上下文数据进行保护即CPU自动进行压栈处理将数据资源存入内核栈当中即保护现场。说到硬件中断就不得不提时钟中断在我们电脑内部存在一个硬件——晶振。晶振可以向我们的CPU间接的周期性的发送硬件中断。CPU就会按照以上的流程去处理当前的中断这样也使得我们的操作系统得以周期性的执行。在这里时钟中断和当前进程的时间片有着千丝万缕的关系。首先CPU每次处理时钟中断内核都会更新全局的时间调整当前进程的时间片。如果当前进程的时间片耗尽就会触发进程调度相关函数。所以进程的调度也是软硬件结合实现的时间片只是一个计数器对计数器的更改又要依靠时钟中断来配合。在处理完中断之后CPU会把在内核栈当中的数据恢复继续去执行进程代码即恢复现场。软件中断软件中断是由CPU自己主动触发的就比如用户在代码当中去调用系统调用函数。在C语言库当中会对系统调用做一些封装里面会由汇编语言帮助我们CPU陷入内核态比如x86‑32位int 0x80x86‑64 现代syscall 指令。这是我们用户自己有意图的去陷入内核当中的之后CPU拿着系统调用号去内核当中去执行内核函数处理完毕后也会恢复现场。缺页异常(缺页中断)很多教材称缺页为缺页中断这是广义层面的叫法代表 “打断程序执行进入操作系统处理”但从 x86CPU 硬件架构严格分类它属于异常下的故障。最大特征处理完成后CPU 会重新执行那条触发缺页的内存访问指令。那么在什么时候会发生缺页异常呢例如我们在访问一块物理内存的时候MMU在通过页表当中的标志位判断之后发现无法映射此内存时会发生缺页异常当我们的文件内容还未加载到物理内存又要访问的时候会发生缺页异常。CPU从用户态陷入内核态。调用相应的中断处理函数。缺页异常与Linux本身的懒加载(懒分配)机制虚拟地址空间强相关。在我们用户new或者malloc一块空间时操作系统并不会立马就把物理内存给我们分配好只是分配了一块虚拟地址编号范围并没有实际的存储空间。只有等到CPU执行到此行代码的时候真正去读取解析这一块虚拟地址的时候CPU才会发生缺页异常内核才去分配物理页填充页表。此时才有了实际的存储空间却写入数据访问数据。我们在与文件系统关联在CPU发生缺页异常后会先对该虚拟地址进行合法性判断这也是缺页异常当中核心的步骤。首先虚拟地址空间是由链表结构组织起来的此时会将该虚拟地址在所有的VMA当中去遍历查找看该虚拟地址落在了哪一个VMA当中如果没有那么就是非法的操作。如果找到了就会进入权限判断逻辑比如对于只读的文件进行写操作就是非法的会通过信号的方式杀死进程等。通过这些检验之后在vm_are_struct当中会有struct file*这个结构体指针这是描述文件的结构体如果该指针为NULL则表明此地址只是需要去申请一块空间存储数据不与文件关联这也就是malloc的部分底层实现机制。反之如果有明确的指向代表与磁盘文件有关此时需要获取inode去分区当中去查找再将他的数据块以4KB为单位加载到物理内存当中填充页表构建映射。即可访问。对于Swap机制的处理也是同样的当内存资源紧张的时候会把部分“冷”资源换出到磁盘当中等到要访问的时候再通过以上操作将数据再载入内存。经过以上的操作之后算是对缺页异常的处理结束了CPU返回用户态重复执行当前的代码此时可以正常运行。从以上的解析当中不难发现有些缺页异常的情况是不需要I/O的比如只是申请一块内存使用对于他们的处理是极快的没有磁盘的I/O操作。总结那么对于中断的一些理解到这里就结束了。若有不足之处敬请指出。感谢阅读
返回列表