glibc 知:手册01:介绍

1. 前言

The GNU C Library Reference Manual for version 2.35

2. 介绍

Introduction

C 语言没有提供用于执行诸如输入/输出、内存管理、字符串操作等常见操作的内置工具。相反,这些设施是在标准库中定义的,您可以编译并链接到您的程序。

本文档中描述的 GNU C 库定义了 ISO C 标准指定的所有库函数,以及特定于 POSIX 和其它 Unix 操作系统衍生产品的附加功能,以及特定于 GNU 系统的扩展。

本手册的目的是告诉您如何使用 GNU C 库的工具。我们已经提到了哪些功能属于哪些标准,以帮助您识别可能无法移植到其它系统的事物。但本手册的重点并不是严格的可移植性。

2.1. 入门

Getting Started

编写本手册的前提是您至少对 C 编程语言和基本编程概念有所熟悉。具体来说,假定熟悉 ISO 标准 C(参见ISO C),而不是“传统的” pre-ISO C 方言。

GNU C 库包括几个头文件,每个头文件都为一组相关工具提供定义和声明;C 编译器在处理您的程序时会使用此信息。比如头文件 stdio.h 声明执行输入和输出的设施,以及头文件 string.h 声明字符串处理实用程序。本手册的组织结构一般与头文件相同。

如果您是第一次阅读本手册,您应该阅读所有介绍材料并略读其余章节。GNU C 库中有很多函数,期望您能够准确记住如何使用每一个函数是不现实的。熟悉库提供的各种设施更为重要,这样当您编写程序时,您可以识别何时使用库函数,以及在本手册中的何处可以找到有关它们的更具体信息。

2.2. 标准和可移植性

Standards and Portability

本节讨论 GNU C 库所基于的各种标准和其它来源。这些来源包括 ISO C 和 POSIX 标准,以及 System V 和 Berkeley Unix 实现。

本手册的主要重点是告诉您如何有效地使用 GNU C 库工具。但是,如果您担心使您的程序与这些标准兼容,或者可移植到 GNU 以外的操作系统,这可能会影响您使用该库的方式。本节概述了这些标准,以便在手册的其它部分提到它们时了解它们是什么。

请参阅库设施摘要,以获取库提供的功能和其它符号的字母列表。该列表还说明了每个功能或符号来自哪些标准。

2.2.1. ISO C

GNU C 库与美国国家标准协会 (ANSI) 采用的 C 标准兼容:美国国家标准 X3.159-1989 —“ANSI C” 以及后来的国际标准化组织 (ISO):ISO/IEC 9899:1990,“编程语言——C”。我们在这里将标准称为 ISO C ,因为这是关于批准的更通用的标准。构成 GNU C 库的头文件和库工具是 ISO C标准 指定的那些的超集。

如果您担心严格遵守 ISO C标准,当您用 GNU C 编译器编译您的程序时,使用 ‘-ansi’ 选项。这告诉编译器只定义库头文件中的 ISO 标准功能,除非您明确要求附加功能。有关如何执行此操作的信息,请参阅功能测试宏

能够将库限制为仅包含 ISO C 功能很重要,因为 ISO C 限制了库实现可以定义的名称,而 GNU 扩展不符合这些限制。有关这些限制的更多信息,请参阅保留名称

本手册并未尝试为您提供有关 ISO C 和旧方言(older dialects)之间差异的完整详细信息。它提供了有关如何编写程序以在多种 C 方言下可移植性工作的建议,但并不旨在完整性。

2.2.2. POSIX(可移植操作系统接口)

POSIX (The Portable Operating System Interfac)

GNU C 库还与 ISO POSIX系列标准兼容,更正式地称为计算机环境的可移植操作系统接口(ISO/IEC 9945)。它们还以 ANSI/IEEE Std 1003 的形式发布。POSIX 主要来源于各种版本的 Unix 操作系统。

POSIX 标准规定的库设施是 ISO C 要求的库设施的超集;POSIX 为 ISO C函数指定了附加特性,并指定了新的附加函数。一般来说,POSIX 标准定义的附加要求和功能旨在为特定类型的操作系统环境提供较低级别的支持,而不是可以在许多不同操作系统环境中运行的通用编程语言支持。

GNU C 库实现了 ISO/IEC 9945-1:1996 中指定的所有功能,即 POSIX 系统应用程序接口,通常称为 POSIX.1。本标准规定的 ISO C 工具的主要扩展包括文件系统接口原语(参见文件系统接口)、特定于设备的终端控制功能(参见底层终端接口)和进程控制功能(参见进程)。

一些来自 ISO/IEC 9945-2:1993 的工具,POSIX Shell and Utilities 标准(POSIX.2) 也在 GNU C 库中实现。其中包括处理正则表达式的实用程序和其它模式匹配工具(请参阅模式匹配)。

2.2.2.1. POSIX 安全概念

POSIX Safety Concepts

本手册记录了 GNU C 库函数的各种安全属性,它们遵循它们的原型,如下所示:

Preliminary: | MT-Safe | AS-Safe | AC-Safe |

