“C 系统调用”和“C 库例程”有什么区别?

问题描述 投票:0回答:5

手册页中有多个部分。其中两个是:

2 Unix 和 C 系统调用
3 C 程序的 C 库例程

例如有

getmntinfo(3)
getfsstat(2)
,两者看起来都做同样的事情。什么时候应该使用哪个以及有什么区别?

c unix system manpage
5个回答
30
投票

系统调用是操作系统函数,就像在 UNIX 上一样,

malloc()
函数构建在
sbrk()
系统调用之上(用于调整进程内存空间大小)。

库只是应用程序代码,不属于操作系统的一部分,并且通常可在多个操作系统上使用。 它们与您自己的程序中的函数调用基本相同。

这条线可能有点模糊,但只是将系统调用视为内核级功能。


15
投票

常用函数库构建在系统调用接口之上,但应用程序可以自由使用两者。

系统调用就像有权使用内核资源的身份验证密钥。

enter image description here

上图来自高级 Linux 编程,有助于理解用户应用程序如何与内核交互。


12
投票

系统调用是用户级代码和内核之间的接口。 C 库例程是像任何其他库调用一样的库调用,它们只是碰巧被普遍提供(几乎普遍存在)。 许多标准库例程都是系统调用的包装器(瘦的或其他的),这确实会使界限有点模糊。

至于使用哪一种,一般来说,使用最适合您需求的一种。


6
投票

手册第 2 节中描述的调用都是对捕获内核的系统服务的实际调用的相对较薄的包装。 本手册第 3 节中描述的 C 标准库例程是客户端库函数,它们实际上可能会也可能不会使用系统调用。

这篇文章描述了系统调用和捕获内核(在稍微不同的上下文中),并通过一些参考解释了系统调用背后的底层机制。


4
投票

作为一般规则,您应该始终使用 C 库版本。 他们通常有包装器来处理深奥的事情,例如根据信号重新启动(如果您有要求)。 如果您已经与该库链接,则尤其如此。 所有规则都有被打破的理由。使用直接通话的原因,

  1. 你想成为
    libc
    不可知论者;也许有安装程序。 此类代码可以在 Android (bionic)、uClibc 和更传统的 glibc/eglibc 系统上运行,无论使用什么库。 此外,使用包装器动态加载以创建运行时 glibc/bionic 层,允许双 Android/Linux 二进制文件。
  2. 您需要极致的性能。尽管这种情况可能很少见,而且很可能被误导。 重新思考问题可能会带来更好的性能优势,并且调用系统通常会带来性能优势,
    libc
    偶尔可以做到这一点。
  3. 您正在编写一些没有库的
    initramfs
    init
    代码;创建更小的映像或更快地启动。
  4. 您正在测试新的内核/平台,并且不想让成熟的文件系统使生活变得复杂;与
    initramfs
    非常相似。
  5. 您希望在程序启动时非常快速地执行某些操作,但最终想要使用
    libc
    例程。
  6. 为了避免
    libc
    中的已知错误。
  7. 无法通过
    libc
    使用该功能。

抱歉,大多数示例都是 Linux 特定的,但其原理应该适用于其他 Unix 变体。 当新功能引入内核时,最后一项非常常见。 例如,当

kqueue
epoll
首次引入时,没有
libc
支持它们。 如果系统有较旧的库,但有较新的内核并且您希望使用此功能,也可能会发生这种情况。

如果您的进程尚未使用

libc
,那么系统中很可能会有某些东西。 通过编写自己的变体,您可以通过提供通往同一最终目标的两条路径来取消缓存。 另外,Unix 将在进程之间共享代码页。 一般来说没有理由不使用
libc
版本。

其他答案已经在

libc
和系统调用之间的差异方面做出了出色的工作。

© www.soinside.com 2019 - 2024. All rights reserved.