
wie genau funktioniert df -h? Wenn ich ausführe df
, erhalte ich Folgendes:
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/simfs 41943040 7659828 34283212 19% /
Wenn ich ausführe df -h
, erhalte ich Folgendes:
Filesystem Size Used Avail Use% Mounted on
/dev/simfs 40G 7.4G 33G 19% /
Die Frage ist, wie man dieselben Zahlen erhält.
41943040 / 1024 / 1024 = 40 OK, teilen wir den Rest durch 1024.
7659828 / 1024 / 1024 = 7,304981
Dann vielleicht um 1000?
7659828 / 1000 / 1000 = 7,659828
Wie df -h
kommt man zu 7,4G?
34283212 / 1024 / 1024 = 32,695, which is ±33G
Obwohl df Open Source ist, habe ichgeklontdas Repo und habe den Code überprüft. Das habe ich gefunden:
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));
}
Ich habe keine Erfahrung mit dieser Sprache, aber so wie ich es verstehe, versucht sie zu prüfen, ob der Wert in jeder Spalte durch 1024 oder 1000 teilbar ist, und wählt dann die bessere -h
Option zur Darstellung der Werte aus. Aber ich erhalte nicht denselben Wert, egal ob ich durch 1000 oder 1024 teile. Warum?
Ich glaube, ich weiß, warum. Es prüft, ob durch 1000 oder 1024 geteilt wird.jedeAufteilung.
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;
also knacken wir 7659828 / 1024 / 1024 = 7,304981. -h
gab Antwort von7,4 G
7659828 / 1024 = 7480,xxx
7659828 / 1000 = 7659,xxx
während 7659 mehr als 7480 ist, teilen Sie durch 1024.
Immer noch eine große Zahl, weiter geht’s:
7659828 / 1024 / 1024 = 7,xxx (7,3049..)
7659828 / 1024 / 1000 = 7,xxx (7,4803..)
es nimmt jetzt 1000 und gibt 7,48 und ichglaubenirgendwo im Code wird abgerundet, also „lieber weniger als mehr“ sagen, während Sie 7,4 G Daten eingeben können, aber nicht 7,5 G.
Gleiche Geschichte mit 33,4G
34283212 / 1024 / 1000 = 33.47...
Es wird also 33G.
Antwort1
Der von Dir gepostete Code stammt aus der Funktion "get_header", die den Text in der ersten Zeile generiert. In Deinem Fall betrifft das die Überschrift "1K-Blöcke" (aufrufen, df -B1023
um den Unterschied zu sehen).
Wichtiger Hinweis: „1K“ bezieht sich auf 1024-Byte-Blöcke, nicht auf 1000-Byte-Blöcke (gekennzeichnet durch „1kB-Blöcke“, siehe df -B1000
)
Die Berechnung der Zahlen in das für Menschen lesbare Format übernimmt die Funktion "human_readable" (human.c:153). In df.c:1571 finden Sie die Optionen, die beim Aufruf mit dem -h
Flag verwendet werden:
case 'h':
human_output_opts = human_autoscale | human_SI | human_base_1024;
output_block_size = 1;
break;
Alle Berechnungen werden mit Basis 1024 in menschenlesbarem Format ("-h") durchgeführt. Zusätzlich zu den angezeigten human_output_opts gibt es eine Standardeinstellung, die hier gilt (siehe human.h, Enumerationsdeklaration):
/* 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,
Da human_output_opts weder human_round_to_nearest noch human_floor enthält, wird der Standardwert human_ceiling verwendet. Alle berechneten Werte werden daher aufgerundet.
Um die Einstellungen zu überprüfen, können wir versuchen, das für Menschen lesbare Format basierend auf den 1K-Blöcken wie folgt zu berechnen 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
Dies ist dasselbe wie die Ausgabe von df -h
.
(... und wenn Sie das 1000-Byte-Format bevorzugen, können Sie einfach aufrufen df -H
).
Antwort2
Weder das df
Programm von FreeBSD (hier kommt es df -h
ursprünglich her) noch die df
Implementierung von Solaris verhalten sich so.
Da es sich bei den Solaris-Quellen um OpenSource handelt, können Sie prüfen, ob die Kompilierung df
auf Ihrem Betriebssystem möglich ist: