6

我了解系统调用的存在是为了提供对用户空间中不允许的功能的访问,例如使用read()系统调用访问 HDD。我也明白这些是由用户模式层以库调用的形式抽象出来的,例如fread(),以提供跨硬件的兼容性。

所以从应用程序开发人员的角度来看,我们有类似的东西

//library    //syscall   //k_driver    //device_driver
fread()  ->  read()  ->  k_read()  ->  d_read()

我的问题是;是什么阻止我将fread()andread()函数中的所有指令直接内联到我的程序中?指令是相同的,所以 CPU 应该以相同的方式运行?我没有尝试过,但我认为由于某种原因我失踪了,这不起作用。否则任何应用程序都可以获得任意内核模式操作。

TL;DR:是什么允许系统调用“进入”应用程序无法复制的内核模式?

4

2 回答 2

8

系统调用本身不会进入内核。更准确地说,例如,就您的应用程序而言,您调用的 read 函数仍然是一个库调用。内部所做的是read(2)使用一些中断或汇编指令调用实际的系统调用syscall(2),具体取决于 CPU 体系结构和操作系统。

这是用户空间代码执行特权代码的唯一方式,但它是一种间接方式。用户态和内核代码在不同的上下文中执行。

这意味着您不能将内核源代码添加到您的用户空间代码中并期望它做任何有用的事情,但会崩溃。特别是,内核代码可以访问与硬件交互所需的物理内存地址。用户态代码仅限于访问没有此功能的虚拟内存空间。此外,允许用户态代码执行的指令是 CPU 支持的指令的子集。一些 I/O、中断和虚拟化相关指令是禁止代码的示例。它们被称为特权指令,需要根据 CPU 架构处于较低的环或主管模式。

于 2013-05-24T13:06:29.353 回答
0

你可以内联它们。您可以直接通过 发出系统调用syscall(2),但这很快就会变得混乱。请注意,系统调用开销(上下文来回切换,内核检查,...),更不用说系统调用本身所花费的时间,通过内联消除噪音使您获得收益(如果有任何收益,更多的代码意味着缓存不是那么有用,并且性能会受到影响)。相信 libc/kernel 的人已经研究了这个问题并在你背后(在相关*.h文件中)为你完成了内联,如果它真的是一个可衡量的收益的话。

于 2013-05-24T11:05:17.613 回答