df -h 究竟是如何工作的?如果我运行df
,我会得到这个:
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/simfs 41943040 7659828 34283212 19% /
如果我运行df -h
,我会得到这个:
Filesystem Size Used Avail Use% Mounted on
/dev/simfs 40G 7.4G 33G 19% /
问题是如何获得相同的数字?
41943040 / 1024 / 1024 = 40 好的,让我们除以 1024。
7659828 / 1024 / 1024 = 7,304981
然后可能是1000?
7659828 / 1000 / 1000 = 7,659828
df -h
7.4G是怎么来的?
34283212 / 1024 / 1024 = 32,695, which is ±33G
虽然 df 是开源的,但我已经克隆了 repo 并检查了代码。这就是我发现的:
for (col = 0; col < ncolumns; col++)
{
char *cell = NULL;
char const *header = _(columns[col]->caption);
if (columns[col]->field == SIZE_FIELD
&& (header_mode == DEFAULT_MODE
|| (header_mode == OUTPUT_MODE
&& !(human_output_opts & human_autoscale))))
{
char buf[LONGEST_HUMAN_READABLE + 1];
int opts = (human_suppress_point_zero
| human_autoscale | human_SI
| (human_output_opts
& (human_group_digits | human_base_1024 | human_B)));
/* Prefer the base that makes the human-readable value more exact,
if there is a difference. */
uintmax_t q1000 = output_block_size;
uintmax_t q1024 = output_block_size;
bool divisible_by_1000;
bool divisible_by_1024;
do
{
divisible_by_1000 = q1000 % 1000 == 0; q1000 /= 1000;
divisible_by_1024 = q1024 % 1024 == 0; q1024 /= 1024;
}
while (divisible_by_1000 & divisible_by_1024);
if (divisible_by_1000 < divisible_by_1024)
opts |= human_base_1024;
if (divisible_by_1024 < divisible_by_1000)
opts &= ~human_base_1024;
if (! (opts & human_base_1024))
opts |= human_B;
char *num = human_readable (output_block_size, buf, opts, 1, 1);
/* Reset the header back to the default in OUTPUT_MODE. */
header = _("blocks");
/* TRANSLATORS: this is the "1K-blocks" header in "df" output. */
if (asprintf (&cell, _("%s-%s"), num, header) == -1)
cell = NULL;
}
else if (header_mode == POSIX_MODE && columns[col]->field == SIZE_FIELD)
{
char buf[INT_BUFSIZE_BOUND (uintmax_t)];
char *num = umaxtostr (output_block_size, buf);
/* TRANSLATORS: this is the "1024-blocks" header in "df -P". */
if (asprintf (&cell, _("%s-%s"), num, header) == -1)
cell = NULL;
}
else
cell = strdup (header);
if (!cell)
xalloc_die ();
hide_problematic_chars (cell);
table[nrows - 1][col] = cell;
columns[col]->width = MAX (columns[col]->width, mbswidth (cell, 0));
}
我没有使用这种语言的经验,但据我了解,它会尝试检查每列上的值是否可以被 1024 或 1000 整除,并选择更好的值来呈现-h
选项的值。但是无论我除以 1000 还是 1024,我都没有得到相同的值。为什么?
我想我知道为什么。它检查在每个除法上除以 1000 或 1024。
if (divisible_by_1000 < divisible_by_1024)
opts |= human_base_1024;
if (divisible_by_1024 < divisible_by_1000)
opts &= ~human_base_1024;
if (! (opts & human_base_1024))
opts |= human_B;
所以让我们破解 7659828 / 1024 / 1024 = 7,304981。-h
给出了7.4G的答案
7659828 / 1024 = 7480,xxx
7659828 / 1000 = 7659,xxx
而 7659 大于 7480,除以 1024。
仍然是一个很大的数字,让我们继续:
7659828 / 1024 / 1024 = 7,xxx (7,3049..)
7659828 / 1024 / 1000 = 7,xxx (7,4803..)
现在需要 1000 并给出 7,48,我相信在代码中的某个地方它会向下舍入,所以“最好说少而不是多”,而您可以输入 7.4G 的数据,但不能输入 7.5G。
与 33.4G 相同的故事
34283212 / 1024 / 1000 = 33.47...
所以变成了33G。
您发布的代码来自函数“get_header”,该函数在第一行生成文本。在您的情况下,这适用于标题“1K-blocks”(致电
df -B1023
查看差异)。需要注意的重要一点:“1K”指的是 1024 字节的块,而不是 1000 字节的块(用“1kB-blocks”表示,请参阅
df -B1000
)人类可读格式的数字计算由函数“human_readable”(human.c:153)处理。在 df.c:1571 中,您可以找到使用
-h
标志调用时使用的选项:所有计算均以人类可读格式(“-h”)的基数 1024 完成。除了显示的 human_output_opts 之外,还有一个适用于此处的默认设置(参见 human.h,枚举声明):
由于human_output_opts 不包括human_round_to_nearest 或human_floor,它将使用其默认值human_ceiling。因此,所有计算值都将向上取整。
为了验证设置,我们可以尝试根据 1K 块计算人类可读的格式
df
:这与 的输出相同
df -h
。(...如果您更喜欢 1000 字节格式,您可以简单地调用
df -H
)。df
来自 FreeBSD的程序(这df -h
是最初的来源)和df
来自 Solaris 的实现都不是这种方式。由于 Solaris 源是开源的,您可以检查是否可以
df
在您的操作系统上编译: