服务器设计细节 之 【eventfd、struct stat、stat接口】

目录

1.eventfd

1.1.核心接口

[2.struct stat](#2.struct stat)

[2.1 核心字段说明](#2.1 核心字段说明)

[2.2 st_mode 详解](#2.2 st_mode 详解)

文件类型判断宏

权限判断宏

[2.3 stat 、lstat、fstat函数](#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)`
`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 不等于 8buf 值非法 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 获取原因
2 ENOENT 文件不存在
13 EACCES 路径中某个目录无搜索权限
20 ENOTDIR 路径中某个组件不是目录
36 ENAMETOOLONG 路径名太长
40 ELOOP 符号链接循环引用
14 EFAULT pathnamestatbuf 指针无效
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> |

相关推荐
资源分享助手1 小时前
三网H5小游戏战车向前冲搭建教程(Win+Linux)
linux·运维·服务器
无限进步_1 小时前
Linux权限模型:从rwx到粘滞位
linux·运维·服务器
似是燕归来1 小时前
WiFi 模块自动联网自带MQTT协议栈和云服务器串口透传免AT开发
服务器·esp32·wifi模块·mqtt协议
Web极客码2 小时前
什么是WHMCS?
服务器·whmcs
SWAGGY..2 小时前
Linux系统编程:(一)基础指令详解
linux·运维·服务器
一池秋_3 小时前
etc/sudo.conf is owned by uid 10258, should be 0解决
linux·运维·服务器
Bert.Cai3 小时前
Linux basename命令详解
linux·运维·服务器
源远流长jerry3 小时前
Linux 本机网络通信机制深度解析:Loopback 设备原理
linux·运维·服务器·网络·tcp/ip·nginx·负载均衡
网络工程小王3 小时前
【LangGraph 子图(Subgraph)详解】学习笔记
java·服务器·数据库·人工智能·langchain