我了解系统调用的存在是为了提供对用户空间中不允许的功能的访问,例如使用read()
系统调用访问HDD。我也理解这些是由用户模式层以库调用形式(例如fread()
)抽象出来的,以提供跨硬件的兼容性。
因此,从应用程序开发人员的角度来看,我们有之类的东西;
//library //syscall //k_driver //device_driver
fread() -> read() -> k_read() -> d_read()
我的问题是;什么阻止我将fread()
和read()
函数中的所有指令直接内联到我的程序中?说明是一样的,所以CPU应该以相同的方式运行?我没有尝试过,但我认为这是因为某些原因我失踪了。否则任何应用程序都可以获得任意内核模式操作。
TL; DR:允许系统调用进入'应用程序无法复制的内核模式?
答案 0 :(得分:8)
系统调用本身不会进入内核。更准确地说,例如,就您的应用程序而言,您调用的读取函数仍然是库调用。内部read(2)
使用某些中断或syscall(2)
汇编指令调用实际系统调用,具体取决于CPU架构和操作系统。
这是userland代码执行特权代码的唯一方法,但这是间接方式。 userland和内核代码在不同的上下文中执行。
这意味着您无法将内核源代码添加到您的用户态代码中,并期望它可以执行任何有用但崩溃的操作。特别是,内核代码可以访问与硬件交互所需的物理内存地址。 Userland代码仅限于访问不具备此功能的虚拟内存空间。此外,允许执行的用户区代码指令是CPU支持的指令的子集。几个I / O,中断和虚拟化相关指令是禁止代码的示例。它们被称为特权指令,需要处于较低的环或管理程序模式,具体取决于CPU架构。
答案 1 :(得分:0)
你可以内联它们。您可以通过syscall(2)
直接发出系统调用,但很快就会变得混乱。请注意,系统调用开销(上下文切换来回,内核中检查......),更不用说系统调用本身所花费的时间,通过在噪声中内联消息来获得增益(如果有任何增益,更多代码意味着缓存不是那么有用,并且性能受损)。相信libc /内核人员已经研究过这个问题并在背后完成了内联(在相关的*.h
文件中),如果它真的是一个可衡量的收益。