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

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

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

640.png

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

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

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

640.png

执行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;
}

运行结果:

640.png

这种方法即不需要去了解实现原理,简单来说就是一个字符串解析的过程。结合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下进行交叉编译后,在开发板将这个程序跑起来,运行如下:

640.png

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

往期精彩

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


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


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


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


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

目录
相关文章
|
6天前
|
缓存 Linux 开发者
Linux内核中的并发控制机制:深入理解与应用####
【10月更文挑战第21天】 本文旨在为读者提供一个全面的指南,探讨Linux操作系统中用于实现多线程和进程间同步的关键技术——并发控制机制。通过剖析互斥锁、自旋锁、读写锁等核心概念及其在实际场景中的应用,本文将帮助开发者更好地理解和运用这些工具来构建高效且稳定的应用程序。 ####
23 5
|
21天前
|
存储 安全 关系型数据库
Linux系统在服务器领域的应用与优势###
本文深入探讨了Linux操作系统在服务器领域的广泛应用及其显著优势。通过分析其开源性、安全性、稳定性和高效性,揭示了为何Linux成为众多企业和开发者的首选服务器操作系统。文章还列举了Linux在服务器管理、性能优化和社区支持等方面的具体优势,为读者提供了全面而深入的理解。 ###
|
30天前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
82 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
2月前
|
存储 Linux 开发工具
如何进行Linux内核开发【ChatGPT】
如何进行Linux内核开发【ChatGPT】
|
3月前
|
Java Linux API
Linux设备驱动开发详解2
Linux设备驱动开发详解
43 6
|
3月前
|
Unix Linux Ruby
在windows和linux上高效快捷地发布Dash应用
在windows和linux上高效快捷地发布Dash应用
|
3月前
|
消息中间件 算法 Unix
Linux设备驱动开发详解1
Linux设备驱动开发详解
49 5
|
3月前
|
Linux iOS开发 开发者
跨平台开发不再难:.NET Core如何让你的应用在Windows、Linux、macOS上自如游走?
【8月更文挑战第28天】本文提供了一份详尽的.NET跨平台开发指南,涵盖.NET Core简介、环境配置、项目结构、代码编写、依赖管理、构建与测试、部署及容器化等多个方面,帮助开发者掌握关键技术与最佳实践,充分利用.NET Core实现高效、便捷的跨平台应用开发与部署。
184 3
|
消息中间件 缓存 Unix
[面试必备]嵌入式Linux内核开发必须了解的三十道题
[面试必备]嵌入式Linux内核开发必须了解的三十道题
|
Linux Go 人机交互
嵌入式linux之go语言开发(十三)LittlevGL,漂亮的嵌入式GUI的go语言绑定
嵌入式linux之go语言开发(十三)LittlevGL,漂亮的嵌入式GUI的go语言绑定

热门文章

最新文章