将statvfs转换为正确的百分比

我有一个非常简单的testing程序,打印出下面的数字。

int main(int argc, char* argv[]) struct statvfs vfs; statvfs(argv[1], &vfs); printf("f_bsize (block size): %lu\n" "f_frsize (fragment size): %lu\n" "f_blocks (size of fs in f_frsize units): %lu\n" "f_bfree (free blocks): %lu\n" "f_bavail free blocks for unprivileged users): %lu\n" "f_files (inodes): %lu\n" "f_ffree (free inodes): %lu\n" "f_favail (free inodes for unprivileged users): %lu\n" "f_fsid (file system ID): %lu\n" "f_flag (mount flags): %lu\n" "f_namemax (maximum filename length)%lu\n", vfs.f_bsize, vfs.f_frsize, vfs.f_blocks, vfs.f_bfree, vfs.f_bavail, vfs.f_files, vfs.f_ffree, vfs.f_favail, vfs.f_fsid, vfs.f_flag, vfs.f_namemax); return 0; } 

打印出来:

 f_bsize (block size): 4096 f_frsize (fragment size): 4096 f_blocks (size of fs in f_frsize units): 10534466 f_bfree (free blocks): 6994546 f_bavail free blocks for unprivileged users): 6459417 f_files (inodes): 2678784 f_ffree (free inodes): 2402069 f_favail (free inodes for unprivileged users): 2402069 f_fsid (file system ID): 12719298601114463092 f_flag (mount flags): 4096 f_namemax (maximum filename length)255 

DF打印出来的根FS:

 Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda5 42137864 14159676 25837672 36% / 

但这里是我困惑的地方。

25837672 + 14159676!= 42137846(实际上是39997348)

因此,如果我要做calc 14159676/42137864 * 100,那么我可以得到33%,而不是36%。

但如果我计算

14159676/39997348 * 100我得到35%。

为什么所有的差异和df获得号码42137864? 是否与一些转换为1k块相对于实际的系统块大小是4k?

这将被集成到我的caching应用程序,告诉我什么时候驱动器在某个阈值…例如90%,然后我开始释放固定大小的块大小为2 ^ n的大小。 所以我所追求的是一个function,使我有一个相当准确的使用%。

编辑:我现在可以匹配什么DF打印。 除了使用的百分比。 这使我们想知道这是多么准确。 什么是片段大小?

 unsigned long total = vfs.f_blocks * vfs.f_frsize / 1024; unsigned long available = vfs.f_bavail * vfs.f_frsize / 1024; unsigned long free = vfs.f_bfree * vfs.f_frsize / 1024; printf("Total: %luK\n", total); printf("Available: %luK\n", available); printf("Used: %luK\n", total - free); 

EDIT2:

 unsigned long total = vfs.f_blocks * vfs.f_frsize / 1024; unsigned long available = vfs.f_bavail * vfs.f_frsize / 1024; unsigned long free = vfs.f_bfree * vfs.f_frsize / 1024; unsigned long used = total - free; printf("Total: %luK\n", total); printf("Available: %luK\n", available); printf("Used: %luK\n", used); printf("Free: %luK\n", free); // Calculate % used based on f_bavail not f_bfree. This is still giving out a different answer to df??? printf("Use%%: %f%%\n", (vfs.f_blocks - vfs.f_bavail) / (double)(vfs.f_blocks) * 100.0); f_bsize (block size): 4096 f_frsize (fragment size): 4096 f_blocks (size of fs in f_frsize units): 10534466 f_bfree (free blocks): 6994182 f_bavail (free blocks for unprivileged users): 6459053 f_files (inodes): 2678784 f_ffree (free inodes): 2402056 f_favail (free inodes for unprivileged users): 2402056 f_fsid (file system ID): 12719298601114463092 f_flag (mount flags): 4096 f_namemax (maximum filename length)255 Total: 42137864K Available: 25836212K Used: 14161136K Free: 27976728K Use%: 38.686470% matth@kubuntu:~/dev$ df Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda5 42137864 14161136 25836212 36% / 

我得到38%不是36.如果用f_bfree计算,我得到33%。 是错误的,或者这是不会准确的? 如果是这样的话,我想要保守一边。

Solutions Collecting From Web of "将statvfs转换为正确的百分比"

df的数据可能基于f_bavail ,而不是f_bfree 。 您可能会发现查看df的源代码以查看它如何执行操作很有帮助。 它有一些需要处理的边界情况(例如,当已用空间超过非root用户可用的空间量时),但正常情况下的相关代码如下:

  uintmax_t u100 = used * 100; uintmax_t nonroot_total = used + available; pct = u100 / nonroot_total + (u100 % nonroot_total != 0); 

换句话说, 100 * used / (used + available) ,四舍五入。 插入你的df输出的值给出100 * 14159676 / (14159676 + 25837672) = 35.4015371 ,向上取整为36%,就像df计算一样。

这是最接近我匹配使用百分比的df -h的输出:

 const uint GB = (1024 * 1024) * 1024; struct statvfs buffer; int ret = statvfs(diskMountPoint.c_str(), &buffer); const double total = ceil((double)(buffer.f_blocks * buffer.f_frsize) / GB); const double available = ceil((double)(buffer.f_bfree * buffer.f_frsize) / GB); const double used = total - available; const double usedPercentage = ceil((double)(used / total) * (double)100); return usedPercentage; 

在编辑#2上,Usage%计算需要更新到这个以匹配df输出:

 100.0 * (double) (vfs.f_blocks - vfs.f_bfree) / (double) (vfs.f_blocks - vfs.f_bfree + vfs.f_bavail) 

推理:
已用= f_blocks – f_bfree
可用= f_bavail
df%=使用/(使用+可用)

statvfs指标有点混乱。 您可以使用psutil源代码作为示例获取有意义的字节值: https : //github.com/giampaolo/psutil/blob/f4734c80203023458cb05b1499db611ed4916af2/psutil/_psposix.py#L119