Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 系统调用是否直接发送到内核?_C_Linux_Linux Kernel_Posix_Libc - Fatal编程技术网

C 系统调用是否直接发送到内核?

C 系统调用是否直接发送到内核?,c,linux,linux-kernel,posix,libc,C,Linux,Linux Kernel,Posix,Libc,我有几个假设,其中一些很可能是不正确的。请纠正我哪里错了 我们可以将用C编写的程序中的函数分类如下: 发送到动态加载库的函数: 这些函数被发送到库中,库将它们转换为多个标准C函数 库将它们传递到libc,在那里它们被转换为多个系统调用 Libc将它们传递到内核,在那里执行它们,并将返回发送回Libc Libc将收集returs,按c函数对它们进行分组,并使用它们为每个c函数创建一个returs。这些返回将被发送回动态加载的库 此库将收集所有返回,并使用它们创建一个返回,并发送回原始程序 在

我有几个假设,其中一些很可能是不正确的。请纠正我哪里错了

我们可以将用C编写的程序中的函数分类如下:

  • 发送到动态加载库的函数:
  • 这些函数被发送到库中,库将它们转换为多个标准C函数
  • 库将它们传递到libc,在那里它们被转换为多个系统调用
  • Libc将它们传递到内核,在那里执行它们,并将返回发送回Libc
  • Libc将收集returs,按c函数对它们进行分组,并使用它们为每个c函数创建一个returs。这些返回将被发送回动态加载的库
  • 此库将收集所有返回,并使用它们创建一个返回,并发送回原始程序
    • 在代码中定义的函数或静态编译库的一部分:所有函数都与上述类别相同,但:
  • 它们的程序已经将它们转换为已知的标准C函数,或者在另一种情况下转换为调用动态加载库的函数
  • 标准c函数被发送到libc,其他函数被发送到动态加载的库(在这里它们将按上述方式处理)
  • 程序将根据两种函数的返回创建1个最终返回
    • 作为标准C函数的函数:它们将被发送到libc,libc将以与上述相同的方式与内核通信,并向程序发送一个返回值

    • 作为系统调用的函数:它们不直接发送到内核,但必须传递到libc,尽管它不做任何额外的工作

    安全检查(权限、写入未分配的mem等)总是由内核完成,尽管上面的libc和库可能也会首先进行检查


    所有与POSIX兼容的系统都遵循这些规则

    在Linux和其他一些POSIX系统(如FreeBSD)上可能不一样

    在Linux上,定义了如何完成系统调用。了解。系统调用在中列出(但也请参见
    /usr/include/asm*/unistd.h
    ..)。也请阅读。说明了更多细节,但仅适用于32位i686

    大多数LinuxLibc都是自由软件,您可以研究它们的源代码。IMHO的源代码非常可读

    为了简化一点,大多数系统调用(例如)都是
    libc
    中的小型C函数,其中:

  • 使用
    SYSENTER
    machine指令调用内核(注意用内核约定传递系统调用号及其参数,这不是通常的C ABI)。内核认为系统调用的只是机器指令(以及与之相关的约定)

  • 通过将故障案例传递给并返回
    -1

    来处理故障案例 (IIRC,失败时,当内核从
    SYSENTER
    返回时,设置进位(或者可能是溢出)标志位;但我可能在细节上出错)

  • 通过返回结果来处理成功案例

  • 您可以使用一些汇编代码在不使用libc的情况下调用系统调用。这是不寻常的,但已完成(例如,在中或中)

    因此
    libc
    用于
    write
    的代码正在做一些微小的额外工作(传递参数、处理失败&
    errno
    和成功案例)


    一些系统调用(可能是
    getpid
    &
    clock\u gettime
    )避免了
    SYSENTER
    机器指令(以及用户模式->内核模式开关)的开销,这要归功于。

    不,您不能对这样的事情进行分类。当你用C语言编程时(但这在几乎所有其他语言中都没有区别),只有函数,不管这些函数的真实状态如何,你都可以用完全相同的方式调用它们。这由ABI(如何传递参数、获取返回值等)定义,并由编译器/链接器强制执行。当然,有些函数只是存根。例如,共享库函数的存根(加载库时可能需要存根、到实际函数的动态链接等)或系统调用(这更具技术性,并且不同内核之间有所不同)。但从程序的角度来看,一切都是一样的(这就是为什么一开始很难理解
    fread
    read
    之间的区别:你用同样的方式称呼它们,它们几乎做同样的工作,区别是什么?)


    POSIX对内核只字未提。。。它只列出了一组具有最小语义的函数的C(以前是ADA)API(加上一些命令、工具等)。这些函数的实现是完全免费的。

    有两个关键区别:(1)用户模式和内核模式之间是否存在转换(在我看来,系统调用的关键定义)和(2)被调用函数是否位于动态链接(共享)或静态链接库中。几乎所有其他的事情都是这样的。可能还有一个区别(3)被调用函数是“程序的一部分”还是“其他人的库”。也许还有一个区别(4)是否有涉及的。函数是系统调用,这在术语上是矛盾的。函数就是函数,系统调用就是系统调用。有些函数比其他函数更接近于系统调用,而且由于对
    *at()
    接口(如)的更改,它可能没有您想象的那么接近。我不知道为什么在C语言中“函数”和“系统调用”之间会有这种区别。如果你在写C,你就在使用函数。您非常需要直接汇编程序来执行实际的系统调用。这是对事物进行分类的一个很好的尝试。。。但这是一个糟糕的问题。它从“不清楚你在问什么”(ther