作者:弟羔羊之妙义
链接:https://www.zhihu.com/question/397142622/answer/1246315406
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
0、首先,我们明确一个概念,Linux所谓的用户态和内核态,本质是对CPU提供的功能的一层封装抽象。现代CPU,其设计目标主要是为了完美高效的实现一个多任务系统,多任务系统的三个核心特征是:权限分级、数据隔离和任务切换。以X86_64架构为例,权限分级通过CPU的多模式机制和分段机制实现,数据隔离通过分页机制实现,任务切换通过中断机制和任务机制(TR/TSS)实现。
1、然后,给内核态和用户态一个相对精确的概念定义。内核态和用户态的概念,是Linux为了有效实现CPU的权限分级和数据隔离的目标而出现的,是通过组合CPU的分段机制+分页机制而形成的。还是以X86_64架构为例,在当CPU处于保护模式下时(X86_64CPU有5种模式,保护模式是其中之一,此时CPU.CR0.PE=1),当CPU.CS=系统代码段时(CS.CPL=0)为内核态,此时通过CPU的指令有操控全部寄存器的权限(包括FLAGS和CR寄存器),当CPU.CS=用户代码段时(CS.CPL=3)为用户态,此时通过CPU的指令只有操控部分寄存器的权限。
2、所谓“一个进程主动跳进内核态”,是指该进程中的一个执行线程通过INT或者SYSCALL指令,使得当前线程的CS=系统代码段(这里还有不同的细节,不多说了)。
3、每个用户进程都有自己的虚拟地址空间,用户进程之间切换的时候,通过切换页表(CR3)来实现,不用改CS寄存器和DS寄存器。所以没有“代码映射在0-3G”一说。就像班级名称和学号,同样的学号在不同的班级代表不同的人,同样的虚拟地址在不同的页表中代表不同的物理内存空间。
4、内核态允许多个用户线程同时进入,不存在阻塞的现象,尤其是多核CPU的情况下。
5、除了用户线程可以进入内核态之外,还有内核线程,即内核自己要干的事情,这种线程只运行在内核态。
最后放几张图,希望对题主理解内核态和用户态有所帮助
图1:从CPU的寄存器视角看,指令运行所处的三种CPU状态
图2:从Linux线程角度看,指令运行所处的两种状态(要么属于某线程,要么黑色切换中)
图3:Linux下,线程类型*CPU状态决定数据空间