目录

1.eventfd

1.1.核心接口

2.struct stat

2.1 核心字段说明

2.2 st_mode 详解

文件类型判断宏

权限判断宏

2.3 stat 、lstat、fstat函数

三者对比


1.eventfd

  • eventfd 是 Linux 提供的一种轻量级事件通知机制,本质上是一个内核维护的 64 位无符号整数计数器,通过文件描述符来操作
  • 它的核心用途是在线程间或进程间实现信号传递,典型场景是 epoll 事件驱动架构。相比于管道(pipe),它更轻量,无需管理缓冲区,开销更低

1.1.核心接口

  • eventfd() 创建接口
项目 详细说明
函数原型 int eventfd(unsigned int initval, int flags);
所属头文件 <sys/eventfd.h>
作用 创建一个 eventfd 对象,返回一个指向它的文件描述符
参数 initval 计数器的初始值(uint64_t 类型,范围 0 ~ 0xfffffffffffffffe
参数 flags 行为控制标志,按位或组合(详见下方 flags 表)
成功返回值 新的文件描述符(非负整数)
失败返回值 -1,并设置 errno
可能 errno EINVALflags 无效
EMFILE:进程 fd 数达上限
ENFILE:系统 fd 数达上限
ENOMEM:内核内存不足
  • eventfd() flags 标志详解表
标志 作用
0 0 默认模式:读写均可能阻塞,read() 读后清零
EFD_CLOEXEC 02000000 (八进制) exec() 时自动关闭该 fd,防止子进程继承
EFD_NONBLOCK 04000 (八进制) 非阻塞模式:计数器为 0 时 read() 返回 EAGAIN;即将溢出时 write() 返回 EAGAIN
EFD_SEMAPHORE 1 信号量模式:read() 每次减 1 并返回 1,支持多消费者场景
组合 场景
eventfd(0, 0) 线程间同步,阻塞等待事件
eventfd(0, EFD_NONBLOCK) 在轮询循环中使用,不阻塞线程
eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK) 与 epoll 结合,安全且高效
eventfd(0, EFD_SEMAPHORE | EFD_NONBLOCK) 多个消费者竞争同一个事件源,非阻塞
  • write() 写入接口
项目 详细说明
函数原型 ssize_t write(int fd, const void *buf, size_t count);
所属头文件 <unistd.h>
对 eventfd 的作用 将 buf 中的 8 字节无符号整数值加到内核计数器上
参数 fd eventfd 的文件描述符
参数 buf 指向一个 uint64_t 值的指针(必须是 8 字节)
参数 count 写入字节数,必须为 8
写入规则 1. 写入值被加到计数器
2. 如果结果超过 0xfffffffffffffffe,调用阻塞(除非设了 EFD_NONBLOCK
3. 写入值为 0 是合法的,但不改变计数器,用于唤醒阻塞的 read()
成功返回值 8(永远完整写入,不存在部分写入)
失败返回值 -1,并设置 errno
可能 errno EAGAIN:非阻塞模式下,写入会导致计数器溢出
EINVALcount 不等于 8 或 buf 值非法
EBADFfd 无效
EINTR:被信号中断
  • read() 读取接口
项目 详细说明
函数原型 ssize_t read(int fd, void *buf, size_t count);
所属头文件 <unistd.h>
对 eventfd 的作用 读取计数器的值,并根据模式清零或减 1
参数 fd eventfd 的文件描述符
参数 buf 指向一个 uint64_t 变量的缓冲区(至少 8 字节)
参数 count 缓冲区大小,必须 ≥ 8
默认模式读取规则 1. 计数器 > 0:返回当前计数,原子清零
2. 计数器 = 0:阻塞,直到有 write() 写入值
3. 非阻塞:返回 EAGAIN
EFD_SEMAPHORE 模式 1. 计数器 > 0:返回固定值 1原子减 1
2. 计数器 = 0:阻塞(非阻塞返回 EAGAIN
3. 相当于每次消耗一个"事件资源"
成功返回值 8(读取到的 8 字节值填入 buf
失败返回值 -1,并设置 errno
可能 errno EAGAIN:非阻塞模式下计数器为零
EINVALcount < 8
EBADFfd 无效
EINTR:被信号中断
  • close() 关闭接口
项目 详细说明
函数原型 int close(int fd);
所属头文件 <unistd.h>
作用 释放 eventfd 对象及其内核资源
参数 fd eventfd 的文件描述符
成功返回值 0
失败返回值 -1,并设置 errno
可能 errno EBADFfd 无效
注意事项 如果多个进程/线程共享同一个 fd(如通过 fork 或 fd 传递),只有在所有引用该对象的 fd 都关闭后,内核计数器才真正释放

2.struct stat

struct stat 是 POSIX 标准中用于存储文件元信息的结构体,定义在 <sys/stat.h>

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;       // 最后访问时间(access)
    time_t    st_mtime;       // 最后修改时间(modify)
    time_t    st_ctime;       // 最后状态改变时间(change)
};

2.1 核心字段说明

字段 类型 含义 使用场景
st_mode mode_t 文件类型 + 权限 最常用,判断文件类型和权限
st_size off_t 文件大小 获取文件大小,分配缓冲区
st_mtime time_t 最后修改时间 HTTP 的 Last-Modified 头、缓存判断
st_ino ino_t inode 号 判断两个路径是否指向同一文件
st_nlink nlink_t 硬链接数 判断文件是否有其他名字(为 0 时文件真正删除)
st_uid/st_gid uid_t/gid_t 所有者/组 权限检查

2.2 st_mode 详解

st_mode 是一个位掩码,包含两部分信息:文件类型(高 4 位)访问权限(低 12 位)

文件类型判断宏

含义 示例
S_ISREG(m) 普通文件 .txt.html, 可执行文件
S_ISDIR(m) 目录 /home/tmp
S_ISLNK(m) 符号链接 软链接文件
S_ISCHR(m) 字符设备 /dev/tty/dev/null
S_ISBLK(m) 块设备 /dev/sda/dev/sdb
S_ISFIFO(m) 命名管道 FIFO 文件
S_ISSOCK(m) 套接字 socket 文件

权限判断宏

st.st_mode & S_XXX

含义 八进制值
S_IRUSR 所有者读 0400
S_IWUSR 所有者写 0200
S_IXUSR 所有者执行 0100
S_IRGRP 组读 0040
S_IWGRP 组写 0020
S_IXGRP 组执行 0010
S_IROTH 其他人读 0004
S_IWOTH 其他人写 0002
S_IXOTH 其他人执行 0001

2.3 stat 、lstat、fstat函数

#include <sys/stat.h>

int stat(const char *pathname, struct stat *statbuf);
参数 类型 方向 说明
pathname const char * 输入 文件路径(绝对或相对,支持符号链接跟随)
statbuf struct stat * 输出 用于存储文件元信息的结构体指针
返回值 含义 后续操作
0 成功,statbuf 已填充 读取 statbuf 中各字段
-1 失败 检查 errno 获取原因
errno 宏常量 含义
2 ENOENT 文件不存在
13 EACCES 路径中某个目录无搜索权限
20 ENOTDIR 路径中某个组件不是目录
36 ENAMETOOLONG 路径名太长
40 ELOOP 符号链接循环引用
14 EFAULT pathname 或 statbuf 指针无效
12 ENOMEM 内核内存不足
116 ESTALE NFS 文件句柄过期
#include <sys/stat.h>

int lstat(const char *pathname, struct stat *statbuf);
项目 说明
参数 同 statpathname(输入路径)、statbuf(输出信息)
返回值 同 stat:成功返回 0,失败返回 -1 并设置 errno
errno 同 statENOENTEACCESENOTDIRELOOP 等
核心区别 若 pathname 是符号链接,返回符号链接自身的信息,而非目标文件
#include <sys/stat.h>

int fstat(int fd, struct stat *statbuf);
项目 说明
参数 fd:已打开的文件描述符(输入);statbuf:输出信息
返回值 成功返回 0,失败返回 -1 并设置 errno
errno EBADF(9):fd 无效;EFAULT(14):statbuf 指针无效;ENOMEM(12):内存不足
核心区别 通过文件描述符获取信息,无需文件名,适用于已打开的文件

三者对比

stat lstat fstat
输入 路径字符串 路径字符串 文件描述符
符号链接 跟随,返回目标信息 不跟随,返回链接自身 跟随(文件已打开)
典型场景 查询任意文件信息 判断文件是否为符号链接 已 open() 后查询
头文件 <sys/stat.h> <sys/stat.h> <sys/stat.h>

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