Direct IO需满足三重对齐:缓冲区地址、文件偏移量、传输字节数均须按设备逻辑扇区大小(如512或4096)对齐,且文件系统(ext4/XFS/Btrfs)和设备须支持,open时启用O_DIRECT,内存须用posix_memalign分配。

在高性能存储场景中,需要绕过内核页缓存直接与块设备交互,避免 read()/write() 调用触发 page cache 拷贝和脏页回写开销,尤其适用于数据库日志、科学计算批量 I/O 或自研文件系统代理层。
确认文件系统与设备支持 Direct IO
执行 stat -f /path/to/file 查看文件所在文件系统类型;ext4、XFS、Btrfs 在挂载时启用 direct_io 或默认支持(XFS 无需额外选项),而 tmpfs、procfs、nfs 不支持 Direct IO;若目标为裸设备(如 /dev/sdb1),需确保其未被 LVM 或 RAID 层抽象,且当前用户有读写权限。
运行 blockdev --getss /dev/sdb1 获取逻辑扇区大小(通常为 512 或 4096 字节)——【Direct IO 的缓冲区地址和文件偏移量都必须按此值对齐】。
打开文件时启用 O_DIRECT 标志
使用 open() 系统调用,传入 O_DIRECT | O_RDWR(或 O_RDONLY/O_WRONLY)标志位,禁用缓存路径:
立即学习“C++免费学习笔记(深入)”;
int fd = open("/data/bigfile.bin", O_RDWR | O_DIRECT | O_CREAT, 0644);
若返回 -1 且 errno == EINVAL,常见原因包括:文件位于不支持 Direct IO 的文件系统(如 overlayfs)、底层设备不支持(如某些 FUSE 实现)、或文件以 O_APPEND 方式打开(O_APPEND 与 O_DIRECT 互斥)。
分配对齐内存缓冲区
方法一:使用 posix_memalign()
调用 posix_memalign(&buf, alignment, size) 分配页对齐内存,其中 【alignment 必须 ≥ 文件系统逻辑扇区大小,推荐使用 getpagesize() 返回值(通常 4096)】;不能用 malloc() 或 new 分配的内存,因其地址无法保证对齐,会导致 read/write 失败并返回 EINVAL。
方法二:使用 memalign()(部分旧系统)或 aligned_alloc()(C11)
memalign() 行为类似 posix_memalign,但失败时返回 NULL 而非错误码;aligned_alloc() 要求 size 是 alignment 的整数倍,否则行为未定义。
执行 Direct IO 读写操作
第一步:确保每次 read/write 的 offset 参数是逻辑扇区大小的整数倍
第二步:确保传入的缓冲区起始地址由 posix_memalign 分配且满足对齐要求
第三步:确保要传输的字节数是逻辑扇区大小的整数倍(例如 4096、8192、131072)
调用 ssize_t n = read(fd, buf, 65536); —— 若 n > 0,表示成功读取指定字节数;若 n == 0,说明已到文件末尾;若 n == -1 且 errno == EINVAL,立即检查上述三项对齐条件是否全部满足。
这一步操作起来很简单,直接把对齐后的 buf 和 offset 传进去就行,但任何一项不满足都会导致系统调用立即失败。


















