我需要一个简单的方法来获取Linux的(守护进程)c代码中的二级存储详细信息(如总大小,已用空间和可用空间);
这是我尝试过的东西
> statvfs – 不知道如何获取磁盘详细信息而不是文件
>在c代码中使用system(“df -h –total | grep total> disk.stat”)然后读取文件.
但是上面涉及文件写入和读取这是不高效的,因为这个c代码是一个守护进程,它将连续轮询系统细节作为图形生成的输入.
如果没有其他方法,请告诉我一个简单快速的ipc机制,以及此bash和c代码之间的通信示例.
/*
* @breif returns total percentage of secondary storage used
*
* - uses bash command to get storage data and store in a file
* - and use c code retrive the percent of usage from file and return it
*/
int calculate_storage_size( )
{
if ( system("df -h --total | grep total > disk.stat") >= 0 )
{
char *temp_char_ptr = (char *)NULL;
int storage_size_percent = -1;
FILE *fp ;
fp = fopen ("disk.stat" , "r");
if (fp != (FILE *)NULL)
{
temp_char_ptr = (char*) calloc ( 6 , 1 );
fscanf( fp,"%s %s %s %s %d", temp_char_ptr, temp_char_ptr, temp_char_ptr, temp_char_ptr, &storage_size_percent);
}
free (temp_char_ptr);
fclose(fp);
return storage_size_percent;
}
return -1;
}
提前致谢和问候
解决方法:
我建议最好让用户指定在总数中应考虑哪些安装,或者使用启发式来省略系统和临时安装.
考虑以下示例,info.c:
#define _POSIX_C_SOURCE 200809L
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/statvfs.h>
#include <mntent.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
static void free_array(char **array)
{
if (array) {
size_t i;
for (i = 0; array[i] != NULL; i++) {
free(array[i]);
array[i] = NULL;
}
free(array);
}
}
static char **normal_mounts(void)
{
char **list = NULL, **temp;
size_t size = 0;
size_t used = 0;
char buffer[4096];
struct mntent entry;
FILE *mounts;
mounts = fopen("/proc/mounts", "r");
if (!mounts)
return NULL;
while (getmntent_r(mounts, &entry, buffer, sizeof buffer) == &entry)
if (strcmp(entry.mnt_fsname, "tmpfs") &&
strcmp(entry.mnt_fsname, "swap") &&
strcmp(entry.mnt_dir, "/proc") && strncmp(entry.mnt_dir, "/proc/", 6) &&
strcmp(entry.mnt_dir, "/boot") && strncmp(entry.mnt_dir, "/boot/", 6) &&
strcmp(entry.mnt_dir, "/sys") && strncmp(entry.mnt_dir, "/sys/", 5) &&
strcmp(entry.mnt_dir, "/run") && strncmp(entry.mnt_dir, "/run/", 5) &&
strcmp(entry.mnt_dir, "/dev") && strncmp(entry.mnt_dir, "/dev/", 5) &&
strcmp(entry.mnt_dir, "/mnt") && strncmp(entry.mnt_dir, "/mnt/", 5) &&
strcmp(entry.mnt_dir, "/media") && strncmp(entry.mnt_dir, "/media/", 7) &&
strcmp(entry.mnt_dir, "/var/run") && strncmp(entry.mnt_dir, "/var/run/", 9)) {
if (used >= size) {
size = (used | 15) + 17;
temp = realloc(list, size * sizeof list[0]);
if (!temp) {
endmntent(mounts);
free_array(list);
errno = ENOMEM;
return NULL;
}
list = temp;
}
if (!(list[used++] = strdup(entry.mnt_dir))) {
endmntent(mounts);
free_array(list);
errno = ENOMEM;
return NULL;
}
}
if (ferror(mounts) || !feof(mounts)) {
endmntent(mounts);
free_array(list);
errno = EIO;
return NULL;
} else
endmntent(mounts);
if (!used) {
free_array(list);
errno = 0;
return NULL;
}
if (size != used + 1) {
size = used + 1;
temp = realloc(list, size * sizeof list[0]);
if (!temp) {
free_array(list);
errno = ENOMEM;
return NULL;
}
list = temp;
}
list[used] = NULL;
errno = 0;
return list;
}
static int statistics(const char **mountpoint, uint64_t *bytes_total, uint64_t *bytes_free)
{
struct statvfs info;
uint64_t btotal = 0;
uint64_t bfree = 0;
size_t i;
if (!mountpoint)
return errno = EINVAL;
for (i = 0; mountpoint[i] != NULL; i++)
if (statvfs(mountpoint[i], &info) != -1) {
btotal += (uint64_t)info.f_frsize * (uint64_t)info.f_blocks;
bfree += (uint64_t)info.f_bsize * (uint64_t)info.f_bavail;
} else
return errno;
if (bytes_total)
*bytes_total = btotal;
if (bytes_free)
*bytes_free = bfree;
return 0;
}
int main(int argc, char *argv[])
{
uint64_t total = 0;
uint64_t nfree = 0;
if (argc > 1) {
if (statistics((const char **)argv + 1, &total, &nfree)) {
fprintf(stderr, "%s.\n", strerror(errno));
return EXIT_FAILURE;
}
} else {
char **mounts = normal_mounts();
size_t i;
if (!mounts) {
if (errno)
fprintf(stderr, "Error determining file systems: %s.\n", strerror(errno));
else
fprintf(stderr, "No normal file systems found.\n");
return EXIT_FAILURE;
}
fprintf(stderr, "Considering mount points");
for (i = 0; mounts[i] != NULL; i++)
fprintf(stderr, " %s", mounts[i]);
fprintf(stderr, "\n");
if (statistics((const char **)mounts, &total, &nfree)) {
fprintf(stderr, "%s.\n", strerror(errno));
return EXIT_FAILURE;
}
free_array(mounts);
}
printf("%20" PRIu64 " bytes total\n", total);
printf("%20" PRIu64 " bytes free\n", nfree);
return EXIT_SUCCESS;
}
statistics()函数采用以NULL结尾的挂载点数组,以及指向无符号64位整数的两个指针.如果成功则返回0,否则返回非零errno代码.如果成功,该函数将把文件系统中的总字节数设置为第一个整数,并将第二个中的空闲字节数设置为第一个整数.
如果提供一个或多个安装点作为命令行参数,则仅考虑这些. (POSIX说argv [argc] == NULL,所以这个用法是安全的.)
否则,normal_mounts()函数用于解析/ proc / mounts以获取“正常”挂载点列表.该函数使用getmntent()
从内核提供的伪文件中读取每个条目(行).排除所有tmpfs(ramdisks)和交换文件系统,以及安装在/ proc,/ boot,/ sys,/ run,/ dev,/ mnt,/ media和/ var / run下的那些系统.这只是一种粗略的启发式方法,而不是一种已知的好方法.
在守护程序中,甚至在图形应用程序中,只调用(相当于)statistics()函数,使用相同的挂载点数组.您甚至可以考虑单独跟踪每个挂载点,并让用户过滤并组合他们感兴趣的信息.事实上,我建议:我个人可能有兴趣看到我临时文件使用的波动(在机器上/ tmp和/ var / tmp是tmpfs mounts),以及跟踪我/ home的长期使用情况.
在守护程序中,您可以使用HUP或USR1或USR2信号指示用户何时需要您重新加载配置 – 安装点列表,此处.我不相信将它集成到DBUS来检测可移动媒体安装/卸载会有多大意思,但当然你可以认为它是有用的.
如果您使用例如编译上述程序
gcc -Wall -O2 info.c -o info
并运行
./info
它会输出类似的东西
Considering mount points / /home
119989497856 bytes total
26786156544 bytes free
第一行输出到标准错误,字节行输出到标准输出.您还可以专门命名挂载点 – 确保它们不同,因为代码不检查重复挂载 – :
./info /home /tmp
如果您想知道如何确定两个目录是否在同一个mount上:在一个上调用stat(path1,& info1),在另一个上调用stat(path2,& info2).当且仅当(info1.st_dev == info2.st_dev)时,这两个路径在同一个挂载上. (一个设备可以在不同的点安装多次,例如使用绑定安装,但通常上面的检查就足够了.)
如果您发现上述所有代码都很烦人,您可以始终依赖df实用程序.要确保输出位于C / POSIX语言环境中(而不是法语或芬兰语),请使用
handle = popen("LANG=C LC_ALL=C df -Pl", "r");
或类似的,并使用len = getline(& line,& size,handle)读取输出.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。