> For the complete documentation index, see [llms.txt](https://man.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://man.bsdcn.org/sys/intro.2.md).

# intro(2)

`intro`, `errno` — 系统调用及其错误编号简介

## 名称

`intro`, `errno`

## 库

Lb libc

## 概要

`#include <sys/syscall.h>`

`#include <errno.h>`

## 描述

本节包含构成 FreeBSD 编程环境的系统调用。本页还提供了与系统调用相关的常见定义和概念的概述、在何处查找系统上当前可用的系统调用表，以及它们的错误返回。

## 定义

**进程 ID** 系统中每个活动进程都由一个称为进程 ID 的非负整数唯一标识。此 ID 的范围从 0 到 99999。

**父进程 ID** 新进程由当前活动的进程创建（参见 [fork(2)](/sys/fork.2.md)）。进程的父进程 ID 最初是其创建者的进程 ID。如果创建进程退出，每个子进程的父进程 ID 将被设置为调用进程的 reaper（参见 [procctl(2)](/sys/procctl.2.md)），通常是 [init(8)](/man8/init.8.md)。

**进程组** 每个活动进程是一个进程组的成员，该进程组由一个称为进程组 ID 的非负整数标识。这是组长的进程 ID。这种分组允许对相关进程进行信号传递（参见 [termios(4)](/man4/termios.4.md)）以及 [csh(1)](/man1/csh.1.md) 的作业控制机制。

**会话** 会话是一个或多个进程组的集合。会话通过成功调用 [setsid(2)](/sys/setsid.2.md) 创建，这使调用者成为新会话中唯一进程组的唯一成员。

**会话组长** 通过成功调用 [setsid(2)](/sys/setsid.2.md) 创建了新会话的进程被称为会话组长。只有会话组长可以将终端作为其控制终端获取（参见 [termios(4)](/man4/termios.4.md)）。

**控制进程** 具有控制终端的会话组长是控制进程。

**控制终端** 与会话关联的终端被称为该会话及其成员的控制终端。

**终端进程组 ID** 终端可由会话组长作为其控制终端获取。一旦终端与会话关联，会话内的任何进程组都可以通过将终端进程组 ID 设置为该进程组的 ID 而被置于前台。此功能用于仲裁争用同一终端的多个作业（参见 [csh(1)](/man1/csh.1.md) 和 [tty(4)](/man4/tty.4.md)）。

**孤儿进程组** 如果进程组不受作业控制 shell 的控制，则被视为孤儿（orphaned）。更确切地说，当进程组的所有成员都没有与该组在同一会话但属于不同进程组的父进程时，该进程组即为孤儿。注意，当进程退出时，其子进程的父进程通常会更改为 [init(8)](/man8/init.8.md)，后者位于单独的会话中。孤儿进程组的所有成员并不一定都是孤儿进程（即创建进程已退出的那些）。会话组长的进程组根据定义是孤儿。

**实际用户 ID 和实际组 ID** 系统上的每个用户由一个称为实际用户 ID 的正整数标识。

每个用户还是一个或多个组的成员。其中一个组与其他组区别开来，用于实现记账功能。与此区别组对应的正整数被称为实际组 ID。

所有进程都有实际用户 ID 和实际组 ID。这些是从创建它的进程的等效属性初始化的。

**有效用户 ID、有效组 ID 和组访问列表** 对系统资源的访问由两个值控制：有效用户 ID 和组访问列表。组访问列表的第一个成员也被称为有效组 ID。在 POSIX.1 中，组访问列表被称为补充组 ID 集合，且未指定有效组 ID 是否为列表的成员。

有效用户 ID 和有效组 ID 最初分别是进程的实际用户 ID 和实际组 ID。两者都可以通过执行 set-user-ID 或 set-group-ID 文件来修改（可能由其某个祖先执行）（参见 [execve(2)](/sys/execve.2.md)）。按照惯例，有效组 ID（组访问列表的第一个成员）被复制，因此执行 set-group-ID 程序不会导致丢失原始（实际）组 ID。

组访问列表是一组组 ID，仅用于确定资源可访问性。访问检查按照下文 "文件访问权限" 中的描述执行。

**保存的设置用户 ID 和保存的设置组 ID** 当进程执行新文件时，如果文件是 set-user-ID 的，则有效用户 ID 设置为文件所有者；如果文件是 set-group-ID 的，则有效组 ID（组访问列表的第一个元素）设置为文件的组。然后进程的有效用户 ID 被记录为保存的设置用户 ID，有效组 ID 被记录为保存的设置组 ID。这些值可用于在恢复到实际 ID 后重新获得这些值作为有效用户或组 ID（参见 [setuid(2)](/sys/setuid.2.md)）。在 POSIX.1 中，保存的设置用户 ID 和保存的设置组 ID 是可选的，并在 setuid 和 setgid 中使用，但对于超级用户这不能按期望工作。

**超级用户** 如果进程的有效用户 ID 为 0，则该进程被识别为超级用户（super-user）进程并被授予特殊特权。

**描述符** 当文件通过 [open(2)](/sys/open.2.md) 或 [dup(2)](/sys/dup.2.md) 引用，或当套接字由 [pipe(2)](/sys/pipe.2.md)、[socket(2)](/sys/socket.2.md) 或 [socketpair(2)](/sys/socketpair.2.md) 创建时，系统分配的一个整数，用于从给定进程或其任何子进程唯一标识该文件或套接字的访问路径。

**文件名** 由最多 `NAME_MAX` 个字符组成的名称可用于命名普通文件、特殊文件或目录。

这些字符可以是任意的八位值，不包括 `NUL`（ASCII 0）和 `/` 字符（斜杠，ASCII 47）。

注意，通常不宜将 `*`、`?`、`[` 或 `]` 作为文件名的一部分，因为 shell 会赋予这些字符特殊含义。

**路径名** 路径名是一个以 `NUL` 结尾的字符串，以可选的斜杠 `/` 开头，后跟零个或多个以斜杠分隔的目录名，可选地后跟一个文件名。路径名的总长度必须小于 `PATH_MAX` 个字符。在某些系统上，此限制可能是无限的。

如果路径名以斜杠开头，则路径搜索从根目录开始。否则，搜索从当前工作目录开始。单独的斜杠命名根目录。空路径名引用当前目录。

**目录** 目录是一种特殊类型的文件，包含作为对其他文件引用的条目。目录条目被称为链接。按照惯例，目录至少包含两个链接，`.` 和 `..`，分别称为 dot 和 dot-dot。dot 引用目录本身，dot-dot 引用其父目录。

**根目录和当前工作目录** 每个进程都关联有根目录和当前工作目录的概念，用于解析路径名搜索。进程的根目录不必是根文件系统的根目录。

**文件访问权限** 文件系统中的每个文件都有一组访问权限。这些权限用于确定进程是否可以对文件执行请求的操作（例如以写入方式打开文件）。访问权限在文件创建时建立。它们可在稍后通过 [chmod(2)](/sys/chmod.2.md) 调用更改。文件访问权限根据文件是否可被读取、写入或执行来细分。目录文件使用执行权限来控制是否可搜索该目录。

文件访问权限由系统解释，因为它们适用于三类不同的用户：文件所有者、文件所属组的用户以及其他任何人。每个文件对这些类中的每一类都有独立的访问权限集合。进行访问检查时，系统通过检查适用于调用者的访问信息来决定是否应授予权限。

文件上的读、写和执行/搜索权限在以下情况下授予进程：

进程的有效用户 ID 为超级用户的 ID。注意，即使是超级用户也无法执行不可执行的文件。

进程的有效用户 ID 与文件所有者的用户 ID 匹配，且所有者权限允许该访问。

进程的有效用户 ID 与文件所有者的用户 ID 不匹配，且进程的有效组 ID 与文件的组 ID 匹配，或者文件的组 ID 在进程的组访问列表中，且组权限允许该访问。

进程的有效用户 ID 和有效组 ID 及组访问列表均不与文件对应的用户 ID 和组 ID 匹配，但 "其他用户" 的权限允许访问。

否则，拒绝访问。

**套接字和地址族** 套接字是进程间通信的端点。每个套接字都有用于发送和接收数据的队列。套接字根据其通信属性进行分类。这些属性包括在套接字处发送和接收的消息是否需要伙伴的名称、通信是否可靠、用于命名消息收件人的格式等。系统的每个实例支持一些套接字类型的集合；有关可用类型及其属性的更多信息，请参见 [socket(2)](/sys/socket.2.md)。

系统的每个实例支持若干组通信协议。每个协议集支持某种格式的地址。地址族是特定协议组的地址集合。每个套接字都有一个从创建套接字的地址族中选择的地址。

## 文件

**`/usr/include/sys/syscall.h`** 当前可用的系统调用表。

## 错误

几乎所有系统调用都通过外部标识符 `errno` 引用提供错误编号。此标识符定义于

`#include <sys/errno.h>`

中，为：

```c
extern int * __error();
```

```c
#define errno (* __error())
```

`__error()` 函数返回一个指向线程特定结构中字段的指针，用于初始线程以外的线程。对于初始线程和非线程进程，`__error()` 返回一个指向全局 `errno` 变量的指针，该变量与之前的定义兼容。

当系统调用检测到错误时，它返回一个指示失败的整数值（通常为 -1），并相应地设置变量 `errno`。这允许在收到 -1 时解释失败并相应地采取行动。成功的调用从不设置 `errno`；一旦设置，它将保持直到发生另一个错误。它只应在错误后检查。注意，许多系统调用重载了这些错误编号的含义，必须根据调用的类型和情况来解释含义。

以下是 `#include <sys/errno.h>` 中给出的错误及其名称的完整列表。

**0 `Eundefined`** *未定义错误：0。* 未使用。

**1 `EPERM`** *操作不允许。* 试图执行仅限于具有适当特权的进程或文件或其他资源所有者的操作。

**2 `ENOENT`** *没有此文件或目录。* 指定路径名的某个组件不存在，或路径名为空字符串。

**3 `ESRCH`** *没有此进程。* 找不到与给定进程 ID 对应的进程。

**4 `EINTR`** *被中断的系统调用。* 在可中断函数执行期间，进程捕获到异步信号（如 `SIGINT` 或 `SIGQUIT`）。如果信号处理程序执行正常返回，被中断的系统调用将看似返回了错误条件。

**5 `EIO`** *输入/输出错误。* 发生了某些物理输入或输出错误。此错误在后续对同一文件描述符的操作之前不会报告，并可能被任何后续错误覆盖。

**6 `ENXIO`** *设备未配置。* 对特殊文件的输入或输出引用了不存在的设备，或提出了超出设备限制的请求。例如，当磁带机不在线或驱动器上未装入磁盘包时，也可能发生此错误。

**7 `E2BIG`** *参数列表太长。* 新进程的参数和环境列表使用的字节数超过了当前限制（sys/param.h 中的 `NCARGS`）。

**8 `ENOEXEC`** *Exec 格式错误。* 请求执行一个文件，虽然它有适当的权限，但不符合可执行文件所需的格式。

**9 `EBADF`** *错误的文件描述符。* 文件描述符参数超出范围，引用了未打开的文件，或对仅以写入（读取）方式打开的文件发出了读（写）请求。

**10 `ECHILD`** *没有子进程。* 由没有现有或未等待子进程的进程执行了 [wait(2)](/sys/wait.2.md) 或 [waitpid(2)](/sys/wait.2.md) 函数。

**11 `EDEADLK`** *避免资源死锁。* 试图锁定系统资源，这会导致死锁情况。

**12 `ENOMEM`** *无法分配内存。* 新进程映像所需的内存超过了硬件或系统施加的内存管理约束所允许的量。交换空间不足通常是暂时的；然而，核心内存不足则不是。软限制可以增加到相应的硬限制。

**13 `EACCES`** *权限拒绝。* 试图以文件访问权限所禁止的方式访问文件。

**14 `EFAULT`** *错误地址。* 系统在尝试使用调用的参数时检测到无效地址。

**15 `ENOTBLK`** *需要块设备。* 在非块设备或文件上尝试了块设备操作。

**16 `EBUSY`** *设备忙。* 试图以与请求冲突的方式使用当时正在使用的系统资源。

**17 `EEXIST`** *文件已存在。* 在不适当的上下文中提到了现有文件，例如作为 [link(2)](/sys/link.2.md) 系统调用中的新链接名。

**18 `EXDEV`** *跨设备链接。* 试图链接到另一文件系统上的文件。

**19 `ENODEV`** *设备不支持此操作。* 试图对设备应用不适当的函数，例如尝试读取只写设备（如打印机）。

**20 `ENOTDIR`** *不是目录。* 指定路径名的某个组件存在，但在期望目录时它不是目录。

**21 `EISDIR`** *是目录。* 试图以写入模式打开目录。

**22 `EINVAL`** *无效参数。* 提供了某些无效参数。例如，向 [signal(3)](/gen/signal.3.md) 函数或 [kill(2)](/sys/kill.2.md) 系统调用指定了未定义的信号。

**23 `ENFILE`** *系统中打开文件过多。* 已达到系统允许的最大打开文件数，在至少关闭一个之前无法满足打开请求。

**24 `EMFILE`** *打开文件过多。* 已达到进程允许的最大文件描述符数，在至少关闭一个之前无法满足打开请求。[getdtablesize(2)](/sys/getdtablesize.2.md) 系统调用将获取当前限制。

**25 `ENOTTY`** *设备的 ioctl 不适当。* 对不适合该操作的文件或特殊设备尝试了控制函数（参见 [ioctl(2)](/sys/ioctl.2.md)）。

**26 `ETXTBSY`** *文本文件忙。* 新进程是一个纯过程（共享文本）文件，该文件被另一进程以写入方式打开，或者在纯过程文件正在执行时，[open(2)](/sys/open.2.md) 调用请求了写访问。

**27 `EFBIG`** *文件太大。* 文件大小超过了最大值。

**28 `ENOSPC`** *设备上没有剩余空间。* 对普通文件的 [write(2)](/sys/write.2.md)、目录或符号链接的创建或目录项的创建失败，因为文件系统上没有更多可用磁盘块，或者新创建文件的 inode 分配失败，因为文件系统上没有更多可用 inode。

**29 `ESPIPE`** *非法寻址。* 在套接字、管道或 FIFO 上发出了 [lseek(2)](/sys/lseek.2.md) 系统调用。

**30 `EROFS`** *只读文件系统。* 试图在当时为只读的文件系统上修改文件或目录。

**31 `EMLINK`** *链接过多。* 已超过单个文件的最大允许硬链接数。此限制是文件系统相关的变量（ufs(4) 上的 `UFS_LINK_MAX`，[fusefs(4)](/man4/fusefs.4.md) 上的 `FUSE_LINK_MAX`，[tmpfs(4)](/man4/tmpfs.4.md) 上的 `TMPFS_MAX`）。

**32 `EPIPE`** *管道破裂。* 向没有进程读取数据的管道、套接字或 FIFO 写入。

**33 `EDOM`** *数值参数超出域。* 数值输入参数超出了数学函数定义的域。

**34 `ERANGE`** *结果太大。* 函数的数值结果太大，无法放入可用空间（可能超出了精度）。

**35 `EAGAIN`** *资源暂时不可用。* 这是临时条件，稍后对同一例程的调用可能正常完成。

**36 `EINPROGRESS`** *操作正在进行中。* 在非阻塞对象上尝试了一个需要很长时间才能完成的操作，如 [connect(2)](/sys/connect.2.md)（参见 [fcntl(2)](/sys/fcntl.2.md)）。

**37 `EALREADY`** *操作已在进行中。* 在已有操作正在进行的非阻塞对象上尝试了操作。

**38 `ENOTSOCK`** *对非套接字进行套接字操作。* 不言自明。

**39 `EDESTADDRREQ`** *需要目标地址。* 套接字上的操作省略了必需的地址。

**40 `EMSGSIZE`** *消息太长。* 套接字上发送的消息大于内部消息缓冲区或某些其他网络限制。

**41 `EPROTOTYPE`** *套接字的协议类型错误。* 指定了不支持所请求套接字类型语义的协议。例如，你不能将 ARPA Internet UDP 协议与 `SOCK_STREAM` 类型一起使用。

**42 `ENOPROTOOPT`** *协议不可用。* 在 [getsockopt(2)](/sys/getsockopt.2.md) 或 [setsockopt(2)](/sys/getsockopt.2.md) 调用中指定了错误的选项或级别。

**43 `EPROTONOSUPPORT`** *协议不受支持。* 该协议未配置到系统中或没有实现。

**44 `ESOCKTNOSUPPORT`** *套接字类型不受支持。* 套接字类型的支持未配置到系统中或没有实现。

**45 `EOPNOTSUPP`** *操作不受支持。* 尝试的操作不支持所引用的对象类型。通常当文件描述符引用不支持此操作的文件或套接字时发生，例如尝试在数据报套接字上接受（accept）连接。

**46 `EPFNOSUPPORT`** *协议族不受支持。* 协议族未配置到系统中或没有实现。

**47 `EAFNOSUPPORT`** *协议族不支持地址族。* 使用了与所请求协议不兼容的地址。例如，你不一定期望能够将 NS 地址与 ARPA Internet 协议一起使用。

**48 `EADDRINUSE`** *地址已被使用。* 通常每个地址只允许一种用途。

**49 `EADDRNOTAVAIL`** *无法分配请求的地址。* 通常是由于试图使用本机上不存在的地址创建套接字。

**50 `ENETDOWN`** *网络已断开。* 套接字操作遇到了已断开的网络。

**51 `ENETUNREACH`** *网络不可达。* 对不可达网络尝试了套接字操作。

**52 `ENETRESET`** *网络在重置时断开连接。* 你连接的主机崩溃并重启。

**53 `ECONNABORTED`** *软件导致连接中止。* 连接中止是由你的主机内部引起的。

**54 `ECONNRESET`** *连接被对端重置。* 连接被对端强制关闭。这通常由于超时或重启导致远程套接字上的连接丢失。

**55 `ENOBUFS`** *没有可用的缓冲区空间。* 由于系统缺乏足够的缓冲区空间或队列已满，套接字或管道上的操作未执行。

**56 `EISCONN`** *套接字已连接。* 在已连接的套接字上发出了 [connect(2)](/sys/connect.2.md) 请求；或在已连接的套接字上指定了目的地的 [sendto(2)](/sys/send.2.md) 或 [sendmsg(2)](/sys/send.2.md) 请求。

**57 `ENOTCONN`** *套接字未连接。* 发送或接收数据的请求被拒绝，因为套接字未连接且（在数据报套接字上发送时）未提供地址。

**58 `ESHUTDOWN`** *套接字关闭后无法发送。* 发送数据的请求被拒绝，因为套接字已通过先前的 [shutdown(2)](/sys/shutdown.2.md) 调用关闭。

**60 `ETIMEDOUT`** *操作超时。* [connect(2)](/sys/connect.2.md) 或 [send(2)](/sys/send.2.md) 请求失败，因为连接方在一段时间后未正确响应。超时时间取决于通信协议。

**61 `ECONNREFUSED`** *连接被拒绝。* 无法建立连接，因为目标机器主动拒绝。这通常是由于尝试连接到外部主机上不活动的服务。

**62 `ELOOP`** *符号链接层级过多。* 路径名查找涉及超过 32（`MAXSYMLINKS`）个符号链接。

**63 `ENAMETOOLONG`** *文件名太长。* 路径名的某个组件超过 `NAME_MAX` 个字符，或整个路径名超过 `PATH_MAX` 个字符。另参见 [pathconf(2)](/sys/pathconf.2.md) 中 `_PC_NO_TRUNC` 的描述。

**64 `EHOSTDOWN`** *主机已宕机。* 套接字操作失败，因为目标主机已宕机。

**65 `EHOSTUNREACH`** *没有到主机的路由。* 对不可达主机尝试了套接字操作。

**66 `ENOTEMPTY`** *目录非空。* 将包含除 `.` 和 `..` 以外条目的目录提供给删除目录或重命名调用。

**67 `EPROCLIM`** *进程过多。*

**68 `EUSERS`** *用户过多。* 配额系统用完了表项。

**69 `EDQUOT`** *磁盘配额超出。* 对普通文件的 [write(2)](/sys/write.2.md)、目录或符号链接的创建或目录项的创建失败，因为用户的磁盘块配额已耗尽，或新创建文件的 inode 分配失败，因为用户的 inode 配额已耗尽。

**70 `ESTALE`** *过期的 NFS 文件句柄。* 试图访问一个打开的文件（在 NFS 文件系统上），该文件现在如文件描述符所引用的那样不可用。这可能表示该文件已在 NFS 服务器上删除或发生了其他灾难性事件。

**72 `EBADRPC`** *RPC 结构错误。* RPC 信息交换失败。

**73 `ERPCMISMATCH`** *RPC 版本错误。* 远程对端的 RPC 版本与本地版本不兼容。

**74 `EPROGUNAVAIL`** *RPC 程序不可用。* 请求的程序未在远程主机上注册。

**75 `EPROGMISMATCH`** *程序版本错误。* 请求的程序版本在远程主机上不可用（RPC）。

**76 `EPROCUNAVAIL`** *程序的错误过程。* 尝试了对远程程序中不存在的过程进行 RPC 调用。

**77 `ENOLCK`** *没有可用的锁。* 达到了系统对同时文件锁数量的限制。

**78 `ENOSYS`** *函数未实现。* 尝试了此系统上不可用的系统调用。

**79 `EFTYPE`** *不适当的文件类型或格式。* 文件类型对于操作错误，或数据文件格式错误。

**80 `EAUTH`** *认证错误。* 尝试使用无效的认证票据挂载 NFS 文件系统。

**81 `ENEEDAUTH`** *需要认证器。* 在挂载给定 NFS 文件系统之前必须获取认证票据。

**82 `EIDRM`** *标识符已移除。* 当当前进程正在等待 IPC 标识符时，该标识符被移除。

**83 `ENOMSG`** *没有所需类型的消息。* IPC 消息队列不包含所需类型的消息，或消息目录不包含请求的消息。

**84 `EOVERFLOW`** *值太大，无法存储在数据类型中。* 函数的数值结果太大，无法存储在调用者提供的空间中。

**85 `ECANCELED`** *操作已取消。* 计划的操作被取消。

**86 `EILSEQ`** *非法字节序列。* 在解码多字节字符时，函数遇到了无效或不完整的字节序列，或给定的宽字符无效。

**87 `ENOATTR`** *未找到属性。* 指定的扩展属性不存在。

**88 `EDOOFUS`** *编程错误。* 函数或 API 以只能在运行时检测到的方式被滥用。

**89 `EBADMSG`** *错误消息。* 检测到损坏的消息。

**90 `EMULTIHOP`** *尝试多跳。* 此错误代码未使用，但为与其他系统兼容而保留。

**91 `ENOLINK`** *链接已被切断。* 此错误代码未使用，但为与其他系统兼容而保留。

**92 `EPROTO`** *协议错误。* 设备或套接字遇到不可恢复的协议错误。

**93 `ENOTCAPABLE`** *权限不足。* 对 capability 文件描述符的操作需要比 capability 允许的更大权限。

**94 `ECAPMODE`** *在 capability 模式下不允许。* 系统调用或操作不允许 capability 模式进程。

**95 `ENOTRECOVERABLE`** *状态不可恢复。* 受 robust mutex 保护的状态不可恢复。

**96 `EOWNERDEAD`** *先前所有者已终止。* robust mutex 的所有者在持有 mutex 锁时终止。

**97 `EINTEGRITY`** *完整性检查失败。* 诸如校验哈希或交叉相关等完整性检查失败。完整性错误位于内核 I/O 堆栈中介于标识系统调用参数错误的 `EINVAL` 和标识底层存储介质错误的 `EIO` 之间。它通常由中间内核层（如文件系统或内核内 GEOM 子系统）在检测到不一致时引发。用途包括允许 [mount(8)](/man8/mount.8.md) 命令返回不同的退出值，以在系统启动期间自动化运行 [fsck(8)](/man8/fsck.8.md)。

## 参见

[intro(3)](/misc/intro.3.md), [perror(3)](/string/strerror.3.md), [dtrace\_syscall(4)](/man4/dtrace_syscall.4.md)

## 历史

`errno`(2) 手册页首次出现于 Version 5 AT\&T UNIX。
