4.2 内核态与用户态
CPU能判断出指令类型,但是,它是如何区分正在运行的程序是内核程序还是应用程序的呢?
其实,CPU有两种状态,“内核态”和“用户态”。
当CPU处于内核态时,说明此时正在运行的是内核程序,此时可以执行特权指令。
当CPU处于应用态时,说明此时正在运行的是应用程序,此时只能执行非特权指令。
CPU中有一个寄存器叫做 程序状态字寄存器(PSW), 其中有个二进制位,1表示内核态,0表示应用态。
用户态和内核态是如何进行转化的?
内核态->用户态: 执行一条特权指令–修改PSW标志位为“用户态”,这个动作意味着操作系统主动让出CPU使用权;
用户态->内核态: 由“中断”引发,硬件自动完成变态过程, 触发中断信号意味着操作系统将强行夺回CPU的使用权。
5 中断和异常
中断的作用
CPU上会运行两种程序,一种是操作系统内核程序,一种是应用程序。在合适的情况下,操作系统内核会把CPU的使用权主动让给应用程序。
而 “中断”是让操作系统内核夺回CPU使用权的唯一途径。
如果没有“中断”机制,那么一旦应用程序上CPU运行,CPU就会一直运行这个应用程序,就没有并发的一席之地了。
中断的类型
内中断:与当前执行的指令有关,中断信号来源于CPU内部;
外中断:与当前执行的指令无关,中断信号来源于CPU外部。
内中断的实例: 试图在用户态下执行特权指令、执行除法指令时发现除数为0。即:若当前执行的指令是非法的,则会引发一个中断信号。
当然,有时候应用程序想要请求操作系统内核的服务,此时就会执行一条特殊的指令:陷入指令, 该指令会引发一个内部中断信号。
执行陷入指令意味着应用程序主动将CPU控制权还给操作系统内核。系统调用就是通过陷入指令完成的。
外中断的实例: 时钟中断–由时钟部件发来的中断信号。每一条指令执行结束时,CPU都会例行检查是否有外中断信号。
内中断也称异常
分为如下三种:
陷阱、陷入(trap): 由陷入指令引发,是应用程序故意引发的;
故障(fault): 由错误条件引起的,可能被内核程序修复。内核程序修复故障后会把CPU的使用权交还给应用程序,让它继续执行下去,如缺页故障;
终止(abort): 由致命错误引起,内核程序无法修复该错误,因此一般不再将CPU使用权还给引发终止的应用程序,而是直接终止该应用程序。如整数除以0、非法使用特权指令。
中断机制的基本原理
不同的中断信号,需要用不同的中断处理程序来处理。 当CPU检测到中断信号后,会根据中断信号的类型去 查询“中断向量表”, 以此来找到相应的中断处理程序在内存中的存放位置。具体硬件上的实现,将在计算机组成原理中探讨。
6 系统调用
6.1 什么是系统调用
“系统调用” 是操作系统提供给应用程序(程序员/编程人员)使用的接口,可以理解为一种可供应用程序调用的函数,应用程序可以通过系统调用来请求获得操作系统内核的服务。
❓ 系统调用与库函数的区别?
答:系统调用应该是比高级语言的库函数更为底层的接口。不过,并不是所有库函数都涉及到系统调用,比如:取绝对值的函数… …
系统调用与库函数的区别见下图:
6.2 为什么系统调用是必须的?
例子见下图:
那么什么功能需要用到系统调用呢? 王道书给出了如下分类:
设备管理: 完成设备的 请求/释放/启动 等功能
文件管理: 完成文件的 读/写/创建/删除 等功能
进程控制: 完成进程的 创建/撤销/阻塞/唤醒 等功能
进程通信: 完成进程之间的 消息传递/信号传递 等功能
内存管理: 完成内存的 分配/回收 等功能
系统调用相关功能涉及系统资源管理,进程管理等操作,需要特权指令,所以系统调用处理需要由操作系统欸和程序负责完成运行在核心态。用户程序可以执行trap命令发起系统调用,请求OS服务,相当于把CPU使用权交给OS内核程序。用户程序不能直接执行对系统影响很大的操作,必须通过系统调用的方式请求OS执行,以便保证系统稳定性和安全性,防止用户程序随意更改/访问重要的系统资源,影响其他进程执行。
6.3 系统调用的过程
传递系统调用参数->执行陷入指令(用户态)->执行相应的内请求核程序处理系统调用(核心态)->返回应用程序。
OS运行环境理解为:用户通过OS上层程序,而这个程序依赖OS底层管理程序提供服务支持,当需要管理程序服务时,系统则通过硬件中断机制进入核心态,运行管理程序,也可能是程序运行出现异常情况,被动需要管理程序服务,通过异常处理来进入核心态,管理程序运行结束时,用户程序需要继续运行,此时通过响应的保存的程序现场退出中断处理程序/异常处理程序,返回断点处继续执行。
需要注意以下两点:
陷入指令是在用户态执行的,执行陷入指令后立即引发一个内中断,使CPU进入核心态;
发出系统调用请求是在用户态,而 对系统调用的相应处理是在核心态完成的。
7 操作系统的体系结构
操作系统的内核
内核是操作系统最基本、最核心的部分。实现操作系统内核功能的那些程序就是内核程序。
操作系统内核需要运行在内核态;
操作系统的非内核功能运行在用户态。
而内核分为大内核和微内核,具体图示如下:
大内核: 将操作系统的主要功能模块都作为系统内核,运行在核心态。
优点:高性能;缺点:内核代码量大,结构混乱,难以维护。
微内核: 只把最基本的功能保留在内核。
优点:内核功能少,结构清晰,方便维护;
缺点:需要频繁地在核心态和用户态之间切换,性能低。