Operating system 操作系统如何允许用户空间程序与内核空间程序交互?

Operating system 操作系统如何允许用户空间程序与内核空间程序交互?,operating-system,Operating System,这不是一个关于特定操作系统的问题,但让我们以Windows为例。用户空间程序使用Windows API与内核空间通信。然而,我不明白这怎么可能。据微软网站称,API存在于用户空间中。为了访问kernelspace,它必须在kernelspace中,如果我理解正确的话。那么,windows API获得与内核空间对话的额外特权的机制是什么呢?该机构在哪个空间工作?这类东西对所有现代PC操作系统都通用吗 它是CPU,充当通过CPU寄存器在用户内存空间(在用户模式下可访问)到受保护内存空间(在内核模式下

这不是一个关于特定操作系统的问题,但让我们以Windows为例。用户空间程序使用Windows API与内核空间通信。然而,我不明白这怎么可能。据微软网站称,API存在于用户空间中。为了访问kernelspace,它必须在kernelspace中,如果我理解正确的话。那么,windows API获得与内核空间对话的额外特权的机制是什么呢?该机构在哪个空间工作?这类东西对所有现代PC操作系统都通用吗

它是CPU,充当通过CPU寄存器在用户内存空间(在用户模式下可访问)到受保护内存空间(在内核模式下可访问)之间传输信息的中介

下面是一个例子:

假设用户用高级语言编写程序。现在,当程序执行时,CPU生成虚拟地址


现在,在执行任何读/写操作之前,虚拟地址将转换为物理地址。由于转换机制(内存管理单元)只能在内核模式下访问,导致其存储在受保护的内存中,因此转换在内核模式下进行,物理地址最终保存到CPU的某个寄存器中,然后才发生读/写操作。

它是CPU,充当通过CPU寄存器在用户内存空间(在用户模式下可访问)到受保护内存空间(在内核模式下可访问)之间传输信息的中介

下面是一个例子:

假设用户用高级语言编写程序。现在,当程序执行时,CPU生成虚拟地址


现在,在执行任何读/写操作之前,虚拟地址将转换为物理地址。由于转换机制(内存管理单元)只能在内核模式下访问,导致其存储在受保护的内存中,因此转换在内核模式下进行,物理地址最终保存到CPU的某个寄存器中,然后才发生读/写操作。

正如您已经知道的,Windows内核向用户空间程序公开了许多功能。(如果你好奇的话)。这些系统调用都由一个唯一的编号标识,该编号不是Microsoft提供的公开文档界面的一部分。相反,当您从程序中调用公开函数时,当您安装(或更新)具有入口点的Windows时,会安装一个DLL,该入口点只是一个普通的、无特权的用户模式函数调用。这个DLL知道公共接口和当前运行内核中可用系统调用之间的映射。这些映射并不总是1:1,这允许在不破坏使用稳定接口的现有代码的情况下进行调整和增强

当一些用户代码调用其中一个函数时,它的作用是为系统调用准备参数,然后启动跳转到内核模式。跳转的具体发生方式取决于Windows当前运行的体系结构。事实上,它不仅在x86和Arm之间有所不同,甚至在AMD和Intel x86系统之间也有所不同。为了简单起见,我将在这里讨论现代Intel x86 32位机箱(使用)。例如,在x86上,大多数其他变化相对较小

在启动的早期,操作系统会做大量的工作来准备启用用户区和系统调用。理解这一点对于理解系统调用如何真正工作至关重要

首先让我们倒退一点,想想我们的用户名和核模式究竟是什么意思。在x86上,当我们谈论特权代码与非特权代码时,我们谈论的是“环”。实际上有4个(忽略虚拟机监控程序),但由于各种原因,除了ring0(内核)和ring3(用户区),没有人真正使用任何东西。当我们在x86上运行代码时,正在执行的地址(EIP)和正在读/写的数据来自段

在x86上进行虚拟寻址之前,数据段大多只是历史遗留下来的一个意外事件。然而,它们在这里对我们很重要,因为有一些特殊的寄存器定义了当我们执行指令或引用内存时,当前正在使用哪些段。x86上的段都定义在一个大表中,称为全局描述符表或。(还有一个本地描述符表LDT,但这不会进一步讨论当前的问题)。我们在这里讨论的要点是,表项的(神秘的)布局包括2位,称为DPL,它定义了当前活动段的特权级别。您会注意到,2位正好足以定义4个权限级别

因此,简而言之,当我们谈论“在内核模式下执行”时,我们实际上只是指我们的活动代码段(CS)和数据段选择器指向GDT中DPL设置为0的条目。同样,对于userland,我们有一个CS和数据段选择器,指向DPL设置为3的GDT条目,并且不能访问内核地址。(还有其他选择器,但是为了保持简单,我们现在只考虑“代码”和“数据”。 回到内核启动期间的早期:在启动期间,内核创建。(为了让SYSENTER正常工作,必须按照特定的顺序进行布局,但这主要只是一个实现细节)。还有一些“特定于机器的寄存器”控制处理器的行为。这些只能由特权代码设置。其中三个在这里很重要:

  • IA32\u系统输入\u ESP
  • IA32\u系统输入\u EIP
  • IA32\u系统输入\u CS
回想一下,我们在userland(ring3)中运行了一些代码,希望转换到ring0。让我们假设它已经保存了根据调用约定需要的所有寄存器,并将参数放入调用所需的正确寄存器中。我们