GNU/Linux >> Znalost Linux >  >> Linux

Bude mít printf stále cenu, i když přesměruji výstup do /dev/null?

Docela.

Když přesměrujete stdout programu na /dev/null , jakékoli volání printf(3) stále vyhodnotí všechny argumenty a proces formátování řetězce bude stále probíhat před voláním write(2) , který zapíše celý formátovaný řetězec na standardní výstup procesu. Na úrovni jádra se data nezapisují na disk, ale zahazují je handler spojený se speciálním zařízením /dev/null .

Takže v nejlepším případě neobejdete ani se nevyhnete režii vyhodnocování argumentů a jejich předávání printf , úloha formátování řetězce za printf a alespoň jedno systémové volání, které skutečně zapíše data, pouhým přesměrováním stdout na /dev/null . No, to je skutečný rozdíl na Linuxu. Implementace pouze vrací počet bajtů, které jste chtěli zapsat (určeno 3. argumentem vašeho volání write(2) ) a ignoruje vše ostatní (viz tato odpověď). V závislosti na množství dat, která zapisujete, a rychlosti cílového zařízení (disku nebo terminálu) se může rozdíl ve výkonu hodně lišit. Na vestavěných systémech, obecně řečeno, přerušení zápisu na disk přesměrováním na /dev/null může ušetřit docela dost systémových prostředků za netriviální množství zapsaných dat.

Ačkoli teoreticky mohl program detekovat /dev/null a provádějí některé optimalizace v rámci omezení standardů, kterým vyhovují (ISO C a POSIX), na základě obecné znalosti běžných implementací prakticky nedělají (tj. nevím o žádném unixovém nebo linuxovém systému, který by to dělal).

Standard POSIX nařizuje zápis na standardní výstup pro jakékoli volání printf(3) , takže není v souladu se standardy potlačovat volání write(2) v závislosti na přidružených deskriptorech souborů. Pro více podrobností o požadavcích POSIX si můžete přečíst Damonovu odpověď. Jo a ještě krátká poznámka:Všechny linuxové distribuce jsou prakticky kompatibilní s POSIX, přestože nejsou certifikovány aby to tak bylo.

Uvědomte si, že pokud nahradíte printf zcela, některé vedlejší účinky se mohou pokazit, například printf("%d%n", a++, &b) . Pokud opravdu potřebujete potlačit výstup v závislosti na prostředí spouštění programu, zvažte nastavení globálního příznaku a zabalte printf, abyste příznak před tiskem zkontrolovali – nezpomalí to program do takové míry, že by byla viditelná ztráta výkonu. , protože kontrola jedné podmínky je hodně rychlejší než volání printf a provede veškeré formátování řetězců.


printf funkce bude zapisovat na stdout . Není v souladu s optimalizací pro /dev/null .Proto budete mít režii na analýzu formátovacího řetězce a vyhodnocení všech nezbytných argumentů a budete mít alespoň jedno systémové volání a navíc zkopírujete vyrovnávací paměť do adresového prostoru jádra (což je ve srovnání s náklady na systémové volání zanedbatelné ).

Tato odpověď je založena na konkrétní dokumentaci POSIX.

Systémová rozhraní
dprintf, fprintf, printf, snprintf, sprintf - tiskový formátovaný výstup

Funkce fprintf() umístí výstup do pojmenovaného výstupního proudu. Funkce printf() umístí výstup na standardní výstupní proud stdout. Funkce sprintf() umístí výstup následovaný prázdným bytem '\0' do po sobě jdoucích bajtů začínajících na *s; je odpovědností uživatele zajistit dostatek místa.

Definice základny
musí
Pro implementaci, která je v souladu s POSIX.1-2017, popisuje funkci nebo chování, které je povinné. Aplikace se může spolehnout na existenci funkce nebo chování.


Linux
  1. Jak Linux zpracovává více po sobě jdoucích oddělovačů cest (/home////username///soubor)?

  2. Jak přenosné jsou /dev/stdin, /dev/stdout a /dev/stderr?

  3. Kdy použít /dev/random vs /dev/urandom?

  1. Jak úplně umlčet Cronjob do /dev/null/?

  2. Co jsou soubory /dev/zero a /dev/null v Linuxu

  3. Jak přesměrovat výstup aplikace na pozadí do /dev/null

  1. Přesměrujte stderr na /dev/null

  2. Přesměrování stdout za běhu procesu -- Co tento proces odesílá do /dev/null

  3. echo nebo print /dev/stdin /dev/stdout /dev/stderr