為什麼 df 和 df -h 顯示不同的值?df -h 如何進行計算?
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
標誌呼叫時使用的選項: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
)。