当仅提供磁盘块设备名称和分区号时,我需要找到(在 C 或 C++ 中)文件系统 (Linux) 上的已用空间。
对于大多数文件系统,我可以:
- 制作一个开发者名称
/dev/<block><part>
或/dev/<block>p</part>
任何存在的名称 - 搜索
/proc/mounts
该设备并获取挂载点 statvfs()
在该安装点上使用
虽然这看起来有点啰嗦,但已经足够了。但是,有一个警告:
我的根目录是从/dev/root
实际的块设备名称安装的。除非没有/dev/root
- 该节点不存在。现在,我可以/dev/<whatever>
通过使用stat("/"...)
获取设备 ID 并将其拆分为主要/次要数字,然后查找/sys/dev/block/<maj>:<min>/uevent
该DEVNAME=
条目,将其取消引用到块名称。
保持它是一个完全通用的函数,然后该方法将扩展为:
- 设计正确的设备名称
/dev/<block><part>
或/dev/<block>p<part>
,以存在的为准 - 对于 中的每个条目
/proc/mounts
:- 提取挂载点
- 获取主要/次要对
stat()
- 查找父设备名称
/sys/dev/block/<maj>:0/uevent
- 将该设备名称与块设备名称进行比较,并将次设备名称与分区号进行比较
- 如果匹配则获取已用空间
statvfs()
现在这样说实在是太啰嗦了,我不喜欢这样。是的,它应该有效,但远非理想。
那么,是否有更简单的界面来执行此操作?直接与内核中的挂载表交互的某种方式?对于每个已安装的文件系统,是否有某种方式获取结构中的块设备(主要/次要)以及它安装的路径(可能还有其他信息)?
我知道有mount()
和umount()
函数,但是有"tell me what is mounted"()
函数吗?
答案1
我的第一条评论是,您所说的所有内容只有在您感兴趣的设备上的文件系统当前已安装时才有效。但我想你知道这一点并接受这个限制。
你提出的方法看起来很彻底,我认为它可以捕获所有情况。
关于查找 ip /sys/dev/block
:
- 你并没有像你所说的那样寻找
<maj>:0
。您正在寻找<major>:<minor>
。 - 为找不到它的情况做好准备。某些文件系统(如
/proc
、 和 typetmpfs
)nfs
没有关联的设备。您需要忽略这些,因为它们不可能与您感兴趣的块设备匹配。
查找设备名称时,不要扫描/sys/dev/block/<major>:<minor>/uevent
。相反,areadlink()
本身/sys/dev/block/<major>:<minor>
并获取结果的基本名称。您应该得到相同的结果,但它更干净、更高效。
如果要查找多个设备,则应该只扫描/proc/mounts
并执行整个/sys
查找一次,并缓存结果以供下一次设备查找使用。
没有show_me_mounts()
系统调用。在 Linux 中,这就是/proc/mounts
目的。但正如您所注意到的,它并不完美。一般来说/dev/root
,尽管使用完全现代的基于 initramfs 的引导,您不会看到虚拟/不存在的问题。
编辑根据您的要求找到每个分区对应的整个磁盘。
为了获取给定“内部”块设备(=分区)的“外部”块设备(=整个磁盘),您不能只需将次设备号更改为 0 即可。
如果您发现主要 8 和次要 1,正确的方法是查看此文件:
/sys/dev/block/8:1/../dev
这将产生8:0
,但不会错误地假设次设备 ID 始终可以切换为 0。
如果您ENOENT
尝试打开它,那是因为相关块设备的类型没有内部/外部层次结构,或者次要设备 ID 与内部设备不对应。