Місткість буферної труби змінюється в різних системах (і може змінюватися навіть в одній системі). Я не впевнений, що існує швидкий, простий і перехресний платформний спосіб просто знайти ємність труби.
Наприклад, Mac OS X використовує ємність 16384 байт за замовчуванням, але може переключитися на 65336 байт ємності, якщо велике записування буде зроблено в трубу, або перейде на ємність однієї системної сторінки, якщо вже занадто багато пам'яті ядра використовуються буферними трубами (див. xnu/bsd/sys/pipe.h
, і xnu/bsd/kern/sys_pipe.c
оскільки вони є з FreeBSD, така ж поведінка може відбуватися і там).
На одній підручній сторінці Linux (7) написано, що ємність трубопроводу становить 65536 байт з моменту Linux 2.6.11, а до цього - одна системна сторінка (наприклад, 4096 байт у 32-бітних системах x86). Здається, що в коді ( include/linux/pipe_fs_i.h
і fs/pipe.c
) використовується 16 системних сторінок (тобто 64 KiB, якщо на системній сторінці 4 KiB), але буфер для кожної труби може бути відрегульований за допомогою fcntl на трубі (до максимальної потужності, яка за замовчуванням становить 1048576 байтів, але їх можна змінити через /proc/sys/fs/pipe-max-size
)).
Ось невелика комбінація bash / perl, яку я використовував для перевірки ємності труби у своїй системі:
#!/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"
Ось що я виявив, що він працює з різними розмірами запису в системі Mac OS X 10.6.7 (зверніть увагу на зміну для записів, більших за 16 Кбіт):
% /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
Той самий сценарій на 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
Примітка. PIPE_BUF
Значення, визначене у файлах заголовка C (та значення pathconf для _PC_PIPE_BUF
), не визначає ємність труб, а максимальну кількість байтів, які можна записати атомно (див. POSIX write (2) ).
Цитата від 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. */