2.2.1 用户态、内核态的形成 -《zobolの操作系统学习札记》
内核态的出现,让计算机系统的权力向操作系统高度集中了。
操作系统分出内核态和用户态,就是为了进行不同等级的权限管理, 从而更好的适应多用户多任务并发的工作环境。
用户态和内核态的来源
在早期的单进程单用户操作系统中,是不存在两种用户态的。
随着进程和用户的出现,当时的计算机面临着一个重要问题,就是如何限制不同进程的操作的权限。(因为操作系统无法预测未来会出现什么样的进程)
把计算机内部想象成一个有条不紊的工厂,那必须在管理者和被管理者之间制定好规则,每个职位的权限都一定要确定好。
所以当时的工程师,就准备让一些危险的操作只允许操作系统的进程去做。如果其他用户进程想做这个操作,必须询先询问操作系统的意见。然后由操作系统去做,做完再把数据传给询问的用户进程。(比如I/O操作)
随着内核态的出现,操作系统进程/线程也正式凌驾于用户线程之上
权限本质就是可以做的事情不同。
CPU的内核态、用户态出现
如果只是操作系统对进程/线程的不同权限限制,还称不上“态”。但是随着操作系统权限限制功能的普及,CPU厂商也与时俱进,开始在硬件层进行权限限制。
操作系统厂商:CPU厂,现在我们都需要权限限制功能,能不能在硬件层做一个设计。软件层做不够安全,速度切换也较慢。
CPU厂商:好的,我在程序状态寄存器设计两位标志位,提供至少四个状态。你操作系统修改这个寄存器的状态位,我CPU就知道此时是什么权限等级了。
现代操作系统一般只使用最高ring 0和最低ring3,它们分别被成为内核态和用户态。
CPU会根据状态位的不同,限制可以执行的指令集,从而从硬件层做出限制。
操作系统通过修改CPU上寄存器的值,来做到切换权限,这种过程就是内核态和用户态的切换。
可见内核态、用户态是针对整个计算机系统来讲,而不是针对某个线程。
问1:我们如何定义高权限?
如果一个线程可以访问并修改计算机系统内的所有内存和寄存器。那么我们就认为这个线程具有最高的权限。
这种最高权限的线程,一般只属于操作系统。
问2:是所有的操作系统都分两种状态吗?
不是,早期的操作系统都不分两种状态,比如MS-DOS。分两种状态,是因为操作系统不得不面对 多用户权限多任务并发的 需要,而创建的。
问3:用户线程和内核线程跟内核态,用户态的关系
没什么关系。线程的切换必须是操作系统的高权限线程去决定(采用中断手段),不可能让普通线程自己去做。所以只要是线程的切换一定是在内核态进行的。
用户线程因为根本不是真正的线程,所以它在用户态的切换,本质只是一种伪切换。
用户线程、内核线程是真伪线程的关系。
内核态、用户态是权限高低的关系。
不建议说“一个线程此时在内核态”,因为内核态是对操作系统某时刻权限的描述。换成“操作系统此时处于内核态执行某个线程”更好。
例1:当某个线程向操作系统申请I/O操作的过程
- A线程因为权限不够,向操作系统申请I/O操作
- 操作系统同意,中断A线程。
- 操作系统修改CPU寄存器状态,使计算机进入内核态。
- 操作系统调用自身的高权限线程,执行I/O操作。(注意不是调用A线程去做)
- 修改CPU寄存器状态,使计算机进入用户态。
- 将数据送给A线程。
- 调用A线程。
内核态的出现源于多权限功能的设计,随着CPU厂商的硬件层面完善,正式形成。
内核态不仅限制了权限,而且操作系统一般情况下只允许自身的线程在内核态下工作。
计算机的权限进一步集中到操作系统之中,这促进了计算机体系结构的形成。