La capacità di un buffer di tubi varia tra i sistemi (e può anche variare sullo stesso sistema). Non sono sicuro che esista un modo rapido, semplice e multipiattaforma per cercare la capacità di un tubo.
Mac OS X, ad esempio, utilizza una capacità di 16384 byte per impostazione predefinita, ma può passare a capacità 65336 byte se viene effettuata una scrittura di grandi dimensioni sulla pipe o passerà a una capacità di una singola pagina di sistema se è già presente troppa memoria del kernel usato dai buffer delle pipe (vedi xnu/bsd/sys/pipe.h
, e xnu/bsd/kern/sys_pipe.c
poiché questi sono di FreeBSD, lo stesso comportamento può accadere anche lì).
Una pagina man di pipe Linux (7) dice che la capacità di pipe è 65536 byte a partire da Linux 2.6.11 e una singola pagina di sistema precedente (ad esempio 4096 byte su sistemi x86 (32 bit)). Il codice ( include/linux/pipe_fs_i.h
, e fs/pipe.c
) sembra utilizzare 16 pagine di sistema (ovvero 64 KiB se una pagina di sistema è 4 KiB), ma il buffer per ogni pipe può essere regolato tramite un fcntl sulla pipe (fino a una capacità massima che viene impostata automaticamente su 1048576 byte, ma può essere modificato tramite /proc/sys/fs/pipe-max-size
)).
Ecco una piccola combinazione bash / perl che ho usato per testare la capacità del tubo sul mio sistema:
#!/bin/bash
test $# -ge 1 || { echo "usage: $0 write-size [wait-time]"; exit 1; }
test $# -ge 2 || set -- "$@" 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: %d\n" \
"$1" "$bytes_written"
Ecco cosa ho trovato eseguendolo con varie dimensioni di scrittura su un sistema Mac OS X 10.6.7 (nota la modifica per scritture di dimensioni superiori a 16 KiB):
% /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
Lo stesso script su Linux 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
Nota: il PIPE_BUF
valore definito nei file di intestazione C (e il valore pathconf per _PC_PIPE_BUF
), non specifica la capacità delle pipe, ma il numero massimo di byte che possono essere scritti atomicamente (vedere POSIX write (2) ).
Citazione da 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. */