这不是一个关于特定操作系统的问题,但让我们以Windows为例。用户空间程序使用Windows API与内核空间进行通信。但是,我不明白这是怎么回事。根据MS网站,API存在于用户空间中。为了访问内核空间,如果我理解正确的话,它必须在内核空间中。那么windows API获得与kernelspace对话的额外权限的机制是什么?该机制在哪个空间运作?对于所有现代PC OS而言,这种事情是否普遍存在?
答案 0 :(得分:3)
正如您已经意识到Windows内核向用户空间程序提供了大量设施。 (如果你有点好奇there's a list of system calls)。这些系统调用都由唯一编号标识,该编号不是Microsoft提供的公开记录界面的一部分。相反,当您从程序中调用公开公开的函数时,安装(或更新)具有入口点的Windows时会安装DLL,该入口点只是普通的非特权用户模式函数调用。此DLL知道公共接口与当前运行的内核中的可用系统调用之间的映射。这些映射并不总是1:1,它允许调整和增强,而不会使用稳定的接口破坏现有代码。
当某些用户态代码调用其中一个函数时,其作用是为系统调用准备参数,然后启动跳转到内核模式。跳转的确切方式特定于Windows当前运行的体系结构。事实上,它不仅在x86和Arm之间变化,而且在AMD和Intel x86系统之间甚至变化。为简单起见,我将在这里谈谈现代Intel x86 32位情况(使用SYSENTER instruction)。在x86上,大多数其他变体都相对较小,例如int 2Eh
was used prior to SYSENTER support。
在启动早期,操作系统会做很多工作来准备启用用户空间和系统调用。理解这一点对于理解系统调用如何真正起作用至关重要。
首先让我们回顾一下,然后考虑userland和kernelmode究竟是什么意思。在x86上,当我们讨论特权代码和非特权代码时,我们谈论" ring"。实际上有4个(忽略虚拟机管理程序)但由于各种原因,除了ring0(内核)和ring3(userland)之外,没有人真正使用过任何东西。当我们在x86上运行代码时,正在执行的地址(EIP)和正在读取/写入的数据来自段。
细分市场大多只是x86上虚拟寻址之前遗留下来的历史事故。然而,它们对我们来说很重要,因为有一些特殊的寄存器可以定义当我们执行指令或以其他方式引用存储器时当前正在使用哪些段。 x86上的段都在一个大表中定义,称为全局描述符表或GDT。 (还有一个本地描述符表,LDT,但这不会在这里进一步讨论当前的讨论)。我们在这里讨论的重点是表项的(奥术)布局包括2位,称为DPL,它定义了当前活动段的权限级别。您会注意到2位正好足以定义4个权限级别。
所以简而言之,我们谈论"在内核模式下执行"我们只是意味着我们的活动代码段(CS)和数据段选择器指向GDT中DPL设置为0的条目。同样对于userland,我们有一个CS和数据段选择器指向GDT条目,DPL设置为3和无法访问内核地址。 (还有其他选择器,但为了保持简单,我们现在只考虑"代码"和#34;数据"现在)。
在内核启动期间回到早期:在启动期间,内核会创建GDT entries we need。 (这些必须按照SYSENTER的特定顺序进行布局,但这主要只是一个实现细节)。还有一些"机器专用寄存器"控制我们的处理器行为的方式。这些只能由特权代码设置。其中三个重要的是:
回想一下,我们在userland(ring3)中有一些想要转换到ring0的代码运行。让我们假设它已根据调用约定保存了所需的任何寄存器,并将参数放入调用所需的正确寄存器中。然后我们点击了SYSENTER指令。 (实际上它使用KiFastSystemCall
我认为)。 SYSENTER指令很特殊。它根据机器特定寄存器IA32_SYSENTER_CS中的内核设置值修改当前代码和数据段选择器。 (堆栈/数据参数值计算为IA32_SYSENTER_CS的偏移量)。随后,堆栈指针本身(ESP)被设置为内核堆栈,该堆栈设置为先前处理系统调用并保存到MSR IA32_SYSENTER_ESP中,同样也用于EIP来自IA32_SYSENTER_EIP的指令指针。
由于CS选择器现在指向GDL条目,DPL设置为0,EIP指向内核堆栈上的内核模式代码,此时我们在内核中运行。
从此开始,内核模式代码可以从内核和用户空间读取和写入内存(有一些适当的注意事项),以承担执行系统调用所需的实际工作。根据调用约定,可以从寄存器等读取系统调用的参数,但是可以访问实际指向用户区或内核对象句柄的任何参数,以读取更大的数据块。
当系统调用结束时,该过程基本上是相反的,我们最终返回用户区,选择器使用DPL 3。
答案 1 :(得分:1)
它的CPU充当中间,用于通过CPU寄存器在用户存储空间(在用户模式下可访问)到受保护的存储空间(在内核模式下可访问)之间传输信息。
这是一个例子:
假设用户使用更高级别的语言编写程序。现在,当执行程序时,CPU会生成虚拟地址。
现在,在发生任何读/写操作之前,虚拟地址将转换为物理地址。因为转换机制(内存管理单元)只能在内核模式下访问,导致它存储在受保护的内存中,转换发生在内核模式下,物理地址最终保存到CPU的某个寄存器中,然后只读取/写操作发生。