GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Wird printf auch dann noch Kosten verursachen, wenn ich die Ausgabe nach /dev/null umleite?

So ziemlich.

Wenn Sie die Standardausgabe des Programms auf /dev/null umleiten , jeder Aufruf von printf(3) wertet weiterhin alle Argumente aus, und der Zeichenfolgenformatierungsprozess findet weiterhin statt, bevor write(2) aufgerufen wird , wodurch die vollständig formatierte Zeichenfolge in die Standardausgabe des Prozesses geschrieben wird. Auf der Kernel-Ebene werden die Daten nicht auf die Festplatte geschrieben, sondern vom Handler verworfen, der dem speziellen Gerät /dev/null zugeordnet ist .

Im besten Fall umgehen oder vermeiden Sie also den Overhead, die Argumente auszuwerten und an printf zu übergeben , der Zeichenfolgenformatierungsjob hinter printf , und mindestens einen Systemaufruf, um die Daten tatsächlich zu schreiben, indem stdout einfach auf /dev/null umgeleitet wird . Nun, das ist ein echter Unterschied zu Linux. Die Implementierung gibt nur die Anzahl der Bytes zurück, die Sie schreiben wollten (angegeben durch das dritte Argument Ihres Aufrufs von write(2) ) und ignoriert alles andere (siehe diese Antwort). Abhängig von der zu schreibenden Datenmenge und der Geschwindigkeit des Zielgeräts (Festplatte oder Terminal) kann der Leistungsunterschied stark variieren. Auf eingebetteten Systemen wird im Allgemeinen das Schreiben auf die Festplatte unterbrochen, indem auf /dev/null umgeleitet wird kann einige Systemressourcen für eine nicht triviale Menge an geschriebenen Daten einsparen.

Obwohl das Programm theoretisch /dev/null erkennen könnte und einige Optimierungen innerhalb der Einschränkungen der Standards durchführen, denen sie entsprechen (ISO C und POSIX), basierend auf dem allgemeinen Verständnis gängiger Implementierungen, tun sie dies praktisch nicht (dh mir ist kein Unix- oder Linux-System bekannt, das dies tut).

Der POSIX-Standard verlangt, dass bei jedem Aufruf von printf(3) in die Standardausgabe geschrieben wird , daher ist es nicht standardkonform, den Aufruf von write(2) zu unterdrücken abhängig von den zugehörigen Dateideskriptoren. Weitere Einzelheiten zu den POSIX-Anforderungen finden Sie in Damons Antwort. Oh, und eine kurze Anmerkung:Alle Linux-Distributionen sind praktisch POSIX-konform, obwohl sie nicht zertifiziert sind so sein.

Beachten Sie das, wenn Sie printf ersetzen vollständig, einige Nebenwirkungen können schief gehen, zum Beispiel printf("%d%n", a++, &b) . Wenn Sie die Ausgabe abhängig von der Programmausführungsumgebung wirklich unterdrücken müssen, ziehen Sie in Betracht, ein globales Flag zu setzen und printf zu beenden, um das Flag vor dem Drucken zu überprüfen – es wird das Programm nicht in einem Ausmaß verlangsamen, in dem der Leistungsverlust sichtbar ist , da eine einzelne Bedingungsprüfung viel ist schneller als printf anzurufen und die gesamte Zeichenfolgenformatierung durchführen.


Die printf Funktion wird schreiben Sie an stdout . Es entspricht nicht der Optimierung für /dev/null .Daher haben Sie den Aufwand, den Formatstring zu parsen und alle notwendigen Argumente auszuwerten, und Sie haben mindestens einen Systemaufruf, außerdem kopieren Sie einen Puffer in den Kernel-Adressraum (was im Vergleich zu den Kosten des Systemaufrufs vernachlässigbar ist). ).

Diese Antwort basiert auf der spezifischen Dokumentation von POSIX.

Systemschnittstellen
dprintf, fprintf, printf, snprintf, sprintf - formatierte Ausgabe drucken

Die Funktion fprintf() soll die Ausgabe auf dem benannten Ausgabestrom platzieren. Die Funktion printf() soll die Ausgabe auf dem Standardausgabestrom stdout platzieren. Die sprintf()-Funktion platziert die Ausgabe gefolgt vom Null-Byte, '\0', in aufeinanderfolgenden Bytes, beginnend bei *s; Es liegt in der Verantwortung des Benutzers sicherzustellen, dass genügend Speicherplatz vorhanden ist.

Basisdefinitionen
soll
Beschreibt für eine Implementierung, die POSIX.1-2017 entspricht, eine Funktion oder ein Verhalten, das obligatorisch ist. Eine Anwendung kann sich auf die Existenz der Funktion oder des Verhaltens verlassen.


Linux
  1. Wie behandelt Linux mehrere aufeinanderfolgende Pfadtrennzeichen (/home////username///file)?

  2. Wie portabel sind /dev/stdin, /dev/stdout und /dev/stderr?

  3. Möglichkeit, die Ausgabe eines Programms umzuleiten und trotzdem nach Stdout zu gehen?

  4. Was sind /dev/zero- und /dev/null-Dateien in Linux

  5. Leite stderr nach /dev/null um

Was ist „/dev/null 2&1“ unter Linux

So leiten Sie die Ausgabe unter Linux nach /dev/null um

Was ist /dev/null unter Linux

DD von /dev/zero nach /dev/null ... was eigentlich passiert

echo oder print /dev/stdin /dev/stdout /dev/stderr

Warum sind < oder > erforderlich, um /dev/tcp