hook用到的函数/c中操作用到的函数 2025-06-30

将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 超出磁盘配额

注意事项

  1. 不同系统可能支持不同的errno值集合,上表主要基于POSIX标准
  2. 某些系统可能有额外的errno值(如网络相关的错误)
  3. EAGAIN和EWOULDBLOCK通常具有相同的值(11)
  4. 可以使用strerror(errno)将错误代码转换为可读字符串
  5. 在程序开始时,errno的值应为0
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容