La capacidad de un buffer de tubería varía entre sistemas (e incluso puede variar en el mismo sistema). No estoy seguro de que haya una manera rápida, fácil y multiplataforma para buscar la capacidad de una tubería.
Mac OS X, por ejemplo, usa una capacidad de 16384 bytes de manera predeterminada, pero puede cambiar a capacidades de 65336 bytes si se realiza una gran escritura en la tubería, o cambiará a una capacidad de una sola página del sistema si ya hay demasiada memoria del núcleo siendo utilizado por los buffers de tubería (ver xnu/bsd/sys/pipe.h
, y xnu/bsd/kern/sys_pipe.c
; dado que estos son de FreeBSD, el mismo comportamiento también puede ocurrir allí).
Una página del comando man Linux pipe (7) dice que la capacidad de la tubería es 65536 bytes desde Linux 2.6.11 y una sola página del sistema anterior (por ejemplo, 4096 bytes en sistemas x86 (32 bits)). El código ( include/linux/pipe_fs_i.h
y fs/pipe.c
) parece usar 16 páginas del sistema (es decir, 64 KiB si una página del sistema es 4 KiB), pero el búfer para cada tubería se puede ajustar a través de un fcntl en la tubería (hasta una capacidad máxima que por defecto es 1048576 bytes, pero se puede cambiar a través de /proc/sys/fs/pipe-max-size
)).
Aquí hay una pequeña combinación bash / perl que utilicé para probar la capacidad de la tubería en mi 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"
Esto es lo que encontré ejecutándolo con varios tamaños de escritura en un sistema Mac OS X 10.6.7 (tenga en cuenta el cambio para escrituras de más de 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
El mismo script en 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: El PIPE_BUF
valor definido en los archivos de encabezado C (y el valor de pathconf para _PC_PIPE_BUF
) no especifica la capacidad de las canalizaciones, sino el número máximo de bytes que pueden escribirse atómicamente (consulte POSIX write (2) ).
Cita 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. */