这些属性是根据 POSIX 标准中针对线程安全、异步信号安全和异步取消安全等安全上下文中规定的标准进行评估的。这些属性的直观定义,试图捕捉标准定义的含义,如下。

  • MT-Safe 或 Thread-Safe 函数在存在其它线程的情况下可以安全调用。MT-Safe 中的 MT 代表多线程。

    MT-Safe 并不意味着函数是原子的,也不意味着它使用 POSIX 向用户公开的任何内存同步机制。甚至有可能按顺序调用 MT-Safe 函数不会产生 MT-Safe 组合。例如,让一个线程一个接一个地调用两个 MT-Safe 函数并不能保证等同于原子执行这两个函数的组合的行为,因为其它线程中的并发调用可能会以破坏性方式干扰。

    可以跨库接口内联函数的整个程序优化可能会暴露不安全的重新排序,因此不建议跨 GNU C 库接口执行内联。在整个程序优化下,不保证记录的 MT-Safety 状态。但是,在用户可见的头文件中定义的函数被设计为内联安全。

  • AS-Safe 或 Async-Signal-Safe 函数可以安全地从异步信号处理程序中调用。AS-Safe 中的 AS 代表异步信号。

    许多 AS 安全的函数可以设置errno或修改浮点环境,因为这样做不会使它们不适合在信号处理程序中使用。但是,如果异步信号处理程序修改此线程本地状态,程序可能会出现异常行为,并且不能指望信号处理机制来保留它。因此,调用可能设置errno或修改浮点环境的函数的信号处理程序必须保存它们的原始值,并在返回之前恢复它们。

  • AC-Safe 或 Async-Cancel-Safe 函数在启用异步取消时可以安全调用。AC-Safe 中的 AC 代表异步取消。

    POSIX 标准仅定义了三个 AC 安全功能,即 pthread_cancel、pthread_setcancelstate 和 pthread_setcanceltype。目前,GNU C 库不提供这三个函数之外的保证,但会记录哪些函数目前是 AC 安全的。本文档供 GNU C 库开发人员使用。

    就像信号处理程序一样,取消清除例程必须配置它们所需的浮点环境。例程不能假设浮点环境,尤其是在启用异步取消时。如果浮点环境的配置不能原子执行,那么也有可能遇到的环境内部不一致。

  • MT-Unsafe, AS-Unsafe, AC-Unsafe 函数在上述安全上下文中调用是不安全的。在这样的上下文中调用它们会调用未定义的行为。

    在安全上下文中未明确记录为安全的功能应被视为不安全的。

  • Preliminary 安全属性,表明在 GNU C 库的未来版本中可能不会依赖这些属性。

    这些初步(Preliminary)属性是对我们当前实施的属性进行评估的结果,而不是当前和未来标准强制和允许的结果。

    尽管我们努力遵守标准,但在某些情况下,即使标准不要求安全,我们的实施也是安全的,而在其他情况下,我们的实施不符合标准的安全要求。后者最有可能是缺陷;前者,当标记为 Preliminary 时,不应指望:未来的标准可能需要与当前实施提供的额外安全特性不兼容的更改。

    此外,POSIX 标准没有提供安全的详细定义。我们假设,通过“调用安全”,POSIX 意味着,只要程序不调用未定义的行为,“调用安全”函数的行为就如指定的那样,并且不会导致其它函数偏离它们指定的行为。我们选择使用其松散的安全定义,不是因为它们是最好的定义,而是因为选择它们可以使本手册与 POSIX 保持一致。

    请记住,这些是初步定义和注释,定义的某些方面仍在讨论中,可能需要澄清或更改。

    随着时间的推移,我们设想将初步的安全说明演变成稳定的承诺,就像我们的接口一样稳定。正如我们所做的那样,我们将从安全说明中删除 Preliminary 关键字。然而,只要关键字仍然存在,它们就不能被视为对未来行为的承诺。

出现在安全说明中的其它关键字在后续部分中定义。

2.2.2.2. 不安全特性

Unsafe Features

在某些上下文中调用不安全的函数使用关键字进行注释,这些关键字记录了它们使调用不安全的特性。本节中的 AS-Unsafe 特性表明,当启用异步信号时,函数永远不会安全调用。AC-Unsafe 特性表明在启用异步取消时调用它们永远不会安全。本节中没有 MT-Unsafe 标记。

  • lock

    标记 lock 作为 AS-Unsafe 特性的函数可能会在持有非递归锁时被信号中断。如果信号处理程序调用另一个采用相同锁的此类函数,则结果是死锁。

    注释 lock 作为 AC-Unsafe 特性的函数如果被异步取消,则可能无法释放锁(如果它们的执行没有被异步线程取消中断时,本应被释放的锁)。一旦一个锁被占用,尝试占用该锁将无限期地阻塞。

  • corrupt

    标记 corrupt 作为 AS-Unsafe 特性的函数可能会损坏数据结构并在它们中断或被另一个此类函数中断时出现异常行为。与标记为 lock 的函数不同,这些函数采用递归锁来避免 MT-Safety 问题,但这不足以阻止信号处理程序观察部分更新的数据结构。被中断的函数未能注意到信号处理程序所做的更新可能会导致进一步的损坏。

    标记 corrupt 作为 AC-Unsafe 特性的函数可能会使数据结构处于损坏的、部分更新的状态。数据结构的后续使用可能行为不端。

  • heap

    标有 heap 的函数可以调用 malloc/free 系列函数中的堆内存管理函数,并且仅与这些函数一样安全。因此,此注释等效于:

    | AS-Unsafe lock | AC-Unsafe lock fd mem |

  • dlopen

    标有 dlopen 的函数使用动态加载器将共享库加载到当前执行映像中。这包括打开文件、将它们映射到内存、分配额外的内存、解析符号、应用重定位等等,所有这些都同时持有内部动态加载器锁。

    这些锁足以使这些功能成为 AS- 和 AC-Unsafe,但可能会出现其他问题。目前这是 dlopen 提出的所有潜在安全问题的占位符。

  • plugin

    使用 plugin 注解的函数可以运行来自可能在 GNU C 库外部的插件的代码。此类插件功能被假定为 MT-Safe、AS-Unsafe 和 AC-Unsafe。此类插件的示例是堆栈展开库、名称服务开关 (NSS) 和字符集转换 (iconv) 后端。

    尽管作为示例提到的插件都是通过 dlopen 引入的,但 plugin 关键字并不意味着动态加载器或 libdl 接口的任何直接参与,这些都包含在 dlopen 中。例如,如果一个函数加载一个模块并找到它的某些函数的地址,而另一个函数只是调用那些已经解析的函数,则前者将被标记为 dlopen,而后者将获得插件。当单个函数执行所有这些操作时,它会同时获得两个标记。

  • i18n

    标有 i18n 的函数可以调用 gettext 系列的国际化函数,并且仅与这些函数一样安全。因此,此注释等效于:

    | MT-Safe env | AS-Unsafe corrupt heap dlopen | AC-Unsafe corrupt |

  • timer

    标有 timer 的函数使用 alarm 函数或类似函数为系统调用或长时间运行的操作设置超时。在多线程程序中,存在超时信号将被传递到不同线程的风险,因此无法中断预期的线程。除了 MT-Unsafe 之外,这些函数始终是 AS-Unsafe,因为在信号处理程序中调用它们可能会干扰在中断代码中设置的计时器,和 AC-Unsafe,因为没有安全的方法来保证在异步取消的情况下会重置较早的计时器。

2.2.2.3. 条件安全特征

Conditionally Safe Features

对于某些使函数在某些上下文中调用不安全的特性,除了完全避免调用函数之外,还有一些已知的方法可以避免安全问题。后面的关键字指的是这些特性,它们的每一个定义都表明需要如何约束整个程序,以消除关键字所指示的安全问题。只有当所有使函数不安全的原因都被观察和解决时,通过应用记录的约束,函数才能在上下文中安全调用。

  • init

    标记 init 作为 MT-Unsafe 特性的函数在首次调用时会执行 MT-Unsafe 初始化。

    在单线程模式下至少调用一次这样的函数可以消除该函数被视为 MT-Unsafe 的特定原因。如果没有其它原因,则可以在启动其它线程后安全地调用该函数。

    标记 init 作为 AS- 或 AC-Unsafe 特性的函数使用内部 libc_once 机制或类似机制来初始化内部数据结构。

    如果信号处理程序中断这样的初始化程序,并调用任何也执行 libc_once 初始化的函数,如果线程库已加载,它将死锁。

    此外,如果初始化程序在被其处理程序需要相同初始化的信号取消或中断之前部分完成,则可能会多次执行部分或全部初始化,从而导致资源泄漏甚至导致内部数据损坏。

    需要调用标记 init 作为 AS- 或 AC-Unsafe 特性的应用程序应确保在配置信号处理程序或启用取消之前执行初始化,以便不会出现与 libc_once 相关的 AS- 和 AC-Safety 问题。

  • race

    注释 race 作为 MT-Safety 问题的函数以可能导致数据竞争或类似形式的破坏性干扰脱离并发执行的方式对对象进行操作。在某些情况下,对象由用户传递给函数;在其他情况下,它们被函数用来向用户返回值;在其他情况下,它们甚至不会暴露给用户。

    我们认为对作为(间接)参数传递给函数的对象的访问是无数据竞争的。数据竞争对象的保证是调用者的责任。如果用户在处理此类对象时未能采取 POSIX 要求的措施来避免数据竞争而出现异常行为,我们不会将其标记为 MT-Unsafe 或 AS-Unsafe。作为一般规则,如果一个函数被记录为读取(通过引用)传递给它的对象,或者修改它,用户应该使用内存同步原语来避免数据竞争,就像他们应该自己执行访问而不是通过调用库函数一样。FILE 流是一般规则的例外,因为 POSIX 要求库在许多操作这种特定不透明类型的对象的函数中防止数据竞争。我们认为这是为用户提供的一种便利,而不是一种普遍要求,其期望应该扩展到其他类型。

    为了提醒用户保护某些参数是他们的责任,我们将对将某些类型的对象作为参数的函数进行注释。我们为用户传递的对象画了一条线,如下所示:类型向用户公开的对象,并且期望用户直接访问的对象,例如内存缓冲区,字符串和各种用户可见的结构类型,不要为用 race 注释的函数提供理由。对于一般要求,这将是嘈杂和多余的,当访问用户可以直接访问的对象时,没有多少人会对库缺乏内部保护感到惊讶。

    至于不透明或类似不透明的对象,因为它们只能通过将它们传递给库函数(例如,FILE、DIR、obstack、iconv_t)来进行操作,对库访问的内部协调可能会有额外的期望。我们将使用 race 后跟冒号和参数名称来注释接受此类对象,但默认情况下不负责同步访问它们的函数。例如,FILE 流未锁定函数将被注释,但默认情况下对 FILE 流执行隐式锁定的函数不会被注释,即使隐式锁定可能在每个流的基础上被禁用。

    在任何一种情况下,如果用户未能确保访问被明确定义,我们不会认为可能以不安全的方式访问用户提供的对象的 MT-Unsafe 函数。人们普遍认为,用户应该保护库代表他们访问的任何用户提供的对象免受数据竞争。

    但是,此用户责任不适用于由库本身控制的对象,例如用于从某些调用返回值的内部对象和静态缓冲区。当库不保护它们防止并发使用时,这些情况被视为 MT-Unsafe 和 AS-Unsafe(尽管 AS-Unsafe 下的 race 标记将被省略,因为与 MT-Unsafe 下的 race 标记一样是多余的)。与用户公开对象的情况一样,标记后面可以跟一个冒号和一个标识符。标识符将所有对某个未保护对象进行操作的函数分组;用户可以通过创建与标识符相关的非递归互斥锁来避免与对此类内部对象的无保护并发访问相关的 MT-Safety 问题,并在调用该标识符上标记为 racy 的任何函数时始终持有互斥锁,因为他们必须标识符是否应该是受用户控制的对象。非递归互斥锁避免了 MT-Safety 问题,但它用一个 AS-Safety 问题换了另一个问题,因此在异步信号中的使用仍未定义。

    当标识符与用于保存返回值的静态缓冲区相关时,只要调用者仍在使用该缓冲区,就必须保留互斥锁。许多返回指向静态缓冲区的指针的函数提供了可重入变体,这些变体将返回值存储在调用者提供的缓冲区中。在某些情况下,例如 tmpname,不是通过调用备用入口点来选择变体,而是通过将非 NULL 指针传递给要存储返回值的缓冲区。这些变体通常在多线程程序中更可取,尽管其中一些由于其他内部缓冲区而不是 MT-Safe,也记录在 race 说明中。

  • const

    标记 const 作为 MT-Safety 问题的函数以非原子方式修改被更好地视为常量的内部对象,因为 GNU C 库的很大一部分在没有同步的情况下访问它们。与 race 不同,这会导致内部对象的读取者和写入者都被视为 MT-Unsafe 和 AS-Unsafe,此标记仅适用于写入者。写入者仍然保持同样的 MT- 和 AS-Unsafe 调用,但是他们修改的对象的强制常量使读取者被视为 MT-Safe 和 AS-Safe(只要没有其他原因导致它们不安全),因为当对象实际上是恒定的时,缺乏同步不是问题。

    const 标记后面的标识符将作为安全说明单独出现在读取者中。希望解决此安全问题以便调用写入者的程序可以使用与标识符关联的非递归 rwlock,并保护对标有 const 的函数的所有调用,然后是带有写锁的标识符,以及对所有调用用标识符标记的函数本身带有读锁。非递归锁定消除了 MT-Safety 问题,但是它将一个 AS-Safety 问题换成了另一个,因此在异步信号中的使用仍未定义。

  • sig

    标记 sig 作为 MT-Safety 问题的功能(这意味着相同的 AS-Safety 问题,为简洁起见省略)可能会临时安装信号处理程序用于内部目的,这可能会干扰信号的其它用途,在冒号后标识。

    这个安全问题可以通过确保在通话期间不会发生信号的其它用途来解决。在调用使用相同临时信号的所有函数时持有非递归互斥锁;建议在调用之前阻止该信号并在之后重置其处理程序。

    没有安全的方法来保证在异步取消的情况下恢复原始信号处理程序,因此标记的函数也是 AC-Unsafe。

    除了建议解决 MT- 和 AS-Safety 问题的措施外,为了避免取消问题,建议禁用异步取消并安装清理处理程序以将信号恢复到所需状态并释放互斥锁。

  • term

    标记 term 作为 MT-Safety 问题的函数可能会以推荐的方式更改终端设置,即:调用 tcgetattr,修改一些标志,然后调用 tcsetattr;这会创建一个窗口,在该窗口中其他线程所做的更改会丢失。因此,标有 term 的函数是 MT-Unsafe。相同的窗口会使异步信号所做的更改丢失。这些功能也是 AS-Unsafe 的,但相应的标记被省略为多余的。

    因此,建议使用终端的应用程序避免与终端的并发和可重入交互,不要在信号处理程序中使用它或阻塞可能使用它的信号,并在调用这些函数并与终端交互时保持锁定。这个锁也应该用于与带有 race:tcattr(fd) 标记的函数的互斥,其中 fd 是控制终端的文件描述符。为简单起见,调用者可以使用单个互斥锁,或者每个终端使用一个互斥锁,即使被不同的文件描述符引用。

    标记 term 作为 AC-Safety 问题的函数应该在临时更改终端设置后将其恢复到原始状态,但如果取消,它们可能无法恢复。

    除了建议解决 MT- 和 AS-Safety 问题的措施外,为了避免取消问题,建议禁用异步取消并安装清理处理程序以将终端设置恢复到原始状态并释放互斥锁。

