como exatamente funciona o df -h? Se eu executar df
, obtenho isto:
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/simfs 41943040 7659828 34283212 19% /
Se eu executar df -h
, obtenho isto:
Filesystem Size Used Avail Use% Mounted on
/dev/simfs 40G 7.4G 33G 19% /
A questão é como obter os mesmos números?
41943040/1024/1024 = 40 OK, vamos dividir os outros por 1024.
7659828 / 1024 / 1024 = 7,304981
Então talvez por 1000?
7659828 / 1000 / 1000 = 7,659828
Como df -h
obteve 7,4G?
34283212 / 1024 / 1024 = 32,695, which is ±33G
Embora df seja open source, eu clonei o repo e verifiquei o código. Foi o que eu encontrei:
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));
}
Eu não tenho experiência com essa linguagem, mas pelo que entendi, ela tenta verificar se o valor em cada coluna é divisível por 1024 ou 1000 e escolha o que é melhor para renderizar valores para a opção -h
. Mas eu não tenho o mesmo valor, não importa se eu divido por 1000 ou 1024. Por quê?
Eu acho que sei porque. Ele verifica para dividir por 1000 ou 1024 em cada divisão.
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;
então vamos quebrar 7659828/1024/1024 = 7,304981. -h
deu resposta de 7.4G
7659828 / 1024 = 7480,xxx
7659828 / 1000 = 7659,xxx
enquanto 7659 é mais que 7480, divida por 1024.
Ainda um grande número, vamos continuar:
7659828 / 1024 / 1024 = 7,xxx (7,3049..)
7659828 / 1024 / 1000 = 7,xxx (7,4803..)
leva 1000 agora e dá 7,48 e eu acredito em algum lugar no código que é arredondado para baixo, então "melhor dizer menos que mais" enquanto você pode colocar 7,4G de dados, mas você pode ' Coloque 7,5G.
Mesma história com 33.4G
34283212 / 1024 / 1000 = 33.47...
Assim, torna-se 33G.