嵌入式Linux QT开发之如何实现获取磁盘空间大小的应用逻辑

Posted Engineer-Bruce_Yang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了嵌入式Linux QT开发之如何实现获取磁盘空间大小的应用逻辑相关的知识,希望对你有一定的参考价值。

点击上方“嵌入式应用研究院”,选择“置顶/星标公众号

干货福利,第一时间送达!

来源 | 嵌入式应用研究院

整理&排版 | 嵌入式应用研究院

在Window系统上,打开我的电脑,我们就能够看见系统的每个磁盘的可用空间以及总空间,如下所示:

在嵌入式Linux与QT界面结合的产品开发中,我们在做产品的文件管理模块通常来说也需要做这样一个功能。那么如何来实现呢?

方法一:(参考QT大神-飞扬青云的磁盘容量空间控件实现)

利用Linux系统天生就已经提供的df命令来获取,例如我们可以带上-h参数,这样就可以获得以人类可读的格式显示输出,如下所示:

基于韦东山imx6ull开发板文件系统

执行df -h以后,我们能发现一定的规律,即是输出是以行为单位输出的,并且,每一行通过空格来进行分隔标识。因此,我们能够借助QT提供的字符串分割方法以及一些简单的逻辑来实现获取其中一行的内容。

QT大佬-飞扬青云在他的磁盘容量控件里就介绍了这种方法,开源仓库:

https://gitee.com/feiyangqingyun/QWidgetDemo?_from=gitee_search

测试解析一行的函数如下:

#include "mainwindow.h"
#include "ui_mainwindow.h"

void MainWindow::Get_Disk(const QString &result, const QString &name)

    uint8_t index = 0;
    uint8_t percent = 0;
    QString dev, use, free, all;
    QStringList list = result.split(" ");
    for (int i = 0; i < list.count(); i++)
    
        QString s = list.at(i).trimmed();
        if (s == "")
            continue;
        index++;
        if (index == 1)
            dev = s;
        else if (index == 2)
            all = s;
        else if (index == 3)
            use = s;
        else if (index == 4)
            free = s;
        else if (index == 5) 
            percent = s.left(s.length() - 1).toInt();
            break;
        
    
    if (name.length() > 0)
        dev = name;
    qDebug() << "设备名称:" << dev ;
    qDebug() << "总空间:" << all ;
    qDebug() << "已经使用了多少空间:" << use ;
    qDebug() << "剩余多少空间:" << free ;
    qDebug() << "使用的空间的百分比:" << percent << "%";


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)

    ui->setupUi(this);
    QString str = "/dev/sda4                14.4G      7.4G      7.0G  52% /mnt";
    Get_Disk(str,"/dev/sda4");


MainWindow::~MainWindow()

    delete ui;

运行结果:

这种方法即不需要去了解实现原理,简单来说就是一个字符串解析的过程。结合QT的QProcess函数或者Linux C提供的popen函数来调用df -h命令来获取磁盘容量信息,然后通过这种方法循环读取每一行,结合自己产品的业务逻辑去获取对应的内容即可。

方法二、直接把df命令的代码搬过来与QT进行结合

基于statfs函数实现,这种方法其实就是df命令的实现原理,statfs可以用于查询文件系统相关的信息。df命令实现如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/statfs.h>
 
static int ok = EXIT_SUCCESS;
//根据挂载的文件的大小来计算
static void printsize(long double n)

    char unit = 'K';
    n /= 1024;
    if (n > 1024) 
        n /= 1024;
        unit = 'M';
    
    if (n > 1024) 
        n /= 1024;
        unit = 'G';
    
    printf("%-4.1Lf%c", n, unit);

 
static void df(char *s, int always) 
    struct statfs st;
    //statfs函数可用来查询文件系统相关的信息。
    if (statfs(s, &st) < 0) 
        fprintf(stderr, "%s: %s\\n", s, strerror(errno));
        ok = EXIT_FAILURE;
     else 
        if (st.f_blocks == 0 && !always)
            return;        
        printf("%-20s  ", s);
        printsize((long double)st.f_blocks * (long double)st.f_bsize);
        printf("  ");
        printsize((long double)(st.f_blocks - (long double)st.f_bfree) * st.f_bsize);
        printf("  ");
        printsize((long double)st.f_bfree * (long double)st.f_bsize);
        printf("   %d\\n", (int) st.f_bsize);
    

 
int df_main(int argc, char *argv[]) 
    printf("Filesystem             Size   Used   Free   Blksize\\n");
    if (argc == 1) 
        char s[2000];
        //挂载的文件都在/proc/mounts下显示
        FILE *f = fopen("/proc/mounts", "r");
 
        while (fgets(s, 2000, f)) 
            char *c, *e = s;
 
            for (c = s; *c; c++) 
                if (*c == ' ') 
                    e = c + 1;
                    break;
                
            
 
            for (c = e; *c; c++) 
                if (*c == ' ') 
                    *c = '\\0';
                    break;
                
            
 
            df(e, 0);
        
 
        fclose(f);
     else 
        int i;
 
        for (i = 1; i < argc; i++) 
            df(argv[i], 1);
        
    
 
    exit(ok);

作为多年Ctrl-C and Ctrl-V职场老司机,想要把它融合到自己代码业务逻辑,那岂不是一件相当容易的事情?经过简单的魔改,需求就搞定了:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <sys/vfs.h>
#include <sys/stat.h>
#include <dirent.h>

/*判断目录是否存在*/
bool dirIsExist(const char *file_path)

    DIR * mydir = NULL;
    if ((mydir = opendir(file_path)) == NULL)
        return false;
    closedir(mydir);
    return true;


/*获取磁盘的可用空间以及总空间*/
int getDiskInfo(const char *path,double * available,double *total)

    uint64_t blocksize;
    uint64_t totalsize;
    uint64_t availablesize;
    struct statfs diskInfo;
    if(dirIsExist(path))
        statfs(path, &diskInfo);
    else
        return -1 ;
    // 每个block里包含的字节数
    blocksize = diskInfo.f_bsize;
    // 总的字节数,f_blocks为block的数目
    totalsize = blocksize * diskInfo.f_blocks;
    // 可用空间大小
    availablesize = diskInfo.f_bavail * blocksize;
    *available = availablesize ;
    *total = totalsize ;
    return 0 ;


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)

    ui->setupUi(this);
    char av_unit = 'K';
    char total_unit = 'K';
    double availablesize = 0.00 ;
    double totalsize = 0.00 ;
    getDiskInfo("/mnt",&availablesize,&totalsize); 
    availablesize /= 1024 ;
    if(availablesize > 1024)
        availablesize /= 1024 ;
        av_unit = 'M';
    
    if(availablesize > 1024)
        availablesize /= 1024 ;
        av_unit = 'G';
    
    totalsize /= 1024 ;
    if(totalsize > 1024)
        totalsize /= 1024 ;
        total_unit = 'M';
    
    if(totalsize > 1024)
        totalsize /= 1024 ;
        total_unit = 'G';
    
    qDebug() <<"availablesize:" <<  QString("%1%2").arg(QString::number(availablesize, 'f', 1)).arg(av_unit) ;
    qDebug() <<"totalsize:" << QString("%1%2").arg(QString::number(totalsize, 'f', 1)).arg(total_unit) ;

在Linux下进行交叉编译后,在开发板将这个程序跑起来,运行如下:

大佬的方法简单粗暴,但个人推荐使用方法二来实现逻辑,可操作空间更大一些。下一期,我们结合iwlist以及wpa_cli来实现WIFI扫描、连接、状态查询等需求。

往期精彩

嵌入式Linux Qt应用开发WIFI搜索、显示与连接思路

嵌入式linux检测U盘拔插与QT界面开发相结合的实现思路

嵌入式QT应用开发之二维码生成

Qt串口通信接收数据不完整,怎么解决?

QT中的QMap也可以实现表驱动

觉得本次分享的文章对您有帮助,随手点[在看]并转发分享,也是对我的支持。

以上是关于嵌入式Linux QT开发之如何实现获取磁盘空间大小的应用逻辑的主要内容,如果未能解决你的问题,请参考以下文章

嵌入式Linux QT开发之如何实现获取磁盘空间大小的应用逻辑

手把手之如何在嵌入式Linux上运行QT应用程序(以百问网imx6ull开发板为例)

Linux——Linux驱动之设备树常用的of操作函数获取节点信息实践(设备树中如何添加自定义节点,如何获取节点的信息?)

Linux——Linux驱动之设备树常用的of操作函数获取节点信息实践(设备树中如何添加自定义节点,如何获取节点的信息?)

嵌入式软件开发之Linux 磁盘管理

串口屏开发之滑动选择控件的使用总结——如何通过滑动屏幕实现参数选择设置和状态显示