Saltar al contenido

¿Qué tan grande es el tope de la tubería?

Te recomendamos que revises esta resolución en un entorno controlado antes de enviarlo a producción, saludos.

Solución:

La capacidad de un amortiguador de tuberías varía según los sistemas (e incluso puede variar en el mismo sistema). No estoy seguro de que haya una forma rápida, fácil y multiplataforma de buscar la capacidad de una tubería.

Mac OS X, por ejemplo, utiliza una capacidad de 16384 bytes de forma predeterminada, pero puede cambiar a capacidades de 65336 bytes si se realizan grandes escrituras en la canalización, o cambiará a una capacidad de una sola página del sistema si ya hay demasiada memoria del kernel. siendo utilizado por amortiguadores de tubería (ver xnu/bsd/sys/pipe.hy xnu/bsd/kern/sys_pipe.c; dado que estos son de FreeBSD, el mismo comportamiento también puede ocurrir allí).

un linux pipa(7) La página de manual dice que la capacidad de la tubería es de 65536 bytes desde Linux 2.6.11 y una sola página del sistema antes de eso (por ejemplo, 4096 bytes en sistemas x86 (32 bits)). El código (include/linux/pipe_fs_i.hy fs/pipe.c) parece usar 16 páginas del sistema (es decir, 64 KiB si una página del sistema es de 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 de 1048576 bytes, pero se puede cambiar a través de /proc/sys/fs/pipe-max-size)).


aquí hay un poco intento/perlas combinación que usé 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 -- "[email protected]" 1
bytes_written=$(
 (sleep "$2"; exec 0<&-);
 | tail -1
)
printf "write size: %10d; bytes successfully before error: %dn" 
    "$1" "$bytes_written"

Esto es lo que encontré al ejecutarlo 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 KiB):

% /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 la PIPE_BUF valor definido en los archivos de encabezado C (y el rutaconf valor por _PC_PIPE_BUF), no especifica la capacidad de las tuberías, sino el número máximo de bytes que se pueden escribir atómicamente (ver POSIX escribir(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.  */

esta línea de shell también puede mostrar el tamaño del búfer de la tubería:

M=0; while true; do dd if=/dev/zero bs=1k count=1 2>/dev/null; 
       M=$(($M+1)); echo -en "r$M KB" 1>&2; done | sleep 999

(enviando 1k fragmentos a la tubería bloqueada hasta que el búfer esté lleno) ... algunas salidas de prueba:

64K (intel-debian), 32K (aix-ppc), 64K (jslinux bellard.org)      ...Ctrl+C.

bash-one-liner más corto usando printf:

M=0; while printf A; do >&2 printf "r$((++M)) B"; done | sleep 999

Aquí hay algunas alternativas adicionales para explorar la capacidad real del búfer de tubería usando solo comandos de shell:

# get pipe buffer size using Bash
yes produce_this_string_as_output | tee >(sleep 1) | wc -c

# portable version
( (sleep 1; exec yes produce_this_string_as_output) & echo $! ) | 
     (pid=$(head -1); sleep 2; kill "$pid"; wc -c 

Reseñas y calificaciones del tutorial

Tienes la opción de añadir valor a nuestra información aportando tu veteranía en las interpretaciones.

¡Haz clic para puntuar esta entrada!
(Votos: 2 Promedio: 5)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *