linux 下应使用 statvfs 获取 f_bsize 作为文件系统推荐 i/o 对齐大小,而非硬编码 4096;o_direct 场景必须用 posix_memalign 分配内存,并确保缓冲区地址、读写长度和文件偏移均按 f_bsize 对齐。

Linux 下用 statfs 或 statvfs 获取物理块大小
文件系统报告的“块大小”不等于磁盘物理扇区或 RAID 条带大小,但它是内核对底层 I/O 对齐建议最直接的来源。优先用 statvfs(POSIX 标准),它返回的 f_bsize 是推荐的文件系统 I/O 缓冲区大小,不是硬编码的 4096。
常见错误是误读 f_frsize(基本分配单元)或 f_blocks(总块数)——它们和 I/O 对齐无关;真正该用的是 f_bsize。
-
statvfs返回值稳定,跨 ext4/xfs/btrfs 均有效,但不反映 NVMe 的真实扇区粒度(需额外查/sys/block/*/queue/logical_block_size) - 若程序需严格对齐到设备物理扇区(如 mmap + O_DIRECT 场景),
f_bsize可能偏大(例如 XFS 默认 65536),此时应 fallback 到ioctl(fd, BLKPBSZGET, &phys) - 示例:获取当前路径所在文件系统的推荐块大小
#include <sys>
struct statvfs sv;
if (statvfs(".", &sv) == 0) {
size_t recommended_io_size = sv.f_bsize; // 这才是你该对齐的尺寸
}</sys>
C++ 中对齐内存分配必须用 posix_memalign 而非 new
用 new 或 malloc 分配的内存几乎必然不对齐到 4K/64K,导致 O_DIRECT 读写直接失败并报错 Invalid argument。
根本原因:glibc 的 malloc 仅保证 16 字节对齐,而 O_DIRECT 要求地址、缓冲区长度、文件偏移三者均按 f_bsize 对齐。
- 必须用
posix_memalign(&buf, alignment, size),其中alignment至少为f_bsize,且必须是 2 的幂 - 不能用
aligned_alloc(C++17),它在某些 libc 版本中对齐行为不一致;std::pmr::monotonic_buffer_resource也不可控 - 释放时用
free(buf),不是delete[]—— 这点极易出错
O_DIRECT 读写必须同时满足三个对齐条件
只对齐缓冲区地址是不够的,O_DIRECT 会检查三处:用户缓冲区地址、读写长度、文件起始偏移。任一不满足就返回 -1 并设 errno = EINVAL。
- 文件打开必须带
O_DIRECT标志(open(path, O_RDONLY | O_DIRECT)),且不能与O_APPEND共存 - 每次
read()/write()的count必须是f_bsize的整数倍(不能是 4096 的倍数,而是f_bsize的倍数) - 文件偏移(
offset参数或当前文件位置)也必须是f_bsize的整数倍 - 绕过 page cache 后,小 IO 性能反而更差——
O_DIRECT适合 ≥ 128KB 的连续读写,别用它读 1KB 配置文件
Windows 上没有等价的 f_bsize,得查卷参数和设备属性
Windows 没有 POSIX 的 statvfs,也不能用 O_DIRECT。替代方案是 CreateFile 开启 FILE_FLAG_NO_BUFFERING,但它强制要求所有操作满足三重对齐,且对齐基准是卷的“扇区大小”,而非文件系统块大小。
- 用
GetDiskFreeSpace获取lpBytesPerSector(逻辑扇区大小),这是最低对齐单位;lpBytesPerCluster是簇大小,可作缓冲区参考,但非强制 -
FILE_FLAG_NO_BUFFERING下,缓冲区地址、长度、文件偏移都必须是lpBytesPerSector的整数倍(通常为 512 或 4096) - 注意:NTFS 压缩卷、ReFS、BitLocker 加密卷可能不支持
FILE_FLAG_NO_BUFFERING,调用WriteFile会失败并返回ERROR_INVALID_PARAMETER
alignas(4096) 就完事的——它只管变量声明时的栈/全局对齐,不管堆上运行时分配的地址。真正影响 O_DIRECT 或 FILE_FLAG_NO_BUFFERING 的,是每次 read/write 调用前那块内存的实际地址值。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!