2.2.2.4. 其它安全备注

Other Safety Remarks

附加的关键字可以附加到函数上,表示不会使函数调用不安全的特性,但在某些类的程序中可能需要考虑:

  • locale

    注释 locale 作为 MT-Safety 问题的函数从区域设置对象中读取,无需任何形式的同步。带有 locale 注释的函数与语言环境更改并发调用的方式可能与执行期间的任何活动语言环境不对应,而是其不可预知的混合。

    但是,我们不会将这些函数标记为 MT- 或 AS-Unsafe,因为修改语言环境对象的函数被标记为 const:locale 并被视为不安全。由于不安全,后者在多个线程正在运行或启用异步信号时不会被调用,因此在这些上下文中可以认为语言环境有效地保持不变,这使得前者是安全的。

  • env

    标记 env 作为 MT-Safety 问题的函数使用 getenv 或类似的方法访问环境,没有任何保护措施来确保存在并发修改时的安全性。

    但是,我们不会将这些函数标记为 MT- 或 AS-Unsafe,因为修改环境的函数都标有 const:env 并被视为不安全。由于不安全,后者在多个线程正在运行或启用异步信号时不会被调用,因此在这些上下文中可以认为环境实际上是恒定的,这使得前者是安全的。

  • hostid

    标记 hostid 作为 MT-Safety 问题的函数从保存机器“主机 ID”的系统范围数据结构中读取。这些数据结构通常不能原子地修改。由于预计“主机ID”不会正常变化,因此读取它的函数(gethostid)被认为是安全的,而修改它的函数(sethostid)标有const:hostid,表示它可能需要特殊关心它是否被调用。在这种特定情况下,特殊照顾相当于系统范围内(不仅仅是进程内)的协调。

  • sigintr

    标记 sigintr 作为 MT-Safety 问题的函数在没有任何保护的情况下访问 _sigintr 内部数据结构,以确保存在并发修改时的安全性。

    但是,我们不会将这些函数标记为 MT- 或 AS-Unsafe,因为修改此数据结构的函数都标有 const:sigintr 并被视为不安全。由于不安全,后者在多个线程运行或启用异步信号时不会被调用,因此在这些上下文中可以认为数据结构有效地保持不变,这使得前者是安全的。

  • fd

    如果异步线程取消中断了函数的执行,则注释 fd 作为 AC-Safety 问题的函数可能会泄漏文件描述符。

    分配或取消分配文件描述符的函数通常会这样标记。即使他们试图通过清理区域来保护文件描述符的分配和释放,分配一个新的描述符并将其编号存储在清理区域可以释放的位置,也不能作为单个原子操作执行。同样,释放描述符并将其从通常负责释放它的数据结构中取出也不能原子地执行。总会有一个窗口无法释放描述符,因为它还没有存储在清理处理程序参数中,或者它在释放之前已经被取出。释放后不能取出:打开的描述符可能意味着描述符仍然必须关闭,或者它已经关闭但描述符被另一个线程或信号处理程序重新分配。

    通过暂时禁用异步线程取消,可以在内部避免此类泄漏,但会带来一些性能损失。但是,由于分配或释放函数的调用者必须自己执行此操作,以避免在他们自己的层中发生相同类型的泄漏,对于库来说,假设他们正在处理它比施加性能损失更有意义,当问题在上层解决时是多余的,而在没有解决时则不足。

    此注释本身不会导致函数被视为 AC-Unsafe。但是,此类泄漏的累积影响可能会给某些程序带来问题。如果是这种情况,建议在调用此类函数期间暂停异步取消。

  • mem

    如果异步线程取消中断了函数的执行,则注释 mem 作为 AC-Safety 问题的函数可能会泄漏内存。

    这个问题类似于文件描述符的问题:没有原子接口来分配内存并将其地址存储在清理处理程序的参数中,或者释放它并从该参数中删除其地址,至少暂时禁用异步取消,这些功能不做。

    这句话本身并不会导致函数被视为一般 AC-Unsafe。但是,对于某些程序来说,这种泄漏的累积影响可能已经足够严重,可能需要在调用这些函数的持续时间内禁用异步取消。

  • cwd

    标记 cwd 作为 MT-Safety 问题的函数可能会在执行期间临时更改当前工作目录,这可能会导致在其他线程或异步信号或取消处理程序中以意想不到的方式解析相对路径名。

    这还不足以将标记的函数标记为 MT- 或 AS-Unsafe,但是当此行为是可选的(例如,带有 FTW_CHDIR 的 nftw)时,避免该选项可能是使用完整路径名或文件描述符的一个很好的替代方案 - 相对(例如 openat)系统调用。

  • !posix

    注释此标记作为 MT-、AS- 或 AC-Safety 的函数,表示已知函数的安全状态与 POSIX 标准中的指定状态不同。例如,POSIX 不要求函数是安全的,但我们的实现是,反之亦然。

    目前,没有此注释并不意味着我们记录的安全属性与 POSIX 为相应功能规定的安全属性相同。

  • :identifier

    注解有时可能跟在标识符后面,旨在将几个函数分组,例如以不安全的方式访问数据结构,例如在 race 和 const 中,或者提供更具体的信息,例如在标有 sig 的函数中命名信号。可以预见,它将来也可能应用于 lock 和 corrupt。

    在大多数情况下,标识符将命名一组函数,但它可以命名全局对象或函数参数,或与它们关联的可识别属性或逻辑组件,使用诸如 :buf(arg) 表示与参数 arg 关联的缓冲区,或 :tcattr(fd) 表示文件描述符 fd 的终端属性。

    标识符最常见的用途是提供需要由相同同步原语保护的函数和参数的逻辑组,以确保在给定上下文中的安全操作。

  • /condition

    一些安全注释可能是有条件的,因为它们仅适用于涉及参数、全局变量甚至底层内核的布尔表达式评估为真时。/hurd 或 /!linux!bsd 等条件表示前面的标记仅适用于底层内核是 HURD,或者它既不是 Linux 也不是 BSD 内核时。/!ps 和 /one_per_line 表示前面的标记仅在参数 ps 为 NULL 或全局变量 one_per_line 非零时适用。

    当所有使函数不安全的标记都带有这样的条件时,并且没有一个命名条件成立,那么该函数可以被认为是安全的。

2.2.3. 伯克利 Unix

Berkeley Unix

GNU C 库定义了一些未正式标准化的 Unix 版本的工具,特别是 4.2 BSD、4.3 BSD 和 4.4 BSD Unix 系统(也称为 Berkeley Unix)和 SunOS(流行的 4.2 BSD 衍生产品,包括一些 Unix System V 功能)。这些系统支持大多数 ISO C 和 POSIX 工具,而 4.4 BSD 和更新的 SunOS 版本实际上都支持它们。

BSD 工具包括符号链接(参见符号链接)、 select函数(参见等待输入或输出)、BSD 信号函数(参见BSD 信号处理)和套接字(参见套接字)。

2.2.4. SVID(System V接口描述)

SVID (The System V Interface Description)

System V Interface Description (SVID) 是描述 AT&T Unix System V 操作系统的文档。它在某种程度上是 POSIX 标准的超集(参见POSIX(可移植操作系统接口))。

GNU C 库定义了 SVID 所需的大部分设施,而 ISO C 或 POSIX 标准也不需要这些设施,以与 System V Unix 和包含这些设施的其他 Unix 系统(如 SunOS)兼容。但是,SVID 所需的许多更晦涩和不太常用的设施并未包括在内。(事实上,Unix System V 本身并没有提供所有这些。)

System V 支持的工具包括进程间通信和共享内存的方法、hsearch 和 drand48 系列函数、fmtmsg 和一些数学函数。

2.2.5. XPG(X/Open 可移植性指南)

XPG (The X/Open Portability Guide)

X/Open Company, Ltd. 发布的 X/Open Portability Guide 是比 POSIX 更通用的标准。X/Open 拥有 Unix 版权,XPG 规定了旨在成为 Unix 系统的系统的要求。

GNU C 库符合 X/Open 可移植性指南,第 4.2 版,具有 XSI(X/Open 系统接口)兼容系统通用的所有扩展以及所有 X/Open UNIX 扩展。

POSIX 之上的添加主要来自 System V 和 BSD 系统中可用的功能。不过,System V 系统中的一些非常严重的错误已得到纠正。由于使用 Unix 扩展实现 XPG 标准是获得 Unix 品牌的先决条件,因此该功能在商业系统上可用的机会很大。

2.3. 使用库

Using the Library

本节描述了使用 GNU C 库所涉及的一些实际问题。

2.3.1. 头文件

Header Files

C 程序使用的库实际上由两部分组成:定义类型和宏以及声明变量和函数的头文件;以及包含变量和函数定义的实际库或存档(静态库)。

(回想一下,在 C 语言中,声明仅提供函数或变量存在的信息并给出其类型。对于函数声明,也可能提供有关其参数类型的信息。声明的目的是允许编译器正确处理对已声明变量和函数的引用。另一方面,定义实际上为变量分配存储空间或说明函数的作用。)

为了使用 GNU C 库中的工具,您应该确保您的程序源文件包含适当的头文件。这样编译器就可以使用这些工具的声明,并且可以正确处理对它们的引用。编译程序后,链接器会将这些引用解析为存档文件中提供的实际定义。

头文件通过 ‘#inlcude’ 预处理指令包含在程序源文件中。C 语言支持该指令的两种形式;首先,

#include "header"

通常用于包含您自己编写的头文件 header;这将包含描述特定应用程序不同部分之间接口的定义和声明。相比之下,

#include <file.h>

通常用于包含头文件 file.h 包含标准库的定义和声明。此文件通常由系统管理员安装在标准位置。您应该对 C 库头文件使用第二种形式。

通常,“#include”指令放置在 C 源文件的顶部,在任何其他代码之前。如果您在源文件开始时有一些注释来解释文件中的代码的作用(一个好主意),请紧接着在功能测试宏定义之后放置“#include”指令(请参阅功能测试宏)。

有关使用头文件和’#include’指令的更多信息,请参阅GNU C 预处理器手册中的头文件

GNU C 库提供了几个头文件,每个头文件都包含一组相关工具的类型和宏定义以及变量和函数声明。这意味着您的程序可能需要包含几个头文件,具体取决于您使用的工具。

一些库头文件会自动包含其它库头文件。但是,就编程风格而言,您不应该依赖于此;最好明确包含您正在使用的库设施所需的所有头文件。GNU C 库头文件的编写方式使得头文件被意外包含多次并不重要;第二次包含头文件无效。同样,如果您的程序需要包含多个头文件,则包含它们的顺序无关紧要。

兼容性说明:在任何 ISO C 实现中以任意顺序和任意次数包含标准头文件都有效。然而,在许多较旧的 C 实现中,传统上并非如此。

严格来说,你不必包含头文件来使用它声明的函数;您可以根据本手册中的规范自行明确声明该函数。但通常最好包含头文件,因为它可以定义其它方式不可用的类型和宏,并且因为它可以为某些函数定义更有效的宏替换。这也是获得正确声明的可靠方法。

2.3.2. 函数宏定义

Macro Definitions of Functions

如果我们在本手册中将某些东西描述为函数,那么它也可能有一个宏定义。这通常对程序的运行方式没有影响 —— 宏定义与函数的作用相同。特别是,库函数的宏等效项只计算一次参数,就像函数调用一样。这些宏定义的主要原因是有时它们可​​以产生比实际函数调用快得多的内联扩展。

即使它也被定义为宏,获取库函数的地址也有效。这是因为,在这种情况下,函数的名称后面没有左括号,这在语法上是识别宏调用所必需的。

您可能偶尔希望避免使用函数的宏定义——也许是为了使您的程序更易于调试。有两种方法可以做到这一点:

  • 您可以通过将函数名称括在括号中来避免特定用途中的宏定义。这是有效的,因为函数的名称没有出现在可以识别为宏调用的语法上下文中。
  • 您可以使用“#undef”预处理器指令禁止整个源文件的任何宏定义,除非该工具的描述中另有明确说明。

例如,假设头文件 stdlib.h 声明了一个名为 abs 的函数:

extern int abs (int);

并且还为 abs 提供一个宏定义:

#include <stdlib.h>
int f (int *i) { return abs (++*i); }

对 abs 的引用可能指的是宏或函数。另一方面,在以下每个示例中,引用的是函数而不是宏。

#include <stdlib.h>
int g (int *i) { return (abs) (++*i); }

#undef abs
int h (int *i) { return abs (++*i); }

由于为函数加倍(double for)的宏定义的行为方式与实际函数版本完全相同,因此通常不需要任何这些方法。事实上,删除宏定义通常只会让你的程序变慢。

2.3.3. 保留名称

Reserved Names

无条件保留所有来自 ISO C 标准的库类型、宏、变量和函数的名称;您的程序可能不会重新定义这些名称。如果您的程序明确包含定义或声明它们的头文件,则保留所有其它库名称。这些限制有几个原因:

  • 例如,如果您使用一个名为 exit 的函数来执行与标准函数 exit 完全不同的操作,那么阅读您的代码的其它人可能会感到非常困惑。防止这种情况有助于使您的程序更易于理解,并有助于模块化和可维护性。
  • 它避免了用户意外重新定义由其它库函数调用的库函数的可能性。如果允许重新定义,那些其它功能将无法正常工作。
  • 它允许编译器在调用这些函数时进行任何它喜欢的特殊优化,而不会被用户重新定义。一些库工具,例如用于处理可变参数(请参阅可变参数函数)和非本地退出(请参阅非本地退出)的工具,实际上需要 C 编译器方面的大量合作,并且关于实现,编译器可能更容易将它们视为语言的内置部分。

除了本手册中记录的名称外,保留名称还包括所有以下划线 (‘_’) 开头的外部标识符(全局函数和变量)以及以两个下划线或一个下划线后跟一个大写字母开头的所有标识符(无论使用如何)都是保留名称。这样库和头文件就可以为内部目的定义函数、变量和宏,而不会有与用户程序中的名称发生冲突的风险。

为将来扩展 C 语言或 POSIX.1 环境保留了一些额外的标识符名称类。虽然现在将这些名称用于您自己的目的可能不会导致问题,但它们确实会增加与 C 或 POSIX 标准的未来版本冲突的可能性,因此您应该避免使用这些名称。

  • 以大写字母 ‘E’ 开头的名称后跟数字或大写字母可用于附加错误代码名称。请参阅错误报告
  • 以 ‘is’ 或 ‘to’ 开头的名称后跟小写字母可用于附加字符测试和转换功能。请参阅字符处理
  • 以 ‘LC_’ 开头的名字后跟大写字母可用于指定语言环境属性的附加宏。请参阅区域设置和国际化
  • 所有现有数学函数(见数学)的名称后缀为“f”或“l”,分别保留给对浮点和长双精度参数进行操作的相应函数。
  • 以 ‘SIG’ 开头后跟大写字母的名称保留用于其它信号名称。请参阅标准信号
  • 以 ‘SIG_’ 开头后跟大写字母的名称保留用于其它信号操作。请参阅基本信号处理
  • 以 ‘str’、‘mem’ 或 ‘wcs’ 开头后跟小写字母的名称保留用于其它字符串和数组函数。请参阅字符串和数组实用程序
  • 以 ‘_t’ 结尾的名称保留用于其它类型名称。

此外,一些单独的头文件保留了超出它们实际定义的名称。如果您的程序包含特定的头文件,您只需要担心这些限制。

  • 头文件 dirent.h 保留以 ‘d_’ 为前缀的名称。
  • 头文件 fcntl.h 保留以 ‘l_’, ‘F_’, ‘O_’,和 ‘S_’ 为前缀的名称。
  • 头文件 grp.h 保留以 ‘gr_’ 为前缀的名称。
  • 头文件 limits.h 保留以 ‘_MAX’ 为后缀的名称。
  • 头文件 pwd.h 保留以 ‘pw_’ 为前缀的名称。
  • 头文件 signal.h 保留以 ‘sa_’ 和 ‘SA_’ 为前缀的名称。
  • 头文件 sys/stat.h 保留以 ‘st_’ 和 ‘S_’ 为前缀的名称。
  • 头文件 sys/times.h 保留以 ‘tms_’ 为前缀的名称。
  • 头文件 termios.h 保留以 ‘c_’, ‘V’, ‘I’, ‘O’,和 ‘TC’ 为前缀的名称; 和以 ‘B’ 为前缀的名称后跟一个数字。

2.3.4. 功能测试宏

Feature Test Macros

编译源文件时可用的确切功能集由您定义的功能测试宏控制。

如果你使用‘gcc -ansi’编译你的程序,你只会得到 ISO C 库的特性,除非你通过定义一个或多个特性宏来明确请求额外的特性。有关 GCC 选项的更多信息,请参阅GNU CC 手册中的 GNU CC 命令选项。

您应该使用 ‘#define’ 预处理器指令在源代码文件顶部定义这些宏。这些指令必须位于系统头文件的任何 #include 之前。最好将它们放在文件中的第一个位置,仅在前面加上注释。您也可以使用 GCC 的“-D”选项,但最好让源文件以独立的方式表明它们自己的含义。

该系统的存在是为了让库符合多种标准。尽管不同的标准经常被描述为彼此的超集,但它们通常是不兼容的,因为较大的标准需要具有较小标准保留给用户程序的名称的函数。这不仅仅是学究气——这在实践中一直是个问题。例如,一些非 GNU 程序定义了与这个库的 getline 无关的名为 getline 的函数。如果不加选择地启用所有功能,它们将无法编译。

这不应用于验证程序是否符合有限标准。这不足以达到这个目的,因为它不会保护您不包含标准之外的头文件,或者依赖于标准中未定义的语义。

_POSIX_SOURCE

如果您定义此宏,则 POSIX.1 标准(IEEE 标准 1003.1)的功能以及所有 ISO C 工具都可用。

如果将宏 _POSIX_C_SOURCE 定义为正整数,则 _POSIX_SOURCE 的状态无关紧要。

_POSIX_C_SOURCE

将此宏定义为一个正整数,以控制哪些 POSIX 功能可用。该宏的值越大,可用的功能就越多。

如果将此宏定义为大于或等于 1 的值,则 POSIX.1 标准(IEEE 标准 1003.1-1990)的 1990 版中的功能可用。

如果将此宏定义为大于或等于 2 的值,则 1992 版 POSIX.2 标准(IEEE 标准 1003.2-1992)中的功能可用。

如果将此宏定义为大于或等于 199309L 的值,则 POSIX.1b 标准(IEEE 标准 1003.1b-1993)的 1993 版中的功能可用。

如果将此宏定义为大于或等于 199506L 的值,则 POSIX.1c 标准(IEEE 标准 1003.1c-1995)的 1995 版中的功能可用。

如果将此宏定义为大于或等于 200112L 的值,则 2001 版 POSIX 标准(IEEE 标准 1003.1-2001)的功能可用。

如果将此宏定义为大于或等于 200809L 的值,则 2008 版 POSIX 标准(IEEE 标准 1003.1-2008)中的功能可用。

_POSIX_C_SOURCE 的更大值将启用未来的扩展。POSIX 标准过程将根据需要定义这些值,并且 GNU C 库应该在它们标准化后的一段时间内支持它们。POSIX.1 的 1996 版 (ISO/IEC 9945-1: 1996) 规定,如果将 _POSIX_C_SOURCE 定义为大于或等于 199506L 的值,则 1996 版的功能可用。通常,在 GNU C 库中,在指定基本版本时会包含对标准的错误修复;例如,POSIX.1-2004 将始终包含值 200112L。

_XOPEN_SOURCE

_XOPEN_SOURCE_EXTENDED

如果您定义此宏,则包含 X/Open 可移植性指南中描述的功能。这是 POSIX.1 和 POSIX.2 功能的超集,实际上 _POSIX_SOURCE 和 _POSIX_C_SOURCE 是自动定义的。

作为所有 Unices 的统一,也包含了仅在 BSD 和 SVID 中可用的功能。

如果还定义了宏 _XOPEN_SOURCE_EXTENDED,则可以使用更多功能。额外的功能将使 X/Open Unix 品牌所需的所有功能都可用。

如果宏 _XOPEN_SOURCE 的值为 500,这包括迄今为止描述的所有功能以及来自单一 Unix 规范版本 2 的一些新定义。值 600(对应于第六版)包括来自 SUSv3 的定义,并使用 700(第七版 ) 包括来自 SUSv4 的定义。

_LARGEFILE_SOURCE

如果定义了此宏,则可以使用一些额外的功能来纠正所有先前标准中的一些缺点。具体来说,函数 fseeko 和 ftello 可用。如果没有这些函数,ISO C 接口(fseek、ftell)和低级 POSIX 接口(lseek)之间的差异将导致问题。

此宏是作为大文件支持扩展 (LFS) 的一部分引入的。

_LARGEFILE64_SOURCE

如果您定义此宏,则会提供一组额外的功能,使 32 位系统能够使用超出通常限制 2GB 大小的文件。如果系统不支持那么大的文件,则此界面不可用。在自然文件大小限制大于 2GB 的系统上(即,在 64 位系统上),新功能与替换功能相同。

新功能是由一组新的类型和功能替代现有的。这些新对象的名称包含 64 来表示意图,例如,off_t 与 off64_t 和 fseeko 与 fseeko64。

此宏是作为大文件支持扩展 (LFS) 的一部分引入的。它是一般不使用 64 位偏移的时期的过渡接口(参见 _FILE_OFFSET_BITS)。

_FILE_OFFSET_BITS

此宏确定应使用哪个文件系统接口,一个替换另一个。_LARGEFILE64_SOURCE 使 64 位接口可用作附加接口,_FILE_OFFSET_BITS 允许 64 位接口替换旧接口。

如果 _FILE_OFFSET_BITS 定义为值 32,则使用 32 位接口,并且像 off_t 这样的类型在 32 位系统上的大小为 32 位。

如果宏定义为值 64,则大文件接口替换旧接口。即,这些函数不能以不同的名称提供(因为它们使用 _LARGEFILE64_SOURCE)。相反,旧函数名称现在引用新函数,例如,对 fseeko 的调用现在确实调用 fseeko64。

如果未定义宏,则当前默认为 32,但由于需要更新 time_t 以确保 Y2038 安全,因此计划更改此默认值,并且应用程序不应依赖默认值。

仅当系统提供处理大文件的机制时才应选择此宏。在 64 位系统上,此宏不起作用,因为 *64 函数与普通函数相同。

此宏是作为大文件支持扩展 (LFS) 的一部分引入的。

_TIME_BITS

定义此宏来控制 time_t 的位大小,从而控制所有 time_t 派生类型的位大小以及所有相关函数的原型。

  1. 如果 _TIME_BITS 未定义,则 time_t 的位大小取决于体系结构。目前它在大多数架构上默认为 64 位。尽管它在某些传统架构(i686、ARM)上默认为 32 位,但已计划更改,应用程序不应依赖此。
  2. 如果 _TIME_BITS 定义为 64,则 time_t 定义为 64 位整数。在 time_t 传统上是 32 位的平台上,对正确系统调用的调用取决于系统运行的 Linux 内核版本。对于 5.1 以上的 Linux 内核版本,使用支持 64 位时间的系统调用。否则,后备代码将与遗留(即 32 位)系统调用一起使用。
  3. 如果 _TIME_BITS 定义为 32,则 time_t 定义为支持的 32 位整数。不建议这样做,因为 32 位 time_t 在 2038 年停止工作。
  4. 对于任何其它用例,都会发出编译时错误。

只有同时定义了_FILE_OFFSET_BITS=64 时,才能定义_TIME_BITS=64。

通过使用这个宏,某些端口获得了对 64 位时间的支持,因此不受 Y2038 问题的影响。

_ISOC99_SOURCE

如果定义了此宏,则包含来自 ISO C99 的功能。由于默认情况下包含这些功能,因此当编译器使用早期语言版本时,此宏最相关。

_ISOC11_SOURCE

如果定义了此宏,则包括对 ISO C99 的 ISO C11 扩展。

_ISOC2X_SOURCE

如果定义了此宏,则包括 ISO C11 的 ISO C2X 扩展。GNU C 库仅支持该标准草案中的一些特性。

STDC_WANT_LIB_EXT2

如果将此宏定义为值 1,则会启用 ISO/IEC TR 24731-2:2010(动态分配功能)中的功能。GNU C 库仅支持此 TR 中的部分功能。

STDC_WANT_IEC_60559_BFP_EXT

如果定义此宏,则会启用 ISO/IEC TS 18661-1:2014(C 的浮点扩展:二进制浮点运算)中的功能。GNU C 库仅支持此 TS 中的一些功能。

STDC_WANT_IEC_60559_FUNCS_EXT

如果定义此宏,则会启用 ISO/IEC TS 18661-4:2015(C 的浮点扩展:补充功能)中的功能。GNU C 库仅支持此 TS 中的一些功能。

STDC_WANT_IEC_60559_TYPES_EXT

如果定义此宏,则会启用 ISO/IEC TS 18661-3:2015(C 的浮点扩展:交换和扩展类型)中的功能。GNU C 库仅支持此 TS 中的一些功能。

STDC_WANT_IEC_60559_EXT

如果您定义此宏,则启用该标准附件 F 中定义的 ISO C2X 功能。这会影响总序函数和与 NaN 有效负载相关的函数的声明。

_GNU_SOURCE

如果您定义此宏,则所有内容都包括在内:ISO C89、ISO C99、POSIX.1、POSIX.2、BSD、SVID、X/Open、LFS 和 GNU 扩展。在 POSIX.1 与 BSD 冲突的情况下,POSIX 定义优先。

_DEFAULT_SOURCE

如果您定义此宏,则除了 X/Open、LFS 和 GNU 扩展之外,大多数功能都包含在内:其效果是启用 POSIX 2008 版的功能,以及某些 BSD 和 SVID 功能,无需单独的功能测试宏来控制 他们。

请注意,编译器选项也会影响包含的功能:

  • 如果您使用严格的一致性选项,编译器语言版本之外的功能将被禁用,尽管可以使用功能测试宏来启用它们。
  • 编译器选项启用的功能不会被功能测试宏覆盖。

_ATFILE_SOURCE

如果定义了此宏,则包含附加的 *at 接口。

_FORTIFY_SOURCE

如果将此宏定义为 1,则将安全加固添加到各种库函数中。如果定义为 2,则应用更严格的检查。如果定义为 3,GNU C 库也可能使用可能有额外性能开销的检查。

_DYNAMIC_STACK_SIZE_SOURCE

如果定义了此宏,则定义了正确的(但非编译时常量)MINSIGSTKSZ、SIGSTKSZ 和 PTHREAD_STACK_MIN。

_REENTRANT

_THREAD_SAFE

这些宏已过时。它们与使用值 199506L 定义 _POSIX_C_SOURCE 具有相同的效果。

一些非常古老的 C 库需要为基本功能(例如 getchar)定义这些宏之一以实现线程安全。

我们建议您在新程序中使用 _GNU_SOURCE。如果您没有为 GCC 指定“-ansi”选项,或其它一致性选项,例如 -std=c99,并且没有明确定义任何这些宏,则效果与将 _DEFAULT_SOURCE 定义为 1 相同。

当您定义功能测试宏以请求更大类别的功能时,为这些功能的子集另外定义功能测试宏是无害的。例如,如果您定义 _POSIX_C_SOURCE,那么定义 _POSIX_SOURCE 也无效。同样,如果您定义 _GNU_SOURCE,那么定义 _POSIX_SOURCE 或 _POSIX_C_SOURCE 也没有任何效果。

2.4. 手册路线图

Roadmap to the Manual

以下是本手册其余章节内容的概述。

  • 错误报告,描述了库检测到的错误是如何报告的。
  • 虚拟内存分配和分页,描述了 GNU C 库管理和使用虚拟和真实内存的设施,包括虚拟内存的动态分配。如果您事先不知道您的程序需要多少内存,您可以改为动态分配它,并通过指针对其进行操作。
  • 字符处理,包含有关字符分类函数(例如 isspace)和执行大小写转换的函数的信息。
  • 字符串和数组实用程序,描述了用于操作字符串(以空结尾的字符数组)和一般字节数组的函数,包括复制和比较等操作。
  • 字符集处理,包含有关使用大于通常 char 数据类型的字符集来操作字符和字符串的信息。
  • 语言环境和国际化,描述了选择特定国家或语言如何影响图书馆的行为。例如,语言环境会影响字符串的排序规则以及货币值的格式。
  • 搜索和排序,包含有关搜索和排序数组的函数的信息。通过提供适当的比较函数,您可以在任何类型的数组上使用这些函数。
  • 模式匹配,提供匹配正则表达式和 shell 文件名模式的函数,以及扩展单词的函数。
  • 输入/输出概述,全面介绍库中的输入和输出设施,并包含有关基本概念的信息,例如文件名。
  • 流上的输入/输出,描述了涉及流(或 FILE * 对象)的 I/O 操作。这些是来自 stdio.h 的普通 C 库函数。
  • 底层输入/输出,包含有关文件描述符上的 I/O 操作的信息。文件描述符是特定于 Unix 系列操作系统的较低级别的机制。
  • 文件系统接口,描述了对整个文件的操作,例如删除和重命名文件以及创建新目录的功能。本章还包含有关如何访问文件属性的信息,例如其所有者和文件保护模式。
  • 管道和FIFO,包含有关简单进程间通信机制的信息。管道允许两个相关进程之间的通信(例如父进程和子进程之间),而 FIFO 允许在同一台机器上共享公共文件系统的进程之间进行通信。
  • 套接字,描述了一种更复杂的进程间通信机制,它允许运行在不同机器上的进程通过网络进行通信。本章还包含有关 Internet 主机寻址以及如何使用系统网络数据库的信息。
  • 底层终端接口,描述如何更改终端设备的属性。例如,如果您想禁用用户键入的字符的回显,请阅读本章。
  • 数学,包含有关数学库函数的信息。这些包括诸如随机数生成器和整数上的余数函数以及浮点数上常见的三角函数和指数函数。
  • 算术函数,描述用于简单算术、浮点值分析和从字符串中读取数字的函数。
  • 日期和时间,描述了测量日历时间和 CPU 时间的函数,以及设置闹钟和定时器的函数。
  • 非本地退出,包含 setjmp 和 longjmp 函数的描述。这些函数为类似 goto 的跳转提供了便利,可以从一个函数跳转到另一个函数。
  • 信号处理,告诉你所有关于信号的信息——它们是什么,如何建立一个在特定类型的信号被传递时调用的处理程序,以及如何防止信号在程序的关键部分到达。
  • 基本程序/系统接口,告诉您的程序如何访问它们的命令行参数和环境变量。
  • 进程,包含有关如何启动新进程和运行程序的信息。
  • 任务控制,描述了用于操作进程组和控制终端的功能。如果您正在编写专门处理作业控制的 shell 或其它程序,则可能仅对本材料感兴趣。
  • 系统数据库和名称服务开关,描述了可用于在系统数据库中查找名称的服务,如何确定哪个服务用于哪个数据库,以及如何实现这些服务,以便贡献者可以设计自己的服务。
  • 用户和组,告诉您如何访问系统用户和组数据库。
  • 系统管理,描述了用于控制和获取有关您的程序正在执行的硬件和软件配置信息的功能。
  • 系统配置,告诉您如何获取有关各种操作系统限制的信息。提供这些参数中的大多数是为了与 POSIX 兼容。
  • 库中的 C 语言设施,包含有关 C 语言标准部分的库支持的信息,包括 sizeof 运算符和符号常量 NULL、如何编写接受可变数量参数的函数以及描述范围和其它属性的常量的数字类型。还有一个简单的调试机制,允许您在代码中放置断言,并在测试失败时打印诊断消息。
  • 库设施摘要,提供库中所有函数、变量和宏的摘要,具有完整的数据类型和函数原型,并说明每个标准或系统源自什么。
  • 安装 GNU C 库,解释如何在您的系统上构建和安装 GNU C 库,以及如何报告您可能发现的任何错误。
  • 库维护,说明如何添加新功能或将库移植到新系统。

如果您已经知道感兴趣的设施名称,可以在库设施概要中查找。这为您提供了其语法的摘要以及指向何处可以找到更详细说明的指针。例如,如果您只想验证函数参数的顺序和类型,则此附录特别有用。它还告诉您每个函数、变量或宏源自什么标准或系统。

3. 参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值