statvfs 的 f_bsize 和 f_frsize 是文件系统 i/o 块大小(如 4kib),非物理扇区大小;真实扇区大小需通过 ioctl(blksszget/blkpbszget) 查询块设备,先由文件路径获取 st_dev,再解析 /proc/mounts 匹配主次设备号定位设备路径。

Linux 下用 statvfs 只能拿到块大小,不是扇区大小
很多人误以为 statvfs 的 f_bsize 或 f_frsize 是物理扇区大小,其实它们是文件系统 I/O 块大小(通常 4KiB),和磁盘真实扇区无关。真正的扇区大小需查设备底层,statvfs 根本不提供这个信息。
正确路径是:先通过文件路径获取其挂载点 → 找到对应块设备(如 /dev/sda2)→ 读取设备的逻辑/物理扇区大小。关键函数是 ioctl 配合 BLKPBSZGET 和 BLKSSZGET。
-
BLKSSZGET返回逻辑扇区大小(通常 512 或 4096),是设备报告的最小可寻址单元 -
BLKPBSZGET返回物理扇区大小(可能大于逻辑值,如 4K 物理扇区 + 512e 模拟),影响对齐性能 - 必须以只读方式打开块设备文件(
O_RDONLY),否则ioctl失败并返回EINVAL
如何从普通文件路径反推对应块设备
不能直接对普通文件调 ioctl —— 它不是块设备。得先用 stat 获取文件所在文件系统的设备号(st_dev),再遍历 /proc/self/mountinfo 或调用 findmnt 命令解析,但更轻量的方式是读 /proc/mounts 并匹配 st_dev 的主/次设备号。
实操建议:
- 用
stat("/path/to/file", &sb)得到sb.st_dev(dev_t类型) - 用
major(sb.st_dev)和minor(sb.st_dev)提取主次号 - 扫描
/proc/mounts,找字段中形如"8:2"的设备标识(对应主:次),定位挂载点 - 再根据挂载点查
/sys/class/block/*/device/name或拼接/dev/block/{name},最终得到可 open 的设备路径
ioctl 获取扇区大小的最小可行代码
以下片段假设你已有合法的块设备路径(如 /dev/sda2):
#include <fcntl.h>
#include <unistd.h>
#include <sys>
#include <linux><p>int fd = open("/dev/sda2", O_RDONLY);
if (fd == -1) { /<em> handle error </em>/ }</p>
<p>int logical_sz = 0, physical_sz = 0;
if (ioctl(fd, BLKSSZGET, &logical_sz) == 0 &&
ioctl(fd, BLKPBSZGET, &physical_sz) == 0) {
printf("logical: %d, physical: %d
", logical_sz, physical_sz);
}
close(fd);</p></linux></sys></unistd.h></fcntl.h>
注意:BLKPBSZGET 在较老内核(ioctl(fd, BLKSSZGET, ...);另外,某些 LVM/DM 设备会透传底层值,但 RAID 或 NVMe 可能返回 4096 即使物理是 512 —— 这是驱动层抽象的结果,应用应以该值为准做对齐。
Windows 下没有直接等价接口,得绕道 WMI 或 DeviceIoControl
Windows 不暴露“扇区大小”为简单数值,而是通过存储类 IOCTL。核心是向卷句柄发送 IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,解析返回的 DISK_GEOMETRY_EX 结构体中的 Geometry.BytesPerSector(逻辑)和 Geometry.PhysicalBytesPerSectorForNonAlignedMeans(物理)。
- 必须用
CreateFile打开类似"\\.\C:"的卷符号链接,而非普通路径 - 需要
FILE_SHARE_READ | FILE_SHARE_WRITE权限,否则打开失败 - 返回结构体中
BytesPerSector通常是 512 或 4096;若为 0,说明设备不支持该查询(极少见) - WMI 方式(
Win32_DiskDrive类的SectorsPerTrack等)只能辅助判断,不能直接得出扇区字节数
跨平台程序别硬编码 512 —— SSD、SMR 盘、某些 NVMe 设备已普遍使用 4K 逻辑扇区,错用会导致性能断崖式下跌或写失败。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











