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