
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 是開源的,但我已經克隆的回購並檢查了代碼。這就是我發現的:
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。
答案1
您發布的程式碼來自函數“get_header”,它會產生第一行中的文字。在您的情況下,這適用於標題“1K-blocks”(致電df -B1023
查看差異)。
要注意的是:「1K」指的是 1024 位元組區塊,而不是 1000 位元組區塊(用「1kB-blocks」表示,請參閱df -B1000
)
人類可讀格式的數字計算由函數「 human_read」 ( human.c:153 ) 處理。在 df.c:1571 中,您可以找到使用下列標誌呼叫時所使用的選項-h
:
case 'h':
human_output_opts = human_autoscale | human_SI | human_base_1024;
output_block_size = 1;
break;
所有計算均以人類可讀格式(“-h”)以 1024 為基數完成。除了顯示的 human_output_opts 之外,還有一個適用於此處的預設設定(請參閱 human.h,枚舉聲明):
/* The following three options are mutually exclusive. */
/* Round to plus infinity (default). */
human_ceiling = 0,
/* Round to nearest, ties to even. */
human_round_to_nearest = 1,
/* Round to minus infinity. */
human_floor = 2,
由於 human_output_opts 不包括 human_round_to_nearest 或 human_floor,因此它將使用其預設值 human_ceiling。因此,所有計算值都將向上舍入。
為了驗證設置,我們可以嘗試根據以下 1K 區塊計算人類可讀格式df
:
Size = ceil(41943040/1024/1024) = ceil(40) = 40
Used = ceil(7659828/1024/1024) = ceil(7.305) = 7.4
Available = ceil(34283212/1024/1024) = ceil(32.695) = 33
這與 的輸出相同df -h
。
(...如果您喜歡 1000 位元組格式,您可以簡單地呼叫df -H
)。
答案2
df
FreeBSD 的程式(這是df -h
最初的來源)和Solaris 的實作都沒有df
這樣做。
由於 Solaris 來源是 OpenSource,您可以檢查是否可以df
在您的作業系統上編譯: