【问题标题】:In what library on Linux are the system calls and how is this library linked to the executable object file that contains the system calls?系统调用在 Linux 上的哪个库中,该库如何链接到包含系统调用的可执行目标文件?
【发布时间】:2017-10-09 12:36:22
【问题描述】:

我知道系统调用不在 C 标准库中。是否有系统调用所在的库(某种系统库)?

如果有这样的库,这个库是如何链接到可执行程序的?

【问题讨论】:

    标签: c linux linux-kernel shared-libraries system-calls


    【解决方案1】:

    系统调用可以以几种不同的方式工作,具体取决于目标架构,但无论如何,它不是库调用。这是运行中的用户空间程序调用内核中某些功能的一种方式。

    在非常旧的系统中,这通常意味着直接跳转到该内核函数开始的某个地址。后来,内核引入了“跳转表”,增加了一层间接性,因此内核更改时地址不必更改。这种简单的方法在很长一段时间内都不再起作用(Linux 从未使用过它),因为如今,用户空间程序以某种“受保护”模式运行,该模式限制了它们可以做什么并让它们在虚拟地址空间中运行,因此保护系统不会因为一个用户空间程序错误而崩溃。

    因此需要新的方法将 CPU 置于允许 任何 代码的模式(特权模式),并确保仅将控制权传递给内核,因此其他代码不会意外地以特权模式运行模式。在x86 上,这通常使用触发软中断的int 指令完成,内核处理该中断。在amd64 上,有一条特殊的syscall 指令用于进入内核。


    任何的情况下,C 不知道系统调用。您不能直接在 C 中发出系统调用(但您可以使用 内联汇编,如果您知道您的目标架构)。 Linux 上的 C 库包含许多函数,它们只是实际系统调用的微小包装,因此您可以直接从 C 中使用它们。


    尽管不在问题的范围内:与 Linux 不同,Windows 隐藏系统调用,以至于它们甚至没有记录在案并且随时可能更改。在 Windows 上,您应该为您的应用软件使用系统库(如 user32.dll)。

    【讨论】:

    • 也许最后一句应该是“你应该只为每个应用软件使用系统库(如 user32.dll)”。
    • 嗯,我的措辞有什么不同吗? :o
    • 我不是以英语为母语的人,第一次阅读时我的理解不同
    • @BasileStarynkevitch 我不是,现在我看到了可能的其他含义......好吧,编辑:)
    【解决方案2】:

    系统调用(在syscalls(2) 中列出)主要由 linux 内核解释。 C 库只包含与内核接口的胶水代码。从应用程序 (user-land) 的角度来看,系统调用是 atomic,并且几乎是一条 machine code 指令(SYSCALLSYSENTER on x86-64)。用于调用系统调用的ABI 不是C ABI。另见Linux Assembler HowTox86-64 ABI。使用strace(1) 了解某些命令或进程执行了哪些系统调用。

    了解operating systemssystem callslinux kernel

    SYSENTER(或SYSCALL)机器指令将CPU modeuser-mode 切换到内核模式。然后内核在特权[内核]模式下运行许多(数百万)机器指令,最后将执行SYSEXIT(或SYSRETURN)机器指令返回到用户模式。内核甚至可以安排另一个任务。所以从应用程序的角度来看,系统调用是一种基本的虚拟机指令;应用程序代码只是“看到”一个非常复杂的机器指令执行整个系统调用,而这种错觉是由内核提供的。

    另请参阅this answer 相关问题。

    (您可以通过直接在汇编程序中进行系统调用来避免使用 libc;Bones 是此类程序的一个示例;但几乎所有 Linux 上的程序都使用了一些 libc)。

    另请阅读vdso(7)ld-linux(8)elf(5)

    【讨论】:

    • 感谢您的详细回答。然而,这仍然让我感到困惑。我认为汇编代码包含直接在处理器上运行的指令,并且汇编中的命令是来自特定架构的指令集架构的指令。我现在不明白内核系统调用和汇编命令之间的联系,直到现在我认为这些命令是在处理器的 ISA 上找到的命令(ADD、LOAD 等)
    • 命令不是正确的词。这将是机器代码操作。
    • 好的,但是机器码操作是可以由CPU微码执行的操作。代码操作如何调用复杂的 Linux 内核系统调用?
    • 应用程序代码看到的东西与内核不同
    • 现在我真的很困惑。应用程序代码和内核与汇编指令由 CPU 微码执行这一事实有什么关系?
    【解决方案3】:

    该库是标准 C 库 (libc)。这通常是 glibc,但一些嵌入式 linux 将使用 musl,而 Android 使用仿生。

    Linux 作为一个平台是相当独特的,因为内核/用户界面相当稳定,因此可以使用不同的 c 库。

    libc 库将被您的工具链作为共享库自动链接,除非您告诉它不要这样做。

    【讨论】:

    • 但是glibc的目标代码怎么知道如何进行系统调用呢?如果 glibc 可以在内部进行系统调用,我的程序是否也可以直接执行此操作,而无需将标准库链接到 glibc?
    • @JenniferAnderson 对您的评论的回答是肯定的,Basile 的回答有一些链接,而我的回答试图解释一般概念。
    • @doron:这个答案是错误的,尽管它意味着正确的事情。 OP 已经声明“我知道系统调用不在 C 标准库中。”实际上,答案将是“没有这样的库”,因为系统调用不是库调用。
    猜你喜欢
    • 2012-09-14
    • 1970-01-01
    • 2015-05-27
    • 1970-01-01
    • 2021-05-25
    • 1970-01-01
    • 2011-08-20
    • 2017-12-12
    • 2013-05-31
    相关资源
    最近更新 更多