Pojemność bufora potoku różni się w zależności od systemu (i może nawet różnić się w tym samym systemie). Nie jestem pewien, czy istnieje szybki, łatwy i wieloplatformowy sposób, aby po prostu sprawdzić pojemność rury.
Na przykład Mac OS X domyślnie wykorzystuje pojemność 16384 bajtów, ale może przełączyć się na pojemność 65336 bajtów, jeśli do potoku wprowadzono duży zapis, lub przełączy się na pojemność pojedynczej strony systemowej, jeśli już jest za dużo pamięci jądra używane przez bufory potokowe (patrz xnu/bsd/sys/pipe.h
i xnu/bsd/kern/sys_pipe.c
; ponieważ pochodzą one z FreeBSD, to samo może się tam zdarzyć).
Jedna strona podręcznika systemowego potoku Linux (7) mówi, że pojemność potoku wynosi 65536 bajtów od Linuksa 2.6.11, a wcześniej jedna strona systemowa (np. 4096 bajtów w systemach (32-bitowych) x86). Wydaje się, że kod ( include/linux/pipe_fs_i.h
i fs/pipe.c
) używa 16 stron systemowych (tj. 64 KiB, jeśli strona systemowa ma 4 KiB), ale bufor dla każdej potoki można regulować za pomocą fcntl na potoku (do maksymalnej pojemności, która domyślnie wynosi 1048576 bajtów, ale można je zmienić za pomocą /proc/sys/fs/pipe-max-size
)).
Oto mała kombinacja bash / perl , której użyłem do przetestowania pojemności rur w moim systemie:
#!/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"
Oto, co znalazłem, uruchamiając go z różnymi rozmiarami zapisu w systemie Mac OS X 10.6.7 (zwróć uwagę na zmianę zapisu większą niż 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
Ten sam skrypt w systemie 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
Uwaga: PIPE_BUF
Wartość zdefiniowana w plikach nagłówka C (i wartość pathconf dla _PC_PIPE_BUF
) nie określa pojemności potoków, ale maksymalną liczbę bajtów, które można zapisać atomowo (patrz zapis POSIX (2) ).
Cytat 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. */