需调用getmntent()遍历/proc/mounts匹配最长前缀挂载项获取设备名和挂载点,再通过ioctl(BLKPBSZGET)或读取/sys/block/*/queue/physical_block_size获取物理扇区大小。

在Linux系统下开发C++程序时,需要精确获取硬盘分区的挂载点路径(如/home)、对应设备名(如/dev/sda2)以及该设备的物理扇区大小(如4096字节),才能正确实现底层IO优化、磁盘缓存对齐或文件系统元数据解析等功能。
获取指定路径所属的挂载点与块设备名
调用getmntent()系列函数遍历/proc/mounts,匹配目标路径的最长前缀挂载项。
第一步:包含必要头文件:#include <mntent.h>、#include <sys/stat.h>、#include <unistd.h>、#include <limits.h>。
第二步:使用realpath()将输入路径标准化为绝对路径,避免因软链接或../导致匹配失败;若传入路径不存在,realpath()返回NULL,需提前检查并报错。
立即学习“C++免费学习笔记(深入)”;
第三步:以setmntent("/proc/mounts", "r")打开挂载表,逐条读取struct mntent*,用strncmp()比较mnt_dir是否为标准化路径的前缀,并确保下一个字符是'/'或字符串结束——否则/boot会错误匹配到/bootloader。
第四步:找到最长匹配项后,记录其mnt_fsname(如/dev/nvme0n1p3)和mnt_dir(如/),调用endmntent()关闭句柄。这一步操作起来很简单,直接循环读取即可,但必须在匹配成功后立即跳出,否则后续更短的挂载点(如/usr)可能覆盖正确结果。
从设备路径解析物理扇区大小
方法一:读取/sys/block/*/queue/logical_block_size与/sys/block/*/queue/physical_block_size
提取设备名(如nvme0n1p3)后,向上追溯到父块设备名(去掉末尾数字和p,【nvme0n1p3 → nvme0n1】);构造路径/sys/block/nvme0n1/queue/physical_block_size,用std::ifstream读取整数值。
方法二:使用ioctl()调用BLKPBSZGET
先用open()以只读方式打开设备文件(如/dev/nvme0n1p3),注意必须加O_RDONLY | O_CLOEXEC标志;然后声明unsigned int phy_bs变量,执行ioctl(fd, BLKPBSZGET, &phy_bs);成功时返回0,phy_bs即为物理扇区大小。若设备不支持该ioctl(如某些LVM逻辑卷),会返回-1并置errno=ENOTTY,此时应降级走方法一。
注意:不要对挂载点路径(如/home)直接open,必须用/dev/xxx设备路径,否则ioctl必然失败。
完整示例:给定路径输出挂载点、设备名、物理扇区大小
编写主函数:接收命令行参数(如./a.out /var/log)→ 调用挂载点查找函数获取device_path和mount_point → 从device_path提取sysfs父名 → 读取physical_block_size → 格式化输出三字段信息(tab分隔)。
编译时需链接-lutil(部分系统需要);运行时程序需有读取/proc/mounts和/sys/block/的权限,普通用户默认可读,无需sudo。
这一步操作起来很简单,直接把文件拖进去就行。


















