用户态、内核态

[TOC]

内核态和用户态?为什么?

假设没有这种内核态和用户态之分,程序随随便便就能访问硬件资源,比如说分配内存,程序能随意的读写所有的内存空间,如果程序员一不小心将不适当的内容写到了不该写的地方,就很可能导致系统崩溃。用户程序是不可信的,不管程序员是有意的还是无意的,都很容易将系统干到崩溃。

​ 正因为如此,Intel就发明了ring0-ring3这些访问控制级别来保护硬件资源,ring0的就是我们所说的内核级别,要想使用硬件资源就必须获取相应的权限(设置PSW寄存器,这个操作只能由操作系统设置)。操作系统对内核级别的指令进行封装,统一管理硬件资源,然后向用户程序提供系统服务,用户程序进行系统调用后,操作系统执行一系列的检查验证,确保这次调用是安全的,再进行相应的资源访问操作。内核态能有效保护硬件资源的安全。

补充:Unix/Linux的特权级
特权级是非常有效的管理和控制程序执行的手段,因此在硬件上对特权级做了很多支持,就Intel x86架构的CPU来说一共有0~3四个特权级,0级最高,3级最低,硬件上在执行每条指令时都会对指令所具有的特权级做相应的检查。对于Unix/Linux来说,只使用了0级特权级和3级特权级。也就是说在Unix/Linux系统中,一条工作在0级特权级的指令具有了CPU能提供的最高权力,而一条工作在3级特权级的指令具有CPU提供的最低或者说最基本权力。当程序运行在3级特权级上时,就可以称之为运行在用户态,因为这是最低特权级,是普通的用户进程运行的特权级,大部分用户直接面对的程序都是运行在用户态;反之,当程序运行在0级特权级上时,就可以称之为运行在内核态。

大内核和微内核

  1. 大内核
    大内核是将操作系统功能作为一个紧密结合的整体放到内核。
    由于各模块共享信息,因此有很高的性能。
  2. 微内核
    由于操作系统不断复杂,因此将一部分操作系统功能移出内核,从而降低内核的复杂性。移出的部分根据分层的原则
    划分成若干服务,相互独立。
    在微内核结构下,操作系统被划分成小的、定义良好的模块,只有微内核这一个模块运行在内核态,其余模块运行在
    用户态。
    因为需要频繁地在用户态和核心态之间进行切换,所以会有一定的性能损失。

用户态到内核态切换的三种方式:

  1. 外中断
    由 CPU 执行指令以外的事件引起,如 I/O 完成中断,表示设备输入/输出处理已经完成,处理器能够发送下一个输
    入/输出请求。此外还有时钟中断、控制台中断等。
  2. 异常
    由 CPU 执行指令的内部事件引起,如非法操作码、地址越界、算术溢出等。
  3. 系统调用:用户态的进程通过系统调用申请试用操作系统提供的服务程序完成工作,比如fork()就是执行了一个创建新进程的系统调用

常见的内核态

image-20201203193354517

用户态和内核态对于读写文件的操作有什么区别?

内核态:CPU可以访问内存的所有数据,包括外围设备,例如网卡、硬盘,CPU也可以将自己从一个程序切换到另一个程序
用户态:CPU只能受限地访问内存,且不允许访问外围设备,占用cpu的能力被剥夺,cpu资源可以被其他程序获取
所有的用户程序都是运行在用户态的,但是有的时候需要做一些内核态的事情, 例如从硬盘读取数据, 或者从键盘获取输入等. 而唯一可以做这些事情的就是操作系统, 所以此时程序就需要先操作系统请求以程序的名义来执行这些操作.

用户态进入内核态的方式

  1. 外中断
    由 CPU 执行指令以外的事件引起,如 I/O 完成中断,表示设备输入/输出处理已经完成,处理器能够发送下一个输
    入/输出请求。此外还有时钟中断、控制台中断等。
  2. 异常
    由 CPU 执行指令的内部事件引起,如非法操作码、地址越界、算术溢出等。
  3. 陷入
    在用户程序中使用系统调用。