用户和内核模式在操作系统中有什么区别?


104

用户模式和内核模式之间有什么区别?为什么以及如何激活它们中的任何一个?它们的用例是什么?



1
@ CiroSantilli709大抓捕六四事件法轮功一个7年前提出的问题不能作为6年前提出的一个问题的副本而关闭。如果它们确实是重复的,则关闭应该是其他方式。
萨尔瓦多·达利

2
@SalvadorDali嗨,当前的共识是通过“质量”结束:meta.stackexchange.com/questions/147643/…由于“质量”是不可衡量的,因此我只接受投票。;-)可能归结为哪个问题使标题上最佳的newb Google关键字成为热门。我鼓励您仅在底部添加免责声明即可复制您的答案,并在该答案关闭时链接到该答案。
Ciro Santilli郝海东冠状病六四事件法轮功

Answers:


143
  1. 内核模式

    在内核模式下,执行代码对底层硬件具有完全且不受限制的访问权限。它可以执行任何CPU指令并引用任何内存地址。内核模式通常保留给操作系统的最低级别,最受信任的功能。内核模式下的崩溃是灾难性的;他们将停止整个PC。

  2. 用户模式

    在用户模式下,执行代码无法直接访问硬件或参考存储器。在用户模式下运行的代码必须委托给系统API才能访问硬件或内存。由于这种隔离提供了保护,因此用户模式下的崩溃总是可以恢复的。您计算机上运行的大多数代码都将在用户模式下执行。

阅读更多

了解用户和内核模式


想知道CPU何时运行操作系统代码,处理器处于哪种模式?
JackieLam 2013年

2
@JackieLam:它应该处于内核模式。
kadina 2014年

因此,就其本身而言,要运行用户空间进程,必须将其映射到内核空间
roottraveller

@rahul我怀疑可以通过用户模式获得参考内存,还是最简单的操作数据将导致像Java这样的昂贵的模式更改。
maki XIE

48

这是计算机可以运行的两种不同模式。在此之前,当计算机像一个大房间时,如果发生某些故障,它将使整个计算机停止运行。因此,计算机架构师决定更改它。现代微处理器在硬件中实现至少两个不同的状态。

用户模式:

  • 所有用户程序都执行的模式。它无权访问RAM和硬件。这样做的原因是因为如果所有程序都以内核模式运行,则它们将能够覆盖彼此的内存。如果需要访问这些功能中的任何一个,它将调用基础API。Windows启动的每个进程(系统进程除外)均以用户模式运行。

内核模式:

  • 所有内核程序都执行的模式(不同的驱动程序)。它可以访问所有资源和基础硬件。可以执行任何CPU指令,并且可以访问每个存储器地址。此模式保留给最低级别的驱动程序

切换如何发生。

CPU不会自动完成从用户模式到内核模式的切换。CPU被中断(定时器,键盘,I / O)中断。发生中断时,CPU停止执行当前正在运行的程序,切换到内核模式,执行中断处理程序。该处理程序保存CPU的状态,执行其操作,恢复状态并返回到用户模式。

http://zh.wikibooks.org/wiki/Windows_Programming/User_Mode_vs_Kernel_Mode

http://tldp.org/HOWTO/KernelAnalysis-HOWTO-3.html

http://en.wikipedia.org/wiki/Direct_memory_access

http://en.wikipedia.org/wiki/Interrupt_request


想知道CPU何时运行操作系统代码,处理器处于哪种模式?
JackieLam 2013年

1
@JackieLam:内核模式
Apurv Nerlekar '16

10

运行Windows的计算机中的处理器具有两种不同的模式:用户模式和内核模式。处理器根据处理器上运行的代码类型在两种模式之间切换。应用程序以用户模式运行,而核心操作系统组件以内核模式运行。尽管许多驱动程序在内核模式下运行,但某些驱动程序可能在用户模式下运行。

启动用户模式应用程序时,Windows会为该应用程序创建一个进程。该过程为应用程序提供了专用虚拟地址空间和专用句柄表。因为应用程序的虚拟地址空间是私有的,所以一个应用程序无法更改属于另一应用程序的数据。每个应用程序都是独立运行的,如果一个应用程序崩溃,则崩溃仅限于该一个应用程序。其他应用程序和操作系统不受崩溃的影响。

除了私有之外,用户模式应用程序的虚拟地址空间也受到限制。在用户模式下运行的处理器无法访问为操作系统保留的虚拟地址。限制用户模式应用程序的虚拟地址空间可防止应用程序更改甚至可能损坏关键操作系统数据。

在内核模式下运行的所有代码共享一个虚拟地址空间。这意味着内核模式驱动程序不会与其他驱动程序以及操作系统本身隔离。如果内核模式驱动程序意外写入错误的虚拟地址,则可能会破坏属于操作系统或其他驱动程序的数据。如果内核模式驱动程序崩溃,则整个操作系统崩溃。

如果您是Windows用户,一旦通过此链接,您将获得更多。

用户模式和内核模式之间的通信


6

CPU环是最明显的区别

在x86保护模式下,CPU始终处于4个振铃之一。Linux内核仅使用0和3:

  • 内核为0
  • 3个用户

这是内核vs用户态的最难,最快速的定义。

为什么Linux不使用环1和2:CPU特权环:为什么不使用环1和2?

如何确定当前铃声?

当前铃声是通过以下方式选择的:

  • 全局描述符表:GDT条目的内存表,每个条目都有一个Privl对环进行编码的字段。

    LGDT指令将地址设置为当前描述符表。

    另请参阅:http : //wiki.osdev.org/Global_Descriptor_Table

  • 段寄存器CS,DS等指向GDT中条目的索引。

    例如,CS = 0意味着GDT的第一个条目当前对于执行代码是活动的。

每个环能做什么?

CPU芯片的物理构造是:

  • 环0可以做什么

  • 环3无法运行多个指令并无法写入多个寄存器,最值得注意的是:

    • 不能改变自己的戒指!否则,它可能会将自己设置为环0,并且环将无用。

      换句话说,不能修改当前段描述符,该描述符确定当前环。

    • 无法修改页表:x86分页如何工作?

      换句话说,不能修改CR3寄存器,分页本身会阻止页表的修改。

      出于安全性/易于编程的原因,这可防止一个进程看到其他进程的内存。

    • 无法注册中断处理程序。通过写入存储位置来配置这些地址,这也可以通过分页来防止。

      处理程序在环0中运行,并且会破坏安全模型。

      换句话说,不能使用LGDT和LIDT指令。

    • 无法执行IO指令(如in和)out,因此可以进行任意硬件访问。

      否则,例如,如果任何程序可以直接从磁盘读取,则文件权限将无用。

      更确切地说,要感谢Michael Petch:操作系统实际上可能在环3上允许IO指令,这实际上是由Task状态段控制的。

      如果环3最初没有它,则它不可能允许自己这样做。

      Linux总是不允许这样做。另请参阅:Linux为什么不通过TSS使用硬件上下文切换?

程序和操作系统如何在环之间转换?

  • 当CPU开启时,它会在环0中开始运行初始程序(虽然不错,但这是一个很好的近似值)。您可以认为此初始程序是内核(但通常是引导加载程序,然后仍在环0中调用内核)。

  • 当用户级进程希望内核为其执行某项操作(例如写入文件)时,它将使用生成中断的指令,例如int 0x80syscall向内核发出信号。x86-64 Linux syscall你好世界示例:

    .data
    hello_world:
        .ascii "hello world\n"
        hello_world_len = . - hello_world
    .text
    .global _start
    _start:
        /* write */
        mov $1, %rax
        mov $1, %rdi
        mov $hello_world, %rsi
        mov $hello_world_len, %rdx
        syscall
    
        /* exit */
        mov $60, %rax
        mov $0, %rdi
        syscall
    

    编译并运行:

    as -o hello_world.o hello_world.S
    ld -o hello_world.out hello_world.o
    ./hello_world.out
    

    GitHub上游

    发生这种情况时,CPU会调用内核在引导时注册的中断回调处理程序。这是一个注册处理程序并使用它的裸机示例

    该处理程序在环0中运行,该环决定内核是否允许该操作,执行该操作并在环3中重新启动userland程序。x86_64

  • 当使用exec系统调用时(或内核将启动时/init),内核准备新的userland进程的寄存器和内存,然后跳转到入口点并将CPU切换到第3环

  • 如果程序试图做一些顽皮的事情,例如写入禁止的寄存器或内存地址(由于页面调度),CPU还会在环0中调用一些内核回调处理程序。

    但是由于用户空间很顽皮,内核这次可能会终止进程,或者发出警告并带有信号。

  • 内核启动时,它将设置一个固定频率的硬件时钟,该时钟会定期生成中断。

    该硬件时钟生成运行于环0的中断,并允许其计划唤醒哪些用户区进程。

    这样,即使进程未进行任何系统调用,调度也可能发生。

多环有什么意义?

分离内核和用户域有两个主要优点:

  • 更加容易地制作程序,因为您更确定一个程序不会干扰另一个程序。例如,一个用户态进程不必担心由于页面调度而覆盖另一程序的内存,也不必担心将硬件置于另一进程的无效状态。
  • 它更安全。例如,文件许可权和内存分离可能会阻止黑客应用读取您的银行数据。当然,这假定您信任内核。

怎么玩呢?

我创建了一个裸机设置,应该是直接操作环的好方法:https : //github.com/cirosantilli/x86-bare-metal-examples

不幸的是,我没有耐心举一个用户区示例,但是我确实进行了分页设置,因此用户区应该是可行的。我很乐意看到拉取请求。

另外,Linux内核模块在环0中运行,因此您可以使用它们来尝试特权操作,例如读取控制寄存器:如何从程序中访问控制寄存器cr0,cr2,cr3?获取细分错误

这是一个方便的QEMU + Buildroot设置,可以在不杀死主机的情况下进行尝试。

内核模块的缺点是其他kthreads正在运行,并且可能会干扰您的实验。但是从理论上讲,您可以使用内核模块来接管所有的中断处理程序并拥有系统,这实际上是一个有趣的项目。

负环

尽管英特尔手册中并未实际提及负环,但实际上有一些CPU模式具有比环0本身更多的功能,因此非常适合“负环”名称。

一个示例是虚拟化中使用的管理程序模式。

有关更多详细信息,请参见:

在ARM中,环被称为“异常级别”,但主要思想保持不变。

ARMv8中存在4个异常级别,通常用作:

  • EL0:用户区

  • EL1:内核(ARM术语中的“主管”)。

    svc指令(SuperVisor调用)一起输入,该指令以前称为swi 统一汇编之前,它是用于进行Linux系统调用的指令。Hello world ARMv8示例:

    你好

    .text
    .global _start
    _start:
        /* write */
        mov x0, 1
        ldr x1, =msg
        ldr x2, =len
        mov x8, 64
        svc 0
    
        /* exit */
        mov x0, 0
        mov x8, 93
        svc 0
    msg:
        .ascii "hello syscall v8\n"
    len = . - msg
    

    GitHub上游

    在Ubuntu 16.04上使用QEMU进行测试:

    sudo apt-get install qemu-user gcc-arm-linux-gnueabihf
    arm-linux-gnueabihf-as -o hello.o hello.S
    arm-linux-gnueabihf-ld -o hello hello.o
    qemu-arm hello
    

    这是一个注册SVC处理程序并进行SVC调用的裸机示例。

  • EL2:系统管理程序,例如Xen

    hvc指令一起输入(HyperVisor调用)。

    虚拟机管理程序是针对操作系统的,就像操作系统是针对用户的。

    例如,Xen允许您在同一系统上同时运行多个操作系统,例如Linux或Windows,并且为了安全性和调试的方便性,它们相互隔离,就像Linux对用户层程序所做的那样。

    虚拟机管理程序是当今云基础架构的关键部分:它们允许多个服务器在单个硬件上运行,从而使硬件使用率始终接近100%,并节省了大量资金。

    例如,直到2017年AWS 迁移到KVM时才使用Xen 。

  • EL3:再上一层。TODO示例。

    输入smc说明(安全模式调用)

ARMv8架构参考模型DDI 0487C.a - D1章-的AArch64系统级编程模型-图D1-1说明了这美丽的:

在此处输入图片说明

随着ARMv8.1虚拟化主机扩展(VHE)的出现,ARM情况发生了一些变化。此扩展允许内核有效地在EL2中运行:

在此处输入图片说明

之所以创建VHE,是因为KVM之类的Linux内核内部虚拟化解决方案已经超过Xen(例如,AWS向上述KVM的迁移),因为大多数客户端仅需要Linux VM,并且可以想象,它们全部集成在一个虚拟机中在项目中,KVM比Xen更简单,效率更高。因此,现在在这些情况下,主机Linux内核将充当管理程序。

请注意,也许是由于事后观察的好处,ARM如何比x86具有更好的特权级别命名约定,而又不需要否定级别:0为最低,3为最高。较高的级别往往比较低的级别创建的频率更高。

可以通过以下MRS指令查询当前的EL :当前的执行模式/异常级别等是什么?

ARM不需要提供所有异常级别,以允许不需要该功能的实现来节省芯片面积。ARMv8“异常级别”说:

一个实现可能不包括所有的异常级别。所有实现都必须包括EL0和EL1。EL2和EL3是可选的。

例如,QEMU默认为EL1,但是可以使用命令行选项启用EL2和EL3:qemu-system-aarch64在模拟a53通电时输入el1

代码片段已在Ubuntu 18.10上进行了测试。


1
因为这个问题是不特定于任何操作系统,in并且out可用于环3的TSS可以指向一个IO权限表的当前任务授权给所有或特定端口的读/写访问。
Michael Petch

当然,您将IOPL位设置为值3,则ring 3程序具有完全的端口访问权限,并且TSS IO权限不适用。
Michael Petch

@MichaelPetch谢谢,我不知道这一点。我已经更新了答案。
西罗Santilli郝海东冠状病六四事件法轮功

5

我将在黑暗中刺痛一下,猜想您在谈论Windows。简而言之,内核模式可以完全访问硬件,而用户模式则不能。例如,许多(如果不是大多数的话)设备驱动程序是以内核模式编写的,因为它们需要控制其硬件的更精细的细节。

另请参阅此Wikibook


2
作为程序员,这对您很重要,因为内核错误往往会给您带来比您可能习惯的严重得多的破坏。内核/用户区别的一个原因是内核可以监视/控制关键系统资源并保护每个用户免受其他用户的侵害。提醒自己,用户错误通常很烦人,不过有点简化了,但仍然很有用,但是内核错误往往会使整个计算机瘫痪。
亚当·利斯

3

其他答案已经解释了用户模式和内核模式之间的区别。如果您真的想详细介绍,则应该获得Windows Internals的副本 ,这是Mark Russinovich和David Solomon撰写的一本非常出色的书,描述了各种Windows操作系统的体系结构和内部细节。


2

什么

基本上,内核模式和用户模式之间的差异不依赖于操作系统,并且仅通过限制某些指令通过硬件设计在内核模式下运行才可以实现。诸如内存保护之类的所有其他目的只能通过该限制来完成。

怎么样

这意味着处理器处于内核模式或用户模式。使用某些机制,该体系结构可以保证只要将其切换到内核模式,就可以获取OS代码以运行。

为什么

有了这种硬件基础架构,可以在常见的操作系统中实现这些功能:

  • 防止用户程序访问整个内存,例如,不要让程序覆盖操作系统,
  • 防止用户程序执行敏感指令(例如那些更改CPU内存指针边界的指令),以使程序不破坏其内存边界。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.