libc

libc 是什么意思?

在 Posix-y 系统上,程序会链接到一个名为 libc 的库(动态或静态)。此库提供了 C 标准定义的函数,以及 C 程序的运行时环境。许多系统还会在同一库中定义其他平台专用接口。其中许多接口是用户空间访问内核功能的首选方式。例如,Posix-y 系统的 libc 中有一个 open 函数,该函数会调用 open 系统调用。有时,这些标准是跨平台标准,例如 pthread。另一些则是指向特定于内核的功能的接口,如 epollkqueue。在任何情况下,该库都存在于系统本身中,并且是一个稳定的接口。相反,Windows 不会在其稳定的 win32 接口中提供系统级 libc。

在 Fuchsia 上,情况与 Posix 系统略有不同。首先,Zircon 内核(Fuchsia 的内核)不提供典型的 Posix 系统调用接口。因此,Posix 函数(如 open)无法调用 Zircon open 系统调用。其次,Fuchsia 实现了 Posix 的某些部分,但省略了 Posix 模型的大部分内容。最明显的是信号、fork 和 exec。第三,Fuchsia 不要求程序使用 libc 的 ABI。程序可以自由使用自己的 libc,也可以不使用。不过,Fucsia 确实提供了 libc.so,以便程序可以动态链接,从而与典型的 Posix 系统一样,同时提供 C 标准库和 Posix Fuchsia 支持的部分的实现。

片头

这是在 Fuchsia 的 libc 中实现(或未实现)的部分列表。

C 标准库

Fuchsia 的 libc 实现了 C11 标准。具体而言,这包括与线程相关的接口,例如线程 (thrd_t) 和互斥量 (mtx_t)。系统的这部分还会提供少量扩展,用于将 C11 结构(例如 thrd_t)桥接至底层内核结构(例如其底层的 zx_handle_t)。

波西克斯

Posix 定义了许多接口。其中包括(并非详尽无遗):文件 I/O、BSD 套接字和 pthread。

文件 I/O 和 BSD 套接字

回想一下,Zircon 是一个不负责实现文件 I/O 的内核。不过,其他 Fuchsia 用户空间服务会提供文件系统。libc 本身为 Posix 文件 I/O 函数定义了弱符号,例如 openwritefstat。但是,所有这些调用都会失败。除了 libc.so 之外,程序还可以关联 fdio.so 库。fdio 知道如何通过通道 IPC 与这些其他 Fuchsia 服务通信,并为 libc 提供一个类似于 Posix 的层。同样地,套接字通过与用户空间网络堆栈通信的 fdio 来实现。

pthread

Fuchsia 的 libc 提供了 pthread 标准的部分。尤其是 pthread_t 的核心部分(直接映射到相应的 C11 概念的部分)和同步基元(如 pthread_mutex_t)。某些详细信息(如进程共享互斥锁)未实现。所实现的子集并不全面。

信号

Fuchsia 没有 Unix 样式的信号。Zircon 无法直接实现这些线程(内核不支持导致其他线程跳出其执行上下文)。因此,Fuchsia 的 libc 不具备信号安全函数的概念,也没有在内部实现以便了解信号等机制。

因此,libc 函数不会 EINTR,并且仅适用于 Fuchsia 的代码没有必要考虑这种情况。不过,这样做完全是安全的。Fucsia 仍会定义 EINTR 常量,并且为 Posix 和 Fuchsia 编写的代码可能仍会包含 EINTR 处理循环。

fork 和 exec

Zircon 没有 fork 或 exec。相反,进程创建由 fdio 提供。虽然 Zircon 包含 Process 和 Thread 对象,但这些对象是原始的,对 ELF 一无所知。fdio_spawn 函数系列知道如何将 ELF 二进制文件和某些初始状态转换为正在运行的进程。