什么是内核态和用户态

总的来说,操作系统为了保证安全,不混乱,把CPU分成了特权模式和用户模式,也就是内核态和用户态,在操作敏感地带时,只能由内核操作,或者用户向内核请求,内核操作完了传给用户,也就是说用户的操作是受限的,仅能操作一些不敏感的东西。具体如下。

计算机的组成

计算机由运算器,控制器,存储器和输入设备,输出设备组成。
其中,运算器是无状态的;控制器配合一部分寄存器,但是寄存器数量很少,而且通常都很容易被修改;输入设备、输出设备只有接受指令的时候才动作。归根结底来说,整个计算机的运行状态几乎完全由存储器和少数几个寄存器控制。也就是说,如果一段程序能够完全控制物理内存,那么它就能做到任意改变计算机的状态。

在一开始的DOS系统上,就可以将要执行的应用程序加载变成了操作系统的一部分,然后混合起来运行,哪一段是用户程序、哪一段是操作系统并没有很明确的界限:用户程序退出就回到操作系统;用户程序触发软中断就到操作系统,返回又回到用户程序;用户程序自己可以访问大部分的硬件设备;用户程序甚至可以随意修改属于操作系统的数据。

于是,当时的许多病毒也毫不客气地把自己直接连接到了操作系统的程序里面,一旦执行就永远驻留成为操作系统的一部分。当时在DOS上流行的病毒可谓多种多样、五花八门。

单任务的情况下已经有不少问题了,到了多任务模式下,问题就更严重了:
因为多个应用程序要独立加载,如果两个应用程序执意要使用同一个内存地址,那就会发生严重的问题,操作系统必须防止这种事情发生。
外部设备一般来说都是很傻的,它并不知道多任务的存在,不管谁操作外部设备它都是一样响应。这样如果多个应用程序自己直接去操纵硬件设备,就会出现相互冲突。
有可能一个程序的数据被发送到了另一个程序等等。
操作系统必须自己响应硬件中断,通过硬件中断来切换任务上下文,让合适的任务在合适的时机继续执行。如果应用程序自己把中断响应程序改掉了,整个操作系统都会崩溃操作。
系统必须有能力在单个应用程序崩溃的情况下清理这个应用程序使用的资源,保证不影响其他应用程序;这就要求它必须清楚知道每个应用程序使用了哪些资源。
如果程序有办法读写所有的物理内存和寄存器,那任何保护手段都无济于事。所以要限制应用程序的行为,必须在应用程序和操作系统执行时有不同的状态,核心问题在于保护关键寄存器和重要的物理内存。

解决办法

CPU必须至少有两种不同的状态:操作系统状态和应用程序状态。
在不同状态下,相同指令会产生不同的结果,也就保证某些任务只有操作系统能执行,某些只有应用程序能执行。
操作系统必须有办法配合CPU,设置哪些内存可以访问,哪些内存不能访问(或者说只有操作系统状态下能访问),不能访问的包括操作系统自己的代码区和数据区、中断向量表等。
应用程序状态下不能直接访问硬件设备
CPU在触发中断时需要自动切换到操作系统状态(否则无法进行多任务切换)
操作系统状态可以自由切换到应用程序状态;应用程序状态不能任意切换到操作系统状态,但也需要有触发进入操作系统代码并切换到操作系统状态的能力(否则无法调用操作系统功能)

这里我们叫做操作系统状态的,在实际操作系统概念中就叫做内核态,在CPU设计上则叫做特权模式;我们叫做应用程序状态的,在实际操作系统概念中叫做用户态,CPU设计上叫做用户模式。

应用程序经常会需要使用一大片连续的内存空间,比如说涉及数组的一系列算法。如果内存空间全部都是动态分配的,那有些程序可能会不断地申请小块小块的空间,从而让内存空间碎片化,没有连续成片的内存。等这些程序退出之后,释放出来的内存都是小块、不连续的,操作系统就没法让其他应用程序使用连续成片的内存了。
安全上有隐患,虽然应用程序没法读取其他内存,但是应用程序可以知道哪些内存已经被其他应用程序用了,于是可以从内存地址的分配上分析出一些信息,例如当前操作系统可能执行了哪些其他应用程序,这些应用程序可能处于什么状态等等。还有可能因为CPU实现的bug导致应用程序能以意想不到的方式读取到不应当能读取的数据。
现代操作系统希望支持一些高级的内存管理方式,例如
虚拟内存——将一部分不使用的内存暂时放在磁盘上,这样可以用较少的内存支撑更多的应用程序;
写时复制——两个应用程序使用相同的内存块,希望能暂时使用同一个物理内存地址,但是其中一个需要修改的时候再将它复制成两份独立的内存块,从而节约内存。
现代MMU通常使用虚拟地址空间的技术来解决这个问题,也就是“用户空间”。在用户模式下,所有访问内存的地址实际上都是虚拟地址,它与实际的物理地址是对应不上的。这样,即便两个应用程序使用了相同的地址,它们也可以做到互不干扰,只需要通过技术手段让它们实际映射到不同的物理地址就行了。

应用程序怎么访问外部设备。

用户模式下应用程序无法直接访问硬件设备,但如果完全没法利用硬件设备,那就太不方便了。这两者的权衡是,应用程序通过操作系统使用硬件,也就是说应用程序给操作系统发起请求,操作系统处理请求时将请求转发到硬件,硬件响应后,再将请求转发回应用程序。许多硬件使用中断和DMA来传输信号或数据。
这种情况下,操作系统开始操作后,到硬件操作完成前会有一段空闲时间,这时候操作系统可以将当前应用程序挂起,先去执行其他的应用程序。当硬件操作完成时,会触发中断,中断向量表在内存中,是操作系统提前设置好的,指向了操作系统自己的代码;同时,这个中断也会立即强迫CPU进入特权模式。这时候操作系统就有机会来处理硬件返回的数据了,同时根据进程优先级,可以将之前挂起的进程重新切换回来重新开始继续执行。

参考链接:
https://www.zhihu.com/question/306127044/answer/555327651

你可能感兴趣的:(什么是内核态和用户态)