A capacidade de um buffer de tubulação varia entre os sistemas (e pode até variar no mesmo sistema). Não tenho certeza se existe uma maneira rápida, fácil e de plataforma cruzada de apenas pesquisar a capacidade de um cano.
O Mac OS X, por exemplo, usa uma capacidade de 16384 bytes por padrão, mas pode alternar para capacidades de 65336 bytes se grandes gravações forem feitas no canal, ou alternará para uma capacidade de uma única página do sistema se houver muito kernel a memória já está sendo usada por buffers de pipe (consulte xnu/bsd/sys/pipe.h
e xnu/bsd/kern/sys_pipe.c
; estes são do FreeBSD, o mesmo comportamento pode acontecer lá também.
Uma canal (>) diz que a capacidade do canal é 65536 bytes desde o Linux 2.6.11 e uma única página do sistema antes disso (por exemplo, 4096 bytes em sistemas x86 de 32 bits). O código ( include/linux/pipe_fs_i.h
e fs/pipe.c
) parece usar 16 páginas do sistema (isto é, 64 KiB se uma página do sistema for 4 KiB), mas o buffer para cada pipe pode ser ajustado através de um fcntl no pipe (até uma capacidade máxima que padrão é 1048576 bytes, mas pode ser alterada via /proc/sys/fs/pipe-max-size
)).
Aqui está uma pequena combinação bash / perl que usei para testar a capacidade do pipe no meu 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"
Aqui está o que eu encontrei executando com vários tamanhos de gravação em um sistema Mac OS X 10.6.7 (observe a mudança para gravações maiores que 16KiB):
% /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
O mesmo script no 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: O valor PIPE_BUF
definido nos arquivos de cabeçalho C (e o valor pathconf para _PC_PIPE_BUF
), não especifica a capacidade dos canais, mas o número máximo de bytes que podem ser escrito atomicamente (veja POSIX escreva (2) ) .
Cite 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. */