我从download.savannah.gnu.org/.../ProgrammingGroundUp-1-0-booksize.pdf学习 程序会中断内核,这就是事情的完成方式。我想知道的是你如何在C中做到这一点(如果可能的话)
答案 0 :(得分:4)
没有与平台无关的方式(显然)!在x86平台上,系统调用通常通过将系统调用代码放在eax
寄存器中,并在汇编器中触发int 80h
来实现,这会导致切换到内核模式。然后内核根据它在eax
中看到的内容执行相关代码。
答案 1 :(得分:3)
用户进程通常通过调用system call中的Standard C Library包装函数来请求内核服务。您可以使用syscall(2)
手动执行此操作。
答案 2 :(得分:1)
用户程序与内核的交互将是特定于平台的,因此它通常发生在各种库例程的幕后。因此,只需调用printf
,write
,select
或其他库例程,这些例程允许程序员编写代码而无需担心内核接口,设备驱动程序等的详细信息
它通常的工作方式是,当其中一个库例程需要内核代表它执行某些操作时,它执行一个低级系统调用,产生其对CPU的控制权内核。这是被中断的用户程序,而不是内核。
答案 3 :(得分:1)
如果您正在使用glibc(如果您使用的是gcc和linux,则可能就是这样),那么unistd.h中就有一个可以使用的系统调用函数。它针对不同的体系结构和操作系统有不同的实现,但实现是在汇编中完成的(可以是内联汇编)。 syscall
有一个手册页,所以:
man syscall
会给你一些信息。
如果你只是好奇所有这些是如何工作的那么你应该知道近年来Linux在x86上已经发生了变化。最初中断0x80被Linux用作x86上的正常系统调用入口点。这种方法运行良好,但随着处理器获得更高级的流水线操作(在先前的指令完成之前启动指令),中断速度变慢(相对于常规代码的执行速度加快,尽管一些测试表明它已经减速超过那)。这样做的原因是,即使使用int
指令触发中断,它的工作方式也与硬件触发的中断大致相同,这些中断会发生不可预测的情况,这会导致它们不能很好地处理指令的流水线操作(流水线工作)当代码路径可预测时更好。)
为了帮助这些新的x86处理器提供专门用于进行系统调用的指令,但Intel和AMD对此使用了不同的指令(分别为sysenter
和syscall
)。此外,英特尔systenter
指令破坏了Linux在x86_32上用于将参数传递给内核的通用寄存器。这意味着程序必须知道要使用的3种可能的系统调用机制中的哪种,以及可能将参数传递给内核的不同方式。为了解决所有这些较新的内核,将一个特殊的内存页面映射到程序中(这个页面称为vsyscall,如果你cat /proc/self/maps
,你会看到它的一个条目),它包含内核所具有的系统调用机制的代码。确定应该在系统上使用,并且较新版本的glib可以使用此页面中的代码实现其系统调用条目。
所有这一切的要点是,这并不像以前那么简单,但如果你只是在x86_32上玩,那么你应该能够使用int 80h
指令,因为那样做在可以使用其他机制之一进行向后兼容的系统上受支持。
答案 4 :(得分:0)
在C中,你并不直接这样做,但是当你使用最终调用系统调用的库函数时,你最终会间接地这样做。文件访问,网络访问等是典型的例子。
这些函数将最终“捕获”到内核,后者将处理请求。