Ubuntu上如何获取分区的可用空间

最近工作需要获取指定磁盘分区的可用空间,在这里记录一下。


网上找的资料一般用的是statvfs获取的,不过这种方案有缺陷,这里先简单介绍一下。

1. 使用statvfs获取

函数原型和入参介绍如下:

cpp 复制代码
int statvfs(const char *path, struct statvfs *buf);
// path:文件系统上的目录,磁盘目录不行,需要传对应磁盘的挂载点
// buf:引用传递的入参,包含查询的结果

statvfs结构体介绍如下:

cpp 复制代码
struct statvfs {
    unsigned long f_bsize;       // 用于执行I/O操作的首选块大小
    unsigned long f_frsize;      // 实际用于计算文件系统容量的块大小
    fsblkcnt_t   f_blocks;      // 文件系统中的总块数
    fsblkcnt_t   f_bfree;       // 空闲块的总数(包括保留给超级用户的块)
    fsblkcnt_t   f_bavail;      // 非超级用户可用的空闲块
    fsfilcnt_t   f_files;       // 文件系统能够创建的最大文件节点(inode)数
    fsfilcnt_t   f_ffree;       // 当前空闲的文件节点数(包括给超级用户的)
    fsfilcnt_t   f_favail;      // 非超级用户可用的自由节点
    unsigned long f_flag;       // 文件系统的挂载标志
    unsigned long f_namemax;    // 最大文件名长度
    // ... 其他成员
};

因此:

空闲空间大小 = f_frsize(块大小)× f_bavail(空闲块数)

代码如下:

cpp 复制代码
float get_partition_available_space(const char* partition) {
    // 1. 首先获取分区的挂载点
    char* mount_point = get_mount_point(partition);
    if (!mount_point) {
        printf("Partition %s is not mounted\n", partition);
        return -1;
    }

    // 2. 使用挂载点获取空间信息
    struct statvfs vfs;
    float available_space = -1;
    
    if (statvfs(mount_point, &vfs) == 0) {
        unsigned long long available = vfs.f_bavail * vfs.f_frsize;
        available_space = available / (1024.0 * 1024.0); // 转换为 MiB
    }

    free(mount_point);
    return available_space;
}

这个办法有一个缺点,就是只能获取挂载的磁盘分区,不挂载的无法获取。

2. 获取未挂载的磁盘可用容量

目前尝试过df等指令,以及libparted库,都无法获取。

临时的解决方案是把未挂载的磁盘挂起来,查看可用容量,查完之后再卸载。

代码如下:

cpp 复制代码
float get_unmounted_partition_space(const char* partition) {
    // 创建临时挂载点
    const char* temp_mount = "/tmp/temp_mount";
    if (mkdir(temp_mount, 0755) != 0 && errno != EEXIST) {
        perror("mkdir");
        return -1;
    }
    
    // 临时挂载
    char cmd[256];
    snprintf(cmd, sizeof(cmd), "mount %s %s", partition, temp_mount);
    if (system(cmd) != 0) {
        rmdir(temp_mount);
        return -1;
    }
    
    // 获取空间信息
    struct statvfs vfs;
    float available_space = -1;
    
    if (statvfs(temp_mount, &vfs) == 0) {
        unsigned long long available = vfs.f_bavail * vfs.f_frsize;
        available_space = available / (1024.0 * 1024.0); // 转换为 MiB
    }
    
    // 清理
    snprintf(cmd, sizeof(cmd), "umount %s", temp_mount);
    system(cmd);
    rmdir(temp_mount);
    
    return available_space;
}

这份代码执行需要root权限,因为涉及到挂载和卸载。

相关推荐
码出钞能力4 小时前
更换libc.so导致linux变砖,通过LD_PRELOAD挽救
linux·服务器
小马学嵌入式~4 小时前
嵌入式 SQLite 数据库开发笔记
linux·c语言·数据库·笔记·sql·学习·sqlite
小猪咪piggy5 小时前
【JavaEE】(24) Linux 基础使用和程序部署
linux·运维·服务器
Haven-5 小时前
Linux常见命令
linux·基本指令
IT 小阿姨(数据库)5 小时前
PgSQL中pg_stat_user_tables 和 pg_stat_user_objects参数详解
linux·运维·数据库·sql·postgresql·oracle
❀͜͡傀儡师5 小时前
Docker部署搜索引擎SearXNG
运维·docker·容器·searxng
MChine慕青5 小时前
顺序表与单链表:核心原理与实战应用
linux·c语言·开发语言·数据结构·c++·算法·链表
虎头金猫5 小时前
如何在Linux上使用Docker在本地部署开源PDF工具Stirling PDF:StirlingPDF+cpolar让专业操作像在线文档一样简单
linux·运维·ubuntu·docker·pdf·开源·centos
荣光波比6 小时前
Nginx 实战系列(七)—— Nginx一键安装脚本详解
运维·nginx·自动化·云计算
努力学习的小廉6 小时前
深入了解linux系统—— 线程同步
linux·服务器·数据库·算法