内核态与用户态
正如标题,本文主要讨论用户态与内核态。文章主要从什么是用户态与内核态,这两个名词是对谁而言的;并且对两种态之间的切换给出详细步骤。
目录
- 一、计算机指令级别
- 二、用户态与内核态的概念
- 2.1 先搞清楚对象
- 2.2 概念
- 三、为什么会分内存态与用户态
- 四、用户态与内核态之间切换场景
- 4.1 用户态切换到内核态
- 4.2 内核态切换到用户态
- 五、切换的具体流程
- 5.1 用户栈与内核栈
- 5.2 流程
- 六、备注
一、计算机指令级别
在计算机的指令中,引入了指令级别的概念,Window下分为0~3级,Linux下分为0、3两级;
分级主要是为了区分不同的程序有不同的指令执行权限;
二、用户态与内核态的概念
2.1 先搞清楚对象
在搞清楚用户态与内核态之前,首先需要搞清楚,用户态和内核态是针对谁描述的?
也看了网上不少资源,很多博客会直接对用户态与内核态的区别直接上手做分析,但实际上了解这两者是针对谁而言,对之后的学习也非常有效果。
这里用户态与内核态是针对CPU而言的,是CPU的两种运行状态,也就是说再任意时刻CPU要么处于内核态要么处于用户态。
2.2 概念
-
内核态:
CPU处于执行操作系统程序的状态属于内核态;如果从指令级别层来看运行R0指令级别时CPU所处的状态。
-
用户态:
CPU处于执行用户程序的状态;同样从指令级别层来看运行R3指令级别时CPU所处的状态。
操作系统本质上也属于程序,而这些程序可以操作计算机的一切,这当然也包括计算机的各种硬件。操作系统的程序编程其实就是内核态程序的编程。
用户态的程序建立在操作系统之上,当CPU处于用户态的时候,CPU只能执行部分指令而不能操作整个计算机所有的硬件设备。
三、为什么会分内存态与用户态
这里的原因主要处于操作系统的安全性考虑;
设想一下,如果CPU没有内核态与用户态的概念,完全是一视同仁,所有用户编写的程序可以访问一切硬件资源包括内存。这种情况下写个病毒程序就太容易了,只要运行起来之后把内存的数据随便迁移,这样的场景对于整个系统安全性来说绝对是极其糟糕的。
因此来说,计算机所有硬件资源的使用权应该仅仅收回给操作系统,用户态的程序无权进行访问,如果用户态的程序需要调用硬件资源如读取网卡的数据,必须通过操作系统层面进行操作。
四、用户态与内核态之间切换场景
4.1 用户态切换到内核态
-
中断
这是三种方式中唯一一种主动发起的CPU状态切换;
当用户态程序需要调用内核态程序时(譬如用户态程序需要从磁盘读取文件),用户态会发出中断指令,如Linux的
int 80h
中断指令,当CPU执行到该指令的时候,会切换自己的状态然后根据int
命令后的地址去执行对应的内核态代码。 -
外围设备中断
这是一种被动方式发起的CPU状态切换;
比如CPU正在处于用户态执行用户程序,此时某个外围设备因为某些响应而向CPU发出了中断,假设此刻CPU正在处于用户态,那么这种情况CPU会保存用户态现场转去执行外围设备发出的中断。
-
异常
这也是一种被动方式发起的CPU状态切换;
当用户态程序正在运行过程中,内存中数据不全还有数据在磁盘中没有读取到内存,此刻就会发生缺页中断,也会逼迫CPU进入内核态。
4.2 内核态切换到用户态
内核态程序执行完毕
五、切换的具体流程
5.1 用户栈与内核栈
在了解两态的具体切换流程首先需要了解两个概念:用户栈与内核栈。
我们都知道程序在执行的过程中是离不开栈的数据结构,操作系统在创建程序进程的同时会创建与该程序对应的两个栈结构,分别用于用户态程序执行与内核态程序执行。
当用户态与内核态相互切换的时候,CPU要切换到不同的栈去执行程序,至于为什么不能共用一个栈结构,多半也是为了安全考虑,分为两个栈也就是两片内存区域天然就有了隔离性,自然也就安全了。
5.2 流程
- CPU指向内核态堆栈;
- 保护现场,将用户态栈中的下一条指令的地址保存到内核态的栈中,CPU执行完内核态代码之后能够恢复之前的用户态程序继续执行;
- 执行内核态代码;
- 现场恢复:执行完毕之后取出内核态堆栈中仅有的一条数据(其实就是期初放入的用户态堆栈的地址,而内核态的程序执行完毕之后自然也就不会存在多余的数据仍存储在内核栈中),进而CPU根据地址切换到对应的用户态程序地址。
六、备注
本文大体描述了内核态与用户态之间的联系,但创作背景是在没有完全看完权威的操作系统相关书籍情况下编写。上述知识大多数来源于网络上的博客或B站视频,可能其中存在不严谨的语句甚至错误,还请大家勘误。
网友评论