在 Linux 系统中,errno 是一个全局变量,用于表示系统调用或库函数调用出错时的错误码。每当一个系统调用或函数遇到错误时,它会将错误码存储在 errno 变量中。通过检查 errno,程序员可以获得关于错误的具体信息。

本文将详细介绍 errno 的工作原理、常见的错误码以及如何使用 errno


1. errno 变量简介

  • errno 是一个 全局变量,通常定义在头文件 <errno.h> 中。
  • 当一个系统调用或标准库函数失败时,errno 会被设置为相应的错误码。
  • errno 是线程局部存储(Thread Local Storage, TLS)变量,因此在多线程程序中,每个线程都有自己的 errno

2. 常见的 errno 错误码

errno 错误码是由系统调用或库函数返回的整数值,代表不同类型的错误。错误码的值会在 <errno.h> 中定义,并且通常会有对应的字符串描述。

以下是一些常见的 errno 错误码及其解释:

错误码错误号错误描述说明
EACCES13权限拒绝(Permission denied)操作系统拒绝访问文件或目录
EBADF9无效文件描述符(Bad file descriptor)提供的文件描述符无效
EEXIST17文件已存在(File exists)尝试创建一个已存在的文件
EFAULT14错误地址(Bad address)提供的地址无效或不对齐
EINVAL22无效参数(Invalid argument)提供给函数的参数无效
ENOMEM12内存不足(Out of memory)系统没有足够的内存来执行操作
ENOSPC28空间不足(No space left on device)文件系统已满
ENOTDIR20不是目录(Not a directory)操作的路径不是目录
EPERM1操作不允许(Operation not permitted)无法执行权限相关操作
ESRCH3进程不存在(No such process)查找进程时未找到该进程
EINTR4被信号中断(Interrupted system call)系统调用被信号中断
ENFILE23系统文件表溢出(File table overflow)系统的文件描述符表已满
ENOTTY25非终端设备(Not a typewriter)用于 I/O 操作的设备不是终端设备
EIO5输入/输出错误(Input/output error)文件或设备发生 I/O 错误

3. 如何使用 errno

  1. 获取错误码
    • 当一个函数调用失败时,你可以通过 errno 来查看具体的错误码。
    • 例如,使用 open() 打开文件失败后,errno 将会被设置为一个相应的错误码。
  2. 错误码的描述
    • 你可以使用 perror() 或 strerror() 来打印或获取 errno 错误码的字符串描述。

3.1 使用 perror() 打印错误信息

perror() 函数打印出与 errno 相关的错误信息。

#include &lt;stdio.h>
#include &lt;errno.h>

int main() {
    FILE *fp = fopen("nonexistent_file.txt", "r");
    if (fp == NULL) {
        perror("Error opening file");
    }
    return 0;
}

输出:

Error opening file: No such file or directory

  • perror() 会根据 errno 输出错误信息,附带一个自定义的字符串。

3.2 使用 strerror() 获取错误描述

strerror() 函数返回一个包含错误描述的字符串。这个函数的参数是 errno 的值。

#include &lt;stdio.h>
#include &lt;errno.h>
#include &lt;string.h>

int main() {
    FILE *fp = fopen("nonexistent_file.txt", "r");
    if (fp == NULL) {
        printf("Error opening file: %s\n", strerror(errno));
    }
    return 0;
}

输出:

Error opening file: No such file or directory

  • strerror(errno) 返回 errno 错误码的描述字符串。

4. 例子:使用 errno 处理错误

下面是一个具体的例子,展示如何在代码中使用 errno 进行错误处理:

#include &lt;stdio.h>
#include &lt;errno.h>
#include &lt;string.h>
#include &lt;fcntl.h>

int main() {
    int fd = open("/nonexistent_file", O_RDONLY);
    
    if (fd == -1) {
        printf("Failed to open file: %s\n", strerror(errno));
        // 根据 errno 的值判断不同类型的错误
        if (errno == ENOENT) {
            printf("Error: The file does not exist.\n");
        } else if (errno == EACCES) {
            printf("Error: Permission denied.\n");
        }
    }
    
    return 0;
}

输出:

Failed to open file: No such file or directory
Error: The file does not exist.

在这个例子中:

  • 当 open() 失败时,errno 被设置为 ENOENT(即文件不存在)。
  • 使用 strerror(errno) 打印具体的错误信息。
  • 你也可以根据 errno 的具体值来判断不同的错误类型并做出相应处理。

5. 常见错误码及其应用

5.1 文件操作相关错误

  • ENOENT(2):文件或目录不存在
  • EACCES(13):权限被拒绝
  • EBADF(9):无效的文件描述符
  • ENOSPC(28):磁盘空间不足
  • EISDIR(21):操作是目录,但被用作文件操作

5.2 网络相关错误

  • ECONNREFUSED(111):连接被拒绝
  • ETIMEDOUT(110):连接超时
  • EHOSTUNREACH(113):主机不可达

5.3 内存管理相关错误

  • ENOMEM(12):内存不足
  • EFAULT(14):无效的内存地址
  • EINVAL(22):无效的参数

6. 总结

  • errno 是用来表示系统调用或库函数出错时的错误码。
  • 你可以通过 strerror() 或 perror() 获取错误码的描述信息,帮助你诊断问题。
  • 常见的错误码包括文件操作错误、内存管理错误、网络错误等。
  • errno 的值在每次调用系统函数失败时都会被自动设置,可以通过检查 errno 来判断错误原因。

理解 errno 及其错误码的使用对于调试程序和处理错误非常重要,它是 Linux 编程中的基础之一。