目录一、进程阻塞的过程二、阻塞队列三、对时钟中断与中断的思考四、虚拟地址的思考五、保存程序状态六、int 0x80 的思考七、中断源八、陷入机制九、MMU的简略描述十、王道题目知识点总结一、进程阻塞的过程进程调用了一个系统调用函数去访问资源CPU去执行系统调用的代码也就是内核代码内核代码里写了 if (资源不可用) { 阻塞当前进程执行阻塞原语; } 这个逻辑系统调用间接触发了内核中的阻塞原语。CPU 执行内核代码→ 内核代码里调用阻塞原语 → 把当前进程链入等待队列也就是说进程本身的代码不会管资源能不能用而是自己只调用了一个系统调用去访问资源至于资源是否可用、状态的切换都是由CPU执行操作系统的代码来完成的但这种行为算是进程主动的阻塞自己进程主动阻塞→ 强调的是触发点是进程自己发起的系统调用操作系统把进程阻塞→ 强调的是实际动作是内核执行的二、阻塞队列CPU是没有自己的阻塞队列的书上说的CPU阻塞队列其实都是那些阻塞事件的阻塞队列进程从事件的阻塞队列到CPU的就绪队列上后等待CPU的调度有了资源后CPU使用资源CPU执行代码去使用资源进程使用资源的过程也是代码也要CPU来执行资源准备好了CPU不会自动使用资源准备好了只是“可以继续用”不是“已经用了”其实就CPU回到没执行完的地方继续执行当然去使用资源的代码是程序员写的具体使用资源的底层是OS的代码的资源就绪后进程并不会自动使用资源CPU 调度该进程后会从上次阻塞的位置继续执行进程代码由这些代码程序员写的或 OS 提供的真正去访问和使用资源。三、时钟中断调度返回与中断响应遇到的问题问题来源书上说“假设进程1在执行的过程中收到一个时钟中断中断响应后CPU 从用户态切换到内核态中断处理程序接管 CPU。若进程 1的时间片到了需要调度则会调用调度程序从就绪队列中选中一个进程 2随后将当前的运行上下文保存到进程1的 PCB 中根据进程2的 PCB 恢复其上下文。随后通过中断返回到进程2”。在中断响应中CPU会保存断点和程状态将程序的返回地址和PSW送到栈或CPU特定寄存器中保存。这里的放回地址应该是进程1的地址进程1的返回地址被保存到了内核栈中对吧那为什么书是上说“随后通过中断返回到进程2”。保存的断点不应该是进程1的吗怎么回到进程2了所有的中断响应过程都会有关中断、保存断点和程序状态、识别异常和中断并转到相应的处理程序。在中断响应过程中保存进程1的断点返回地址和程序状态字PSW送到进程1的内核栈或特定的寄存器中每个进程创建时OS 会分配两样东西分配项说明PCB存进程所有管理信息 硬件上下文内核栈进程陷入内核时用跟进程同生共死内核栈不是临时的它跟 PCB 绑定在一起生命周期完全一致进程创建 → 分配内核栈 PCB → 进程运行/睡眠/被换出 → 进程销毁 → 内核栈才释放(这里的PC理解为要继续执行的指令地址也就是返回地址一般是当前PC的值或PC“1”的值我的简单理解在中断响应时CPU把进程1的PC和PSW压入进程1的内核栈然后执行中断处理程序如果是时钟中断且进程1的时间片用完了或者放弃CPU等等那么CPU就会执行调度程序此时会将CPU中寄存器的状态都保存在进程1的PCB中其中包括了esp(栈指针操作系统再把进程1内核栈中保存的PC值和PSW也保存在进程1的PCB中。然后把进程2的PCB中的寄存器的值恢复到CPU寄存器上其中就包括esp寄存器的值所以CPU的栈指针自然就指向了进程2的栈空间。中断返回主要就是弹出当前栈指针指向的栈空间中的值PC、PSW所以最终CPU处理完中断服务程序执行中断返回时就自然而然的“返回到进程2中”进程的内核栈始终会保存着这个进程的返回地址和PSW哦。四、虚拟地址的思考看这 : 虚拟地址空间就是方便你写代码的地址描述图假的这不就虚拟地址前面是地址后面是指令为什么有虚拟地址在一个程序编译好后例如进程A的代码段会存在一些指令mov eax, [850] 从起始地址为850处取出数据执行还有 JMP 等指令这些指令涉及到了指令和数据的地址。可见在形成可执行文件时就已经给出了每个指令和数据的地址。那么好进程在内存中调入时换进换出时那个指令所在的位置可能已经变了比如变成了400真实地址是400但在指令中写的是850 那么CPU去执行这个代码时就会找不到正确的地址。在中断响应中不是有一些其他的硬件来执行这一系列操作而是CPU自动执行的在它内部电路中设计好了只要发生中断CPU就自动去执行这个流程也就是中断响应那在中断响应中PC要指向中断服务程序的地址入口请问CPU都不知道内核代码的具体位置它怎么跳转到 那里去最好的结果不就是拿到进程中的保存的内核虚拟地址在执行时再转换到真实地址上去我们不关心应用程序或内核程序的代码的物理地址具体在哪我们只需要使用虚拟地址即可。在执行时通过页表找到真实的物理地址这步骤我们并不关心程序员/编译器/链接器只和虚拟地址打交道写代码、编译、链接时用的全是虚拟地址只有在CPU去找这个地址时才会涉及到真实的物理地址五、保存程序状态在中断响应中保存程序状态可以理解为就是保存PSW。六、int 0x80 的思考执行陷入指令int 0x80这里的int就是x86的软中断的指令执行它主动产生一个中断而0x80 表示中断号/中断向量号CPU知道了中断号知道了中断源就去中断向量表 找到中断向量中断服务程序的入口地址从而找到该中断源的中断服务程序 int 0x80 是系统调用的入口中断服务程序会进一步根据EAX不就eax寄存器吗大写我还以为是什么呢 中的系统调用号分发到具体的系统调用处理函数。七、中断源中断源就是能够引发中断的事件/设备常见分类硬盘是一个中断源 ✅硬盘完成读写后磁盘控制器会向 CPU 发一个硬件中断信号如 IRQ 14/15通知我干完了。系统调用也是一个中断源 ✅通过 int 0x80 或 syscall 指令主动触发软中断/陷入让 CPU 陷入内核态。每个中断源或者说每个中断向量都有对应的中断服务程序ISR硬盘的 IRQ → 对应硬盘驱动中的中断处理程序处理数据传输完成、错误处理等int 0x80 → 对应系统调用统一入口处理程序如 system_call再根据具体系统调用号分发不过要注意一个细节多个外部设备可能共享同一个 IRQ 线这时一个中断向量可能对应多个 ISR内核会依次调用。但逻辑上每个中断源都有自己专属的处理程序这是驱动开发的基本模型。总结一句话中断响应时硬件自动保存断点PC和程序状态PSW/FLAGS软件再保存其余现场int 0x80触发一个软中断让 CPU 从用户态陷入内核态跳转到系统调用统一入口处理程序用中断号索引中断向量表找到服务程序系统调用和硬盘都是中断源各自有对应的中断处理程序。所以每个中断源都有自己的一些中断处理程序。八、陷入机制所以“陷入”也只是一个机制int 就能产生中断系统调用也只是利用这个机制而已在 int 0x80 之前系统调用是要通过寄存器传参write(1, hello, 5);汇编代码mov eax, 4 ; sys_write mov ebx, 1 ; fd stdout mov ecx, msg ; buffer mov edx, 5 ; length int 0x801、用 eax 表示“要调用哪个系统调用”eax 系统调用号例如2、用其他寄存器传参数流程就是CPU 把eax/ebx/ecx/edx ..... 设置参数执行到int 0x80 陷入内核态跳转到系统调用服务程序的地址从eax 取出系统调用号查系统调用表 sys_call_tablr[eax] ,在去执行具体的系统调用函数九、MMU的简略描述十、王道题目知识点总结进程映像也就是进程实体就像是给进程在运行过程中拍了一张照片。主要包括三个部分程序段、相关数据段、PCB。程序是一个静态的概念由代码和数据组成进程是一个动态的概念由程序、和该程序的运行上下文组成PS进程时一个程序在运行时OS方便管理这个程序的执行而提出的概念它的堆、栈、通用寄存器的值、PC的值... ,都是记录在这个进程映像/实体随着程序的执行里面的值是不断在变化的所以与程序相比当然也只能和程序比最重要的特性就是动态。一个进程就是一个正在运行的程序由这个程序和在计算机中涉及到这个程序的所有状态信息组成无非就是在内存和CPU中的状态也就是运行上下文以及一些系统资源进程的生命周期是断断续续的并发的进程具有间断运行的特点进程具有失去封闭性进程的执行结果与速度有关使得进程的执行具有不可再现性会相互影响体现在速度不同共享变量而导致执行结果与速度有关优先级分为静态和动态动态优先级是随运行情况而随时调整的单处理器系统发生死锁时有可能进程全部都处于阻塞态并发进程执行的相对速度不是只由优先级有关最主要的还是与调度策略有关一个进程在其生命周期中可执行多个程序没弄懂正文段数据段代码段涉及用户级线程切换的事件不会设计操作系统导致创建新进程的事件 操作系统启动用户发出请求创建一个新进程(也就是用户与OS的交互会创建新..CPU执行一个进程代码执行到了创建新进程的系统调用
