将libc库中的接口重新找回来的函数dlsym()
#include <dlfcn.h>
/*
* 第一个参数固定为 RTLD_NEXT,第二个参数为符号的名称
*/
void *dlsym(void *handle, const char *symbol);
dlsym - 从一个动态链接库或者可执行文件中获取到符号地址。成功返回跟name关联的地址
RTLD_NEXT 返回第一个匹配到的 "name" 的函数地址
取出原函数,赋值给新函数
获取文件状态信息的函数fstat
int fstat(int fd, struct stat *buf);
第一个参数是文件描述符,第二个参数是返回的文件描述符的状态
在<sys/stat.h>和<unistd.h>头文件中声明
成功时返回0,失败时返回-1,并设置errno
struct stat结构体
struct stat {
dev_t st_dev; /* 设备ID */
ino_t st_ino; /* inode号 */
mode_t st_mode; /* 文件类型和权限 */
nlink_t st_nlink; /* 硬链接数 */
uid_t st_uid; /* 所有者用户ID */
gid_t st_gid; /* 所有者组ID */
dev_t st_rdev; /* 设备ID(如果是特殊文件) */
off_t st_size; /* 文件大小(字节) */
blksize_t st_blksize; /* 文件系统I/O块大小 */
blkcnt_t st_blocks; /* 分配的512B块数量 */
time_t st_atime; /* 最后访问时间 */
time_t st_mtime; /* 最后修改时间 */
time_t st_ctime; /* 最后状态变更时间 */
};
用于检测文件描述符是否指向一个socket文件
#include <sys/stat.h>
#include <unistd.h>
struct stat fd_stat;
fstat(fd, &fd_stat); // 获取文件描述符的状态信息
if (S_ISSOCK(fd_stat.st_mode)) {
printf("文件描述符 %d 是一个 socket\n", fd);
}
需要包含 <sys/stat.h> 和 <unistd.h>(用于 fstat 调用)
其他类似宏
S_ISREG():普通文件
S_ISDIR():目录
S_ISCHR():字符设备
S_ISBLK():块设备
S_ISFIFO():管道/FIFO
S_ISLNK():符号链接
设置套接字的接收超时和发送超时
SO_RCVTIMEO(读超时也就是接收超时), SO_SNDTIMEO(写超时也就是发送超时)
#include <sys/socket.h>
#include <sys/time.h>
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
// 设置接收超时为3秒
struct timeval tv_rcv;
tv_rcv.tv_sec = 3; // 秒
tv_rcv.tv_usec = 0; // 微秒
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv_rcv, sizeof(tv_rcv));
// 设置发送超时为2秒
struct timeval tv_snd;
tv_snd.tv_sec = 2;
tv_snd.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &tv_snd, sizeof(tv_snd));
程序退出状态码
EXIT_FAILURE与EXIT_SUCCESS
特性 | EXIT_FAILURE | errno |
---|---|---|
所属头文件 | <stdlib.h> |
<errno.h> |
用途 | 程序退出状态码 | 记录函数调用失败的具体原因 |
值类型 | 固定宏(如 1) | 动态变量(随错误类型变化) |
关联函数 |
exit() , return
|
perror() , strerror()
|
errno
errno是C语言标准库中用于报告错误的一个重要机制。它是一个全局变量(实际上通常实现为宏),用于存储最近发生的错误代码。
基本概念
定义:errno在<errno.h>头文件中声明,是一个int类型的变量。
用途:当库函数执行失败时,通常会设置errno来指示具体的错误原因。
线程安全:在现代实现中,errno通常是线程安全的(每个线程有自己的errno副本)。
strerror(errno)将errno转换为string好显示
常见errno值
C语言常见errno值完整表格
以下是C语言中常见的errno值及其对应的宏定义和描述:
错误代码 | 宏定义 | 描述 |
---|---|---|
1 | EPERM | 操作不允许(通常由于权限问题) |
2 | ENOENT | 文件或目录不存在 |
3 | ESRCH | 进程或线程不存在 |
4 | EINTR | 系统调用被中断 |
5 | EIO | 输入/输出错误 |
6 | ENXIO | 设备或地址不存在 |
7 | E2BIG | 参数列表过长 |
8 | ENOEXEC | 可执行文件格式错误 |
9 | EBADF | 文件描述符无效 |
10 | ECHILD | 无子进程 |
11 | EAGAIN/EWOULDBLOCK | 资源暂时不可用,请重试(非阻塞操作) |
12 | ENOMEM | 内存不足 |
13 | EACCES | 权限不足 |
14 | EFAULT | 错误的地址 |
15 | ENOTBLK | 需要块设备 |
16 | EBUSY | 设备或资源忙 |
17 | EEXIST | 文件已存在 |
18 | EXDEV | 跨设备链接 |
19 | ENODEV | 设备不存在 |
20 | ENOTDIR | 不是目录 |
21 | EISDIR | 是目录 |
22 | EINVAL | 无效参数 |
23 | ENFILE | 系统打开文件数达到上限 |
24 | EMFILE | 进程打开文件数达到上限 |
25 | ENOTTY | 不适当的I/O控制操作 |
26 | ETXTBSY | 文本文件忙 |
27 | EFBIG | 文件过大 |
28 | ENOSPC | 设备无剩余空间 |
29 | ESPIPE | 非法定位(如对管道执行lseek) |
30 | EROFS | 只读文件系统 |
31 | EMLINK | 链接数过多 |
32 | EPIPE | 管道破裂(写入无读端的管道) |
33 | EDOM | 数学参数超出函数定义域 |
34 | ERANGE | 数学结果无法表示 |
35 | EDEADLK | 资源死锁 |
36 | ENAMETOOLONG | 文件名过长 |
37 | ENOLCK | 无可用锁 |
38 | ENOSYS | 功能未实现 |
39 | ENOTEMPTY | 目录非空 |
40 | ELOOP | 符号链接层级过多 |
42 | ENOMSG | 无所需类型的消息 |
43 | EIDRM | 标识符已移除 |
122 | EDQUOT | 超出磁盘配额 |
注意事项
- 不同系统可能支持不同的errno值集合,上表主要基于POSIX标准
- 某些系统可能有额外的errno值(如网络相关的错误)
- EAGAIN和EWOULDBLOCK通常具有相同的值(11)
- 可以使用
strerror(errno)
将错误代码转换为可读字符串 - 在程序开始时,errno的值应为0