24

联机帮助页中有多个部分。其中两个是:

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

例如,有getmntinfo(3)and getfsstat(2),两者看起来都在做同样的事情。什么时候应该使用 which 和有什么区别?

4

5 回答 5

30

系统调用是操作系统函数,就像在 UNIX 上一样,该malloc()函数建立在系统调用之上sbrk()(用于调整进程内存空间的大小)。

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

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

于 2009-02-21T13:08:07.517 回答
13

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

系统调用就像可以访问使用内核资源的身份验证密钥。

在此处输入图像描述

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

于 2012-11-01T05:43:11.893 回答
12

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

至于使用哪一种,作为一般规则,使用最适合您需要的一种。

于 2009-02-21T13:09:09.433 回答
6

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

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

于 2009-02-21T14:00:25.287 回答
4

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

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

抱歉,大多数示例都是特定于 Linux 的,但原理应该适用于其他 Unix 变体。当新特性被引入内核时,最后一项是很常见的。例如,何时kqueue何地epoll首次引入,没有libc人支持它们。如果系统具有较旧的库但较新的内核并且您希望使用此功能,也可能会发生这种情况。

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

其他答案已经在libc系统调用和系统调用之间的区别上做了出色的工作。

于 2013-03-24T04:45:43.310 回答