在 Linux 系统中,errno
是一个全局变量,用于表示系统调用或库函数调用出错时的错误码。每当一个系统调用或函数遇到错误时,它会将错误码存储在 errno
变量中。通过检查 errno
,程序员可以获得关于错误的具体信息。
本文将详细介绍 errno
的工作原理、常见的错误码以及如何使用 errno
。
1. errno
变量简介
errno
是一个 全局变量,通常定义在头文件<errno.h>
中。- 当一个系统调用或标准库函数失败时,
errno
会被设置为相应的错误码。 errno
是线程局部存储(Thread Local Storage, TLS)变量,因此在多线程程序中,每个线程都有自己的errno
。
2. 常见的 errno
错误码
errno
错误码是由系统调用或库函数返回的整数值,代表不同类型的错误。错误码的值会在 <errno.h>
中定义,并且通常会有对应的字符串描述。
以下是一些常见的 errno
错误码及其解释:
错误码 | 错误号 | 错误描述 | 说明 |
---|---|---|---|
EACCES | 13 | 权限拒绝(Permission denied) | 操作系统拒绝访问文件或目录 |
EBADF | 9 | 无效文件描述符(Bad file descriptor) | 提供的文件描述符无效 |
EEXIST | 17 | 文件已存在(File exists) | 尝试创建一个已存在的文件 |
EFAULT | 14 | 错误地址(Bad address) | 提供的地址无效或不对齐 |
EINVAL | 22 | 无效参数(Invalid argument) | 提供给函数的参数无效 |
ENOMEM | 12 | 内存不足(Out of memory) | 系统没有足够的内存来执行操作 |
ENOSPC | 28 | 空间不足(No space left on device) | 文件系统已满 |
ENOTDIR | 20 | 不是目录(Not a directory) | 操作的路径不是目录 |
EPERM | 1 | 操作不允许(Operation not permitted) | 无法执行权限相关操作 |
ESRCH | 3 | 进程不存在(No such process) | 查找进程时未找到该进程 |
EINTR | 4 | 被信号中断(Interrupted system call) | 系统调用被信号中断 |
ENFILE | 23 | 系统文件表溢出(File table overflow) | 系统的文件描述符表已满 |
ENOTTY | 25 | 非终端设备(Not a typewriter) | 用于 I/O 操作的设备不是终端设备 |
EIO | 5 | 输入/输出错误(Input/output error) | 文件或设备发生 I/O 错误 |
3. 如何使用 errno
- 获取错误码:
- 当一个函数调用失败时,你可以通过
errno
来查看具体的错误码。 - 例如,使用
open()
打开文件失败后,errno
将会被设置为一个相应的错误码。
- 当一个函数调用失败时,你可以通过
- 错误码的描述:
- 你可以使用
perror()
或strerror()
来打印或获取errno
错误码的字符串描述。
- 你可以使用
3.1 使用 perror()
打印错误信息
perror()
函数打印出与 errno
相关的错误信息。
#include <stdio.h>
#include <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 <stdio.h>
#include <errno.h>
#include <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 <stdio.h>
#include <errno.h>
#include <string.h>
#include <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 编程中的基础之一。
发表回复