You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux平台使用C++如何正确检测系统块设备?

问题原因

靠文件名前缀匹配/dev下的块设备是非常不可靠的做法:块设备的命名完全由对应内核驱动决定,除了你提到的会漏掉loop、nbd设备之外,常见的mmcblk(EMMC/SD卡)、zram(压缩内存盘)、dm-(LVM、LUKS等Device Mapper设备)、md(软RAID)、sr*(光驱)、ram*(内存盘)等块设备全都会漏,而且以后内核加了新的块设备驱动,你还得不停补前缀,根本维护不过来。

正确实现方法

Linux本身有标准接口判断文件类型,根本不需要看文件名猜是不是块设备:

  • C++17以上直接用标准库std::filesystem的is_block_file()方法就能判断
  • 要兼容老版本C++就用POSIX标准的stat()接口,配合S_ISBLK()宏判断
  • 如果要拿当前系统真正在线的整块磁盘(不含分区),直接遍历内核导出的/sys/block目录最准,这个目录是内核实时生成的,不会有/dev下可能残留的无效设备节点。
参考代码

遍历/dev获取所有块设备(含分区)

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

int main() {
    for (const auto& entry : fs::directory_iterator("/dev/")) {
        // 核心判断:直接识别块设备文件,和文件名没有任何关系
        if (fs::is_block_file(entry.status())) {
            std::cout << "Found block device: " << entry.path() << '\n';
            
            // 要过滤分区只留整盘的话,在这里加判断就行:可以查设备号的分区位,或者去/sys/block下查对应条目是否存在
        }
    }
    return 0;
}

遍历/sys/block仅获取在线整块块设备

这个方案不会返回分区,也不会返回已经拔掉但/dev下还留着节点的无效设备,适合做磁盘枚举的场景:

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

int main() {
    for (const auto& entry : fs::directory_iterator("/sys/block/")) {
        auto dev_name = entry.path().filename().string();
        std::cout << "Found online whole disk: /dev/" << dev_name << '\n';
        
        // 要枚举这个盘的分区也很简单,遍历entry.path()下的子目录,名字是盘名加数字的就是分区,对应/dev下的同名分区设备
    }
    return 0;
}

兼容无C++17环境的判断函数

如果编译环境不支持C++17,用POSIX接口实现块设备判断即可:

#include <sys/stat.h>
#include <cerrno>

bool is_block_device(const char* path) {
    struct stat st{};
    if (stat(path, &st) != 0) {
        // 可以根据errno拿错误原因,比如权限不足、文件不存在
        return false;
    }
    return S_ISBLK(st.st_mode);
}
注意事项
  • 永远不要硬编码设备名前缀,内核里的块设备驱动有几十上百种,你枚举不完的
  • 要拿块设备的容量、扇区大小、是否可移动等属性,直接读/sys/block/<设备名>/目录下的对应文件就行,不用调用lsblk、fdisk之类的外部命令,解析效率高还没有兼容性问题

内容的提问来源于stack exchange,提问作者hanshenrik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 02:27:19