Linux系统C语言遍历系统文件系统,并查询其磁盘使用率(有效磁盘)
getmntent_r接口示例程序地址:https://github.com/Rtoax/test/tree/master/c/glibc/mntent
statfs 接口示例程序地址:https://github.com/Rtoax/test/tree/master/c/glibc/sys/statfs
本文所有代码地址:GitHub地址:https://github.com/Rtoax/test/tree/master/fs-filesystem/fs_occupy
目录
背景介绍
相关接口
文件系统接口
struct mntent
getmntent_r
文件系统状态接口
struct statfs
statfs
C语言实现
接口设计
struct fs_occupy_info
fs_info_ops_fn
fs_storage_occupy
源代码地址
fs_occupy.c
fs_occupy.h
test.c
运行结果
编译运行
df指令查询结果对比
背景介绍
Linux系统C语言遍历系统文件系统,并查询其磁盘使用率(有效磁盘)
相关接口
文件系统接口
struct mntent
#include <mntent.h>struct mntent {char *mnt_fsname; /* name of mounted file system */char *mnt_dir; /* file system path prefix */char *mnt_type; /* mount type (see mntent.h) */char *mnt_opts; /* mount options (see mntent.h) */int mnt_freq; /* dump frequency in days */int mnt_passno; /* pass number on parallel fsck */
};
getmntent_r
getmntent_r是线程安全的。
getmntent_r接口示例程序地址:https://github.com/Rtoax/test/tree/master/c/glibc/mntent
/* GNU extension */
#include <mntent.h>//The reentrant getmntent_r() function is similar to getmntent(),
//but stores the struct mount in the provided *mntbuf and stores the strings
//pointed to by the entries in that struct in the provided array buf of size buflen.
struct mntent *getmntent_r(FILE *fp, struct mntent *mntbuf,char *buf, int buflen);
文件系统状态接口
struct statfs
#if __WORDSIZE == 32 /* System word size */
# define __SWORD_TYPE int
#else /* __WORDSIZE == 64 */
# define __SWORD_TYPE long int
#endifstruct statfs {__SWORD_TYPE f_type; /* type of file system (see below) */__SWORD_TYPE f_bsize; /* optimal transfer block size */fsblkcnt_t f_blocks; /* total data blocks in file system */fsblkcnt_t f_bfree; /* free blocks in fs */fsblkcnt_t f_bavail; /* free blocks available tounprivileged user */fsfilcnt_t f_files; /* total file nodes in file system */fsfilcnt_t f_ffree; /* free file nodes in fs */fsid_t f_fsid; /* file system id */__SWORD_TYPE f_namelen; /* maximum length of filenames */__SWORD_TYPE f_frsize; /* fragment size (since Linux 2.6) */__SWORD_TYPE f_spare[5];
};
系统定义的文件系统类型
//File system types:
//
#define ADFS_SUPER_MAGIC 0xadf5
#define AFFS_SUPER_MAGIC 0xADFF
#define BEFS_SUPER_MAGIC 0x42465331
#define BFS_MAGIC 0x1BADFACE
#define CIFS_MAGIC_NUMBER 0xFF534D42
#define CODA_SUPER_MAGIC 0x73757245
#define COH_SUPER_MAGIC 0x012FF7B7
#define CRAMFS_MAGIC 0x28cd3d45
#define DEVFS_SUPER_MAGIC 0x1373
#define EFS_SUPER_MAGIC 0x00414A53
#define EXT_SUPER_MAGIC 0x137D
#define EXT2_OLD_SUPER_MAGIC 0xEF51
#define EXT2_SUPER_MAGIC 0xEF53
#define EXT3_SUPER_MAGIC 0xEF53
#define EXT4_SUPER_MAGIC 0xEF53
#define HFS_SUPER_MAGIC 0x4244
#define HPFS_SUPER_MAGIC 0xF995E849
#define HUGETLBFS_MAGIC 0x958458f6
#define ISOFS_SUPER_MAGIC 0x9660
#define JFFS2_SUPER_MAGIC 0x72b6
#define JFS_SUPER_MAGIC 0x3153464a
#define MINIX_SUPER_MAGIC 0x137F /* orig. minix */
#define MINIX_SUPER_MAGIC2 0x138F /* 30 char minix */
#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 */
#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2, 30 char names */
#define MSDOS_SUPER_MAGIC 0x4d44
#define NCP_SUPER_MAGIC 0x564c
#define NFS_SUPER_MAGIC 0x6969
#define NTFS_SB_MAGIC 0x5346544e
#define OPENPROM_SUPER_MAGIC 0x9fa1
#define PROC_SUPER_MAGIC 0x9fa0
#define QNX4_SUPER_MAGIC 0x002f
#define REISERFS_SUPER_MAGIC 0x52654973
#define ROMFS_MAGIC 0x7275
#define SMB_SUPER_MAGIC 0x517B
#define SYSV2_SUPER_MAGIC 0x012FF7B6
#define SYSV4_SUPER_MAGIC 0x012FF7B5
#define TMPFS_MAGIC 0x01021994
#define UDF_SUPER_MAGIC 0x15013346
#define UFS_MAGIC 0x00011954
#define USBDEVICE_SUPER_MAGIC 0x9fa2
#define VXFS_SUPER_MAGIC 0xa501FCF5
#define XENIX_SUPER_MAGIC 0x012FF7B4
#define XFS_SUPER_MAGIC 0x58465342
#define _XIAFS_SUPER_MAGIC 0x012FD16D
statfs
statfs 接口示例程序地址:https://github.com/Rtoax/test/tree/master/c/glibc/sys/statfs
int statfs (const char *__file, struct statfs *__buf);
C语言实现
接口设计
struct fs_occupy_info
struct fs_occupy_info {char fs_name[64]; /* name of mounted file system */char fs_mnt_dir[128]; /* file system path prefix */char fs_type[64]; /* mount type (see mntent.h) */unsigned long int totalMB;unsigned long int freeMB;struct {int integer;int decimal;}occupy;
};
fs_info_ops_fn
/*** fs_info_ops_fn - 有效文件系统使用率查询回调函数* * info - 参见 struct fs_occupy_info */
typedef void (*fs_info_ops_fn)(const struct fs_occupy_info *info);
fs_storage_occupy
/** * fs_storage_occupy - 查询有效文件系统使用率* * 该接口会轮询调用 display 有效文件系统个数次,每次将 struct fs_occupy_info 结构* 传递给 fs_info_ops_fn 回调函数。*/
void fs_storage_occupy(fs_info_ops_fn display);
源代码地址
GitHub地址:https://github.com/Rtoax/test/tree/master/fs-filesystem/fs_occupy
fs_occupy.c
/*** fs_occupy - 遍历系统文件系统,并查询其磁盘使用率(有效磁盘)* * 日期:2020年10月15日* 作者:荣涛*/
#include <stdio.h>
#include <stdlib.h>
#include <mntent.h>
#include <pthread.h>
#include <assert.h>
#include <malloc.h>
#include <string.h>
#include <sys/statfs.h>#include "list.h"
#include "fs_occupy.h"#ifndef weak_alias
#define weak_alias(name, aliasname) extern typeof (name) aliasname __attribute__ ((weak, alias(#name)))
#endif/* 文件系统列表 */
struct crypto_fs_system {struct fs_occupy_info occupy_info;struct list_head list;
};/* 为了线程安全 */
static pthread_rwlock_t fs_rwlock = PTHREAD_RWLOCK_INITIALIZER;
static LIST_HEAD(fs_list);/*多文件系统链表头 *//* 返回0,有效的文件系统,可以统计出使用率返回其他,无效的文件系统,不可以统计使用率
*/
static int calculate_fs_occupy_nonlock(struct fs_occupy_info *info)
{struct statfs diskInfo;memset(&diskInfo, 0, sizeof(struct statfs));/* 获取文件系统属性 */statfs(info->fs_mnt_dir, &diskInfo);/* 获取参数,计算总MB数 */unsigned long long totalBlocks = diskInfo.f_bsize;unsigned long long totalSize = totalBlocks * diskInfo.f_blocks;size_t mbTotalsize = totalSize>>20;info->totalMB = mbTotalsize;// printf(">>>>>>>>> %-15s %ld\t%ld\t\n",
// info->fs_mnt_dir,
// diskInfo.f_blocks, /* total data blocks in file system */
// diskInfo.f_bfree /* free blocks in fs */
// );/* 检测参数有效性 */if(mbTotalsize <= 0) return -1;/* 计算参数 */unsigned long long freeDisk = diskInfo.f_bfree*totalBlocks;size_t mbFreedisk = freeDisk>>20;info->freeMB = mbFreedisk;/* 检测参数有效性 */if(mbFreedisk <= 0) return -1;/* 计算使用率 */double occupy = (mbTotalsize-mbFreedisk)*1.0/mbTotalsize;int occupy_integer = (int) (occupy*100.0);int occupy_decimal = (int) (occupy*100000.0) - occupy_integer*100;if(occupy_integer < 0) return -1;if(occupy_decimal < 0) return -1;info->occupy.integer = occupy_integer;info->occupy.decimal = occupy_decimal;return 0;
}/* 从系统中获取 */
static void fs_list_alloc_nonlock()
{struct mntent *ent, mntbuf;FILE *aFile;aFile = setmntent("/proc/mounts", "r"); assert(aFile != NULL);char buf[512] = {0};while (NULL != (ent = getmntent_r(aFile, &mntbuf, buf, 512))) {struct crypto_fs_system *fs = malloc(sizeof(struct crypto_fs_system));assert(fs != NULL);memset(fs, 0, sizeof(struct crypto_fs_system));/* 这里需要拷贝新实例 */strcpy(fs->occupy_info.fs_name, ent->mnt_fsname);strcpy(fs->occupy_info.fs_type, ent->mnt_type);strcpy(fs->occupy_info.fs_mnt_dir, ent->mnt_dir);/* 计算使用率 */int ret = calculate_fs_occupy_nonlock(&fs->occupy_info);if(ret == 0) {list_add_tail(&fs->list, &fs_list);} else {free(fs);}}endmntent(aFile);
}/* 释放链表 */
static void fs_list_free_nonlock()
{struct crypto_fs_system *ifs = NULL, *next_fs = NULL;list_for_each_entry_safe(ifs, next_fs, &fs_list, list) {if(ifs) {list_del(&ifs->list);free(ifs);}}
}
/* 初始化/创建/填充链表 */
static void fs_list_init_safe()
{volatile static int load_already = 0;/* 线程锁 */pthread_rwlock_wrlock(&fs_rwlock);load_already += 1; if(load_already == 1) {fs_list_alloc_nonlock();}if(load_already == 3) {load_already = 1;fs_list_free_nonlock();fs_list_alloc_nonlock();}pthread_rwlock_unlock(&fs_rwlock);
}/* 轮询链表 */
static void for_each_fs_nonlock(fs_info_ops_fn display)
{ if(list_empty_careful(&fs_list)) {return ;}struct crypto_fs_system *ifs = NULL, *next_fs = NULL;list_for_each_entry_safe(ifs, next_fs, &fs_list, list) {if(ifs) {struct fs_occupy_info *info = &ifs->occupy_info;if(display) display(info);}}
}/* 轮询链表,线程安全 */
static void for_each_fs_safe(fs_info_ops_fn display)
{pthread_rwlock_rdlock(&fs_rwlock);for_each_fs_nonlock(display);pthread_rwlock_unlock(&fs_rwlock);
}/** * __fs_storage_occupy - 查询有效文件系统使用率* * 该接口会轮询调用 display 有效文件系统个数次,每次将 struct fs_occupy_info 结构* 传递给 fs_info_ops_fn 回调函数。*/
static void __fs_storage_occupy(fs_info_ops_fn display)
{if(!display) return ;fs_list_init_safe();for_each_fs_safe(display);
}
weak_alias(__fs_storage_occupy, fs_storage_occupy);
fs_occupy.h
/*** fs_occupy - 遍历系统文件系统,并查询其磁盘使用率(有效磁盘)* * 日期:2020年10月15日* 作者:荣涛*/
#ifndef __FS_OCCUPY_H
#define __FS_OCCUPY_H 1#include <stdio.h>/*** struct fs_occupy_info - 文件系统使用率查询信息结构* * fs_name - 文件系统名称,例如 /dev/mapper/centos-root* fs_mnt_dir - 文件系统挂载点* # df * 文件系统 1K-块 已用 可用 已用% 挂载点* /dev/mapper/centos-root 36678148 35066696 1611452 96% /** fs_type - 文件系统类型 xfs ext4 rootfs 等* * * occupy occupy.integer 使用率的正数部分* occupy.decimal 使用率的小数部分* 例如: 使用率为 20.234 %时:* occupy.integer=20* occupy.decimal=234*/
struct fs_occupy_info {char fs_name[64]; /* name of mounted file system */char fs_mnt_dir[128]; /* file system path prefix */char fs_type[64]; /* mount type (see mntent.h) */unsigned long int totalMB;unsigned long int freeMB;struct {int integer;int decimal;}occupy;
};/*** fs_info_ops_fn - 有效文件系统使用率查询回调函数* * info - 参见 struct fs_occupy_info */
typedef void (*fs_info_ops_fn)(const struct fs_occupy_info *info);/** * fs_storage_occupy - 查询有效文件系统使用率* * 该接口会轮询调用 display 有效文件系统个数次,每次将 struct fs_occupy_info 结构* 传递给 fs_info_ops_fn 回调函数。*/
void fs_storage_occupy(fs_info_ops_fn display);#endif /*<__FS_OCCUPY_H>*/
test.c
#include <stdio.h>#include "fs_occupy.h"void fs_display(const struct fs_occupy_info *info)
{printf("%-25s %-10s %-16s %ldMb/%ldMb %3d.%2d%%\n", info->fs_name, info->fs_type, info->fs_mnt_dir,info->freeMB,info->totalMB,info->occupy.integer,info->occupy.decimal);
}int main(void)
{printf("\n-------------------------------------\n");fs_storage_occupy(fs_display);
}
运行结果
编译运行
[root@localhost fs_occupy]# make
gcc fs_occupy.c test.c -o test.out -pthread
[root@localhost fs_occupy]# ./test.out -------------------------------------
rootfs rootfs / 1573Mb/35818Mb 95.86108%
devtmpfs devtmpfs /dev 3875Mb/3875Mb 0. 0%
tmpfs tmpfs /dev/shm 3891Mb/3891Mb 0. 0%
tmpfs tmpfs /run 3410Mb/3891Mb 12.11161%
tmpfs tmpfs /sys/fs/cgroup 3891Mb/3891Mb 0. 0%
/dev/mapper/centos-root xfs / 1573Mb/35818Mb 95.86108%
/dev/vda1 xfs /boot 641Mb/1014Mb 36.33185%
/dev/vdb ext4 /work 66404Mb/100664Mb 34.30634%
tmpfs tmpfs /run/user/42 778Mb/778Mb 0. 0%
tmpfs tmpfs /run/user/1002 778Mb/778Mb 0. 0%
df指令查询结果对比
[root@localhost fs_occupy]# df
文件系统 1K-块 已用 可用 已用% 挂载点
/dev/mapper/centos-root 36678148 35066860 1611288 96% /
devtmpfs 3968696 0 3968696 0% /dev
tmpfs 3985092 88 3985004 1% /dev/shm
tmpfs 3985092 492648 3492444 13% /run
tmpfs 3985092 0 3985092 0% /sys/fs/cgroup
/dev/vda1 1038336 381768 656568 37% /boot
/dev/vdb 103080888 35082384 62739240 36% /work
tmpfs 797020 12 797008 1% /run/user/42
tmpfs 797020 0 797020 0% /run/user/1002
可以看出本文结果精确度更高
Linux系统C语言遍历系统文件系统,并查询其磁盘使用率(有效磁盘)相关推荐
- c语言的学生理系统,C语言学习系统的教程
完美者(wmzhe.com)网站以软件下载为基础,改版后的网站对功能性板块进行扩充,以期能够解决用户在软件使用过程中遇见的所有问题.网站新增了"软件百科"."锦囊妙技&q ...
- Linux系统查看CPU使用率、内存使用率、磁盘使用率、磁盘大小
一.查看CPU使用率 1.top命令 在linux的系统维护中,可能需要经常查看cpu使用率,分析系统整体的运行情况.常用的查看CPU使用率命令为top命令. top命令是Linux下常用的性能分析工 ...
- c语言飞机订餐系统,C语言订餐系统.doc
C语言订餐系统 课 程 设 计 说 明 书 课程名称:C语言程序设计 设计题目:电话订餐信息处理 院 系:计算机科学与信息工程学院 姓名学号: 专业班级: 指导教师: 课 程 设 计 任 务 书 设计 ...
- c语言报表系统,C语言考试系统程序设计报告.doc
C语言考试系统程序设计报告 <程序设计基础> 课程设计报告 考试系统 指导教师:任姚鹏 班 级:计科系1204班 学生姓名:丁晓荟 加雪梅 姚乐 张进 吕亚斌 完成日期:2013.11.2 ...
- Linux下C语言的系统头文件
Linux菜鸟初看Linux下编程的糗事. 前段时间琢磨着接触一下Linux下的C语言编程,就找了本书看.看到很多文件操作的程序要包含"sys/stat.h". 写程序前,我想先找 ...
- linux vim go语言,CentOS7系统基于Vim8搭建Go语言开发环境
主要是在vim中通过vundle来安装vim-go插件.gocode插件,支持代码高亮.代码提示以及语法检查等功能 安装Golang 1.11.2 curl -Lo golang.tar.gz htt ...
- linux 使用 C 语言获得系统 MAC 地址
2019独角兽企业重金招聘Python工程师标准>>> //google 到的 测试有效 #include <stdio.h> #include <sys/ioct ...
- 城市公交查询系统c语言,Android的城市公交查询系统
随着国家大力发展公共交通,越来越多的人选择公交出行,如何才能快速准确地获得出行信息也成为了关注的问题.正在被大家使用的GPS和GIS等手段已经非常成熟,其中最主要的三大功能:站点查询,线路查询,公交换 ...
- linux 系统 Shell语言 基础
linux 系统 Shell语言 基础 第一章 Shell 编程 1 . 概述 Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Sh ...
最新文章
- excel数据透视表列名更改
- mysql gbk支持_mysql如何支持gbk编码
- C语言:内存的分配与管理
- code vs 集成tfs_关于编译器和集成开发环境,一文给你讲明白!
- 你一定要了解的NB-IoT !
- 描写火车站场景_关于描写火车站的句子
- python 爬虫是什么_“python爬虫“是什么呢?
- 递归列出文件下的文件信息,迭代器
- python十大实例_Python练习实例100例(从简入难)96-100
- unity怪物攻击玩家减血_怪物猎人发布15周年 — 回顾历代封面怪之三大传奇怪物...
- Rust 创始人谈 Rust 2019 和未来:社区应限制成长速度
- 常用计算机故障的判断方法有哪些,常用汽车故障基本诊断方法
- 查看显卡型号命令_ubuntu查看显卡型号方法有哪些
- 不同音乐格式之谜(wav,flac,ape,wv,tak,ogg,aac)
- 若菜光个人小档案(dambolo)
- You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true
- How to install VIB on VMware ESXi
- Delphi对象克隆技术
- Java 关于java.util.LinkedHashMap cannot be cast to 实体类问题答案
- 【HTML+CSS】字体字号行高
热门文章
- java关键字:volatile
- Spring框架----Spring的IOC
- POJ 2762Going from u to v or from v to u?(强联通 + 缩点 + 拓扑排序)
- Python3 移动文件——合集
- css3-background clip 和background origin
- Spring-Security (学习记录二)--修改为自己的登录页面
- 黑马程序员—————— 随机访问流
- Ubuntu下 VirtualBox的卸载和升级 (转载)
- loadrunner 脚本优化-事务时间简介
- havlenapetr ffmpeg的移植