正确地将statvfs转换为百分比

Mat*_*att 20 c c++ linux filesystems

我有一个非常简单的测试程序,打印出以下数字.

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;
    }
Run Code Online (Sandbox Code Playgroud)

打印出来:

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
Run Code Online (Sandbox Code Playgroud)

df打印出根fs:

Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sda5             42137864  14159676  25837672  36% /
Run Code Online (Sandbox Code Playgroud)

但这里是我困惑的地方.

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

因此,如果我要进行计算14159676/42137864*100,我得到33%而不是36%作为df打印.

但如果我计算

14159676/39997348*100我得到35%.

为什么所有的差异以及在哪里得到号码42137864?它是否与某些转换为1k块相比,实际系统块大小为4k?

这将被集成到我的缓存应用程序中,以告诉我何时驱动器处于某个阈值...例如90%之前我开始释放大小为2 ^ n大小的固定大小的块.所以我所追求的是一个功能,它给了我一个相当准确的%使用.

编辑:我现在可以匹配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);
Run Code Online (Sandbox Code Playgroud)

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% /
Run Code Online (Sandbox Code Playgroud)

我得到38%不是36.如果按f_bfree计算我得到33%.是df错了还是这个从来都不准确?如果是这种情况,那么我想依靠保守的一面.

bdo*_*lan 17

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);
Run Code Online (Sandbox Code Playgroud)

换句话说,100 * used / (used + available)向上舍入.从您的df输出中插入值得出100 * 14159676 / (14159676 + 25837672) = 35.4015371,其舍入值为36%,正如df计算的那样.


小智 5

在您的Edit#2上,需要将Usage%计算更新为此,以匹配df输出:

100.0 * (double) (vfs.f_blocks - vfs.f_bfree) / (double) (vfs.f_blocks - vfs.f_bfree + vfs.f_bavail)
Run Code Online (Sandbox Code Playgroud)

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