Ich habe ein Verzeichnis mit über 400 GiB Daten. Ich wollte prüfen, ob alle Dateien fehlerfrei gelesen werden können, so dass eine einfache Art und Weise dachte ich, war tar
es in /dev/null
. Stattdessen sehe ich folgendes Verhalten:
$ time tar cf /dev/null .
real 0m4.387s
user 0m3.462s
sys 0m0.185s
$ time tar cf - . > /dev/null
real 0m3.130s
user 0m3.091s
sys 0m0.035s
$ time tar cf - . | cat > /dev/null
^C
real 10m32.985s
user 0m1.942s
sys 0m33.764s
Der dritte obige Befehl wurde von Ctrl+ gewaltsam gestoppt, Cnachdem er schon ziemlich lange gelaufen war. Während die ersten beiden Befehle funktionierten, war die Aktivitätsanzeige des Speichergeräts, das sie enthielt, .
fast immer inaktiv. Mit dem dritten Befehl leuchtet die Anzeige konstant und bedeutet extreme Betriebsamkeit.
Wenn also festgestellt werden kann, dass tar
es sich um eine Ausgabedatei handelt /dev/null
, dh wenn sie /dev/null
direkt geöffnet wird, um das tar
Dateihandle zu haben, in das geschrieben wird, wird der Dateikörper übersprungen. (Durch Hinzufügen der v
Option zum tar
Drucken werden alle Dateien im Verzeichnis tar
"rot" gedruckt .)
Also frage ich mich, warum das so ist? Ist es eine Art Optimierung? Wenn ja, warum sollte dann tar
überhaupt eine so zweifelhafte Optimierung für einen solchen Sonderfall durchgeführt werden?
Ich verwende GNU tar 1.26 mit glibc 2.27 unter Linux 4.14.105 amd64.
find . -type f -exec shasum -a256 -b '{}' +
. Nicht nur , dass es tatsächlich lesen und alle die Daten Prüfsumme, aber wenn Sie die Ausgabe speichern, können Sie erneut ausführen , um es später zu prüfen, ob der Inhalt der Dateien nicht verändert hat.pv
:tar -cf - | pv >/dev/null
. Das umgeht das Problem und gibt Ihnen eine Fortschrittsinformation (die verschiedenenpv
Optionen)gtar -cf /dev/zero ...
, um zu bekommen, was Sie möchten.Antworten:
Es ist eine dokumentierte Optimierung :
quelle
info tar
stattdessen versuchen sollen ...info
oder als HTML in einem Browser verfügbar ist .Dies kann mit einer Vielzahl von Programmen passieren, zum Beispiel hatte ich dieses Verhalten einmal, als ich es nur benutzte
cp file /dev/null
. Anstatt eine Schätzung meiner Lesegeschwindigkeit zu erhalten, kehrte der Befehl nach einigen Millisekunden zurück.Soweit ich mich erinnere, war das unter Solaris oder AIX, aber das Prinzip gilt für alle Arten von Unix-y-Systemen.
In früheren Zeiten, als ein Programm eine Datei irgendwohin kopierte, wechselte es zwischen
read
Aufrufen, die einige Daten von der Festplatte (oder was auch immer der Dateideskriptor bezeichnet) in den Speicher abriefen (mit der Garantie, dass beiread
Rückkehr alles vorhanden ist ) undwrite
Aufrufen (Die nehmen den Teil des Speichers und senden den Inhalt an das Ziel).Es gibt jedoch mindestens zwei neuere Methoden, um dasselbe zu erreichen:
Linux hat Systemaufrufe
copy_file_range
(nicht portierbar für andere Unixe) undsendfile
(etwas portierbar; ursprünglich zum Senden einer Datei an das Netzwerk gedacht, kann aber jetzt jedes Ziel verwenden). Sie sollen den Transfer optimieren. Wenn das Programm eines davon verwendet, ist es leicht vorstellbar, dass der Kernel das Ziel erkennt/dev/null
und den Systemaufruf in ein No-Op verwandeltProgramme können verwenden
mmap
, um den Dateiinhalt abzurufenread
. Dies bedeutet im Wesentlichen, dass die Daten vorhanden sind, wenn ich versuche, auf diesen Speicherblock zuzugreifen, und nicht, dass die Daten vorhanden sind, wenn der Systemaufruf zurückkehrt. Ein Programm kann alsommap
die Quelldatei und dannwrite
diesen Teil des zugeordneten Speichers aufrufen . Da beim Schreiben/dev/null
jedoch nicht auf die geschriebenen Daten zugegriffen werden muss, wird die Bedingung "Vergewissern Sie sich, dass sie vorhanden sind" nie ausgelöst, sodass die Datei auch nicht gelesen wird.Nicht sicher , ob Gnu Teer verwendet überhaupt, und das, diese beiden Mechanismen , wenn es erkennt es schriftlich
/dev/null
, aber sie sind der Grund , warum jedes Programm, wenn verwendet Lesegeschwindigkeiten zu überprüfen , sollte ausgeführt werden ,| cat > /dev/null
statt> /dev/null
- und warum| cat > /dev/null
sollst wird vermieden in allen anderen Fällen.quelle
tar
Infoseite (siehe andere Antwort) ist, dass es einen speziellen Modus dafür gibt, der vermutlich nur Dateien anzeigt, ohne sie zu öffnen. Tatsächlich habe ich nurtar cf /dev/null foo*
ein paar Dateien durchgesehen und ja, nurnewfstatat(..., AT_SYMLINK_NOFOLLOW)
Systemaufrufe, nicht einmal eineopen()
, die das Atime aktualisieren könnte. Aber +1 zur Beschreibung von Mechanismen, bei denen dies passieren kann, ohne dass dies speziell erkannt werden muss.splice(2)
unter Linux. Tatsächlich würde das Ersetzencat > /dev/null
durchpv -q > /dev/null
(dassplice()
unter Linux verwendet wird) wahrscheinlich den Overhead reduzieren. Oderdd bs=65536 skip=9999999999 2> /dev/null
, oderwc -c > /dev/null
odertail -c1 > /dev/null
...