GNU/Linux >> Znalost Linux >  >> Linux

Jak velký je Pipe Buffer?

V komentáři jsem zmatený, proč „| true“ v makefile má stejný účinek jako „|| true” uživatel cjm napsal:

Další důvod, proč se vyhnout | true spočívá v tom, že pokud by příkaz produkoval dostatek výstupu k zaplnění vyrovnávací paměti roury, zablokoval by čekání na hodnotu true, aby jej přečetl.

Máme nějaký způsob, jak zjistit, jaká je velikost vyrovnávací paměti potrubí?

Přijatá odpověď:

Kapacita vyrovnávací paměti potrubí se v různých systémech liší (a může se dokonce lišit na stejném systému). Nejsem si jistý, zda existuje rychlý, snadný a víceplatformový způsob, jak jednoduše vyhledat kapacitu potrubí.

Mac OS X například používá ve výchozím nastavení kapacitu 16384 bajtů, ale může přepnout na kapacitu 65336 bajtů, pokud se do kanálu zapisuje velký počet, nebo přepne na kapacitu jedné systémové stránky, pokud je již příliš mnoho paměti jádra. které používají vyrovnávací paměti potrubí (viz xnu/bsd/sys/pipe.h a xnu/bsd/kern/sys_pipe.c; protože jsou z FreeBSD, stejné chování může nastat i tam).

One Linux pipe(7) manuálová stránka říká, že kapacita kanálu je 65536 bajtů od Linuxu 2.6.11 a jedna systémová stránka před tím (např. 4096 bajtů na (32bitových) systémech x86). Kód (include/linux/pipe_fs_i.h a fs/pipe.c ) Zdá se, že používá 16 systémových stránek (tj. 64 kB, pokud má systémová stránka 4 kB), ale vyrovnávací paměť pro každý kanál lze upravit pomocí fcntl na rouře (až do maximální kapacity, která je výchozí 1048576 bajtů, ale lze ji změnit pomocí /proc/sys/fs/pipe-max-size )).

Tady je malá bash /perl kombinace, kterou jsem použil k testování kapacity potrubí na mém systému:

#!/bin/bash
test $# -ge 1 || { echo "usage: $0 write-size [wait-time]"; exit 1; }
test $# -ge 2 || set -- "[email protected]" 1
bytes_written=$(
{
    exec 3>&1
    {
        perl -e '
            $size = $ARGV[0];
            $block = q(a) x $size;
            $num_written = 0;
            sub report { print STDERR $num_written * $size, qq(n); }
            report; while (defined syswrite STDOUT, $block) {
                $num_written++; report;
            }
        ' "$1" 2>&3
    } | (sleep "$2"; exec 0<&-);
} | tail -1
)
printf "write size: %10d; bytes successfully before error: %dn" 
    "$1" "$bytes_written"

Zde je to, co jsem zjistil, že běží s různými velikostmi zápisu na systému Mac OS X 10.6.7 (všimněte si změny pro zápisy větší než 16 kB):

% /bin/bash -c 'for p in {0..18}; do /tmp/ts.sh $((2 ** $p)) 0.5; done'
write size:          1; bytes successfully before error: 16384
write size:          2; bytes successfully before error: 16384
write size:          4; bytes successfully before error: 16384
write size:          8; bytes successfully before error: 16384
write size:         16; bytes successfully before error: 16384
write size:         32; bytes successfully before error: 16384
write size:         64; bytes successfully before error: 16384
write size:        128; bytes successfully before error: 16384
write size:        256; bytes successfully before error: 16384
write size:        512; bytes successfully before error: 16384
write size:       1024; bytes successfully before error: 16384
write size:       2048; bytes successfully before error: 16384
write size:       4096; bytes successfully before error: 16384
write size:       8192; bytes successfully before error: 16384
write size:      16384; bytes successfully before error: 16384
write size:      32768; bytes successfully before error: 65536
write size:      65536; bytes successfully before error: 65536
write size:     131072; bytes successfully before error: 0
write size:     262144; bytes successfully before error: 0

Stejný skript v Linuxu 3.19:

/bin/bash -c 'for p in {0..18}; do /tmp/ts.sh $((2 ** $p)) 0.5; done'
write size:          1; bytes successfully before error: 65536
write size:          2; bytes successfully before error: 65536
write size:          4; bytes successfully before error: 65536
write size:          8; bytes successfully before error: 65536
write size:         16; bytes successfully before error: 65536
write size:         32; bytes successfully before error: 65536
write size:         64; bytes successfully before error: 65536
write size:        128; bytes successfully before error: 65536
write size:        256; bytes successfully before error: 65536
write size:        512; bytes successfully before error: 65536
write size:       1024; bytes successfully before error: 65536
write size:       2048; bytes successfully before error: 65536
write size:       4096; bytes successfully before error: 65536
write size:       8192; bytes successfully before error: 65536
write size:      16384; bytes successfully before error: 65536
write size:      32768; bytes successfully before error: 65536
write size:      65536; bytes successfully before error: 65536
write size:     131072; bytes successfully before error: 0
write size:     262144; bytes successfully before error: 0

Poznámka:PIPE_BUF hodnota definovaná v hlavičkových souborech C (a pathconf hodnotu pro _PC_PIPE_BUF ), nespecifikuje kapacitu rour, ale maximální počet bajtů, které lze zapsat atomicky (viz POSIX write(2) ).

Související:Linux – obrázky potrubí ffmpeg extrahované z videa?

Citace z include/linux/pipe_fs_i.h :

/* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
   memory allocation, whereas PIPE_BUF makes atomicity guarantees.  */

Linux
  1. Jak vytvořit kanál se seznamem příkazů zobrazených jako „karta dokončena“?

  2. Jak cloud zefektivňuje analýzu velkých dat

  3. Jak zapíšu stderr do souboru při použití tee s potrubím?

  1. Jak generovat náhodná čísla v prostředí BusyBox

  2. Jak zjistit velikost vyrovnávací paměti soketu linuxu

  3. Jak zkopírovat vyrovnávací paměť GNU Screen copy do schránky?

  1. Jak přenést výsledky 'najít' do mv v Linuxu

  2. Jak přenést text z příkazového řádku do schránky

  3. Jak velký by měl být swapovací oddíl?