Operating system 在操作系统的上下文中,环0和环3是什么?

Operating system 在操作系统的上下文中,环0和环3是什么?,operating-system,driver,Operating System,Driver,我一直在学习Windows中驱动程序开发的基础知识,我一直在寻找术语环0和环3。这些是指什么?它们是否与内核模式和用户模式相同?英特尔处理器(x86和其他处理器)允许应用程序使用有限的电源。为了限制(保护)关键资源,如IO、内存、端口等,与操作系统(本例中为Windows)联系的CPU提供特权级别(0为最高特权,3为最低特权),分别映射到内核模式和用户模式 因此,操作系统运行环0中的内核代码——由CPU提供的最高特权级别(0)——以及环3中的用户代码 有关更多详细信息,请参阅Linux x86环

我一直在学习Windows中驱动程序开发的基础知识,我一直在寻找术语环0和环3。这些是指什么?它们是否与内核模式和用户模式相同?

英特尔处理器(x86和其他处理器)允许应用程序使用有限的电源。为了限制(保护)关键资源,如IO、内存、端口等,与操作系统(本例中为Windows)联系的CPU提供特权级别(0为最高特权,3为最低特权),分别映射到内核模式和用户模式

因此,操作系统运行环0中的内核代码——由CPU提供的最高特权级别(0)——以及环3中的用户代码


有关更多详细信息,请参阅Linux x86环使用概述

了解环在Linux中的使用方式将使您对它们的设计目的有一个很好的了解

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

  • 0表示内核
  • 3为用户提供
这是内核与用户区之间最硬最快的定义

为什么Linux不使用环1和环2:

如何确定当前环?

通过以下组合选择当前环:

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

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

    另见:

  • 段寄存器CS、DS等,它们指向GDT中某个条目的索引

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

每个戒指能做什么?

CPU芯片的物理构造应确保:

  • 环0可以做任何事情

  • 环3不能运行多条指令并写入多个寄存器,最明显的是:

    • 不能改变自己的戒指!否则,它会将自身设置为环0,环将无效

      换言之,无法修改电流,这决定了当前环

    • 无法修改页面表:

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

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

    • 无法注册中断处理程序。这些都是通过写入内存位置来配置的,这也是通过分页来阻止的

      处理程序在环0中运行,将破坏安全模型

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

    • 无法执行输入/输出指令,如
      输入
      输出
      ,因此具有任意硬件访问

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

      更确切地说,这要归功于:操作系统实际上可以在环3上允许IO指令,这实际上是由控制的

      不可能的是,如果环3一开始没有它,它就允许自己这样做

      Linux总是不允许它。另见:

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

  • 当CPU打开时,它开始运行环0中的初始程序(这是一种很好的近似值)。您可以将此初始程序视为内核(但通常是)

  • 当userland进程希望内核为其执行某些操作(如写入文件)时,它使用一条生成中断的指令(如向内核发送信号)。x86-64 Linux系统调用hello world示例:

编译并运行:

as-o hello\u world.o hello\u world.S
ld-o hello_world.out hello_world.o
/您好,我们的世界

当这种情况发生时,CPU调用内核在引导时注册的中断回调处理程序。这是一本书

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

  • 当使用
    exec
    系统调用(或内核)时,新userland进程的内核将跳转到入口点,并将CPU切换到环3

  • 如果程序试图做一些顽皮的事情,比如写入禁止的寄存器或内存地址(因为分页),CPU还会调用环0中的某个内核回调处理程序

    但是,由于userland是顽皮的,内核这次可能会终止进程,或者给它一个带有信号的警告

  • 当内核启动时,它设置一个固定频率的硬件时钟,该时钟周期性地产生中断

    此硬件时钟生成运行环0的中断,并允许它计划唤醒哪些userland进程

    这样,即使进程没有进行任何系统调用,也可以进行调度

拥有多个戒指有什么意义?

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

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

我已经创建了一个裸机设置,这应该是直接操作戒指的好方法:

不幸的是,我没有耐心去做一个userland的例子,但我确实做了一次尝试
.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
.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
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