¿Existe un límite superior en la cantidad de datos que puede contener?¿Puede una tubería en Linux perder datos alguna vez?
Respuesta
A excepción de un bloqueo de la máquina, no, no puede perder datos. Sin embargo, es fácil usarlo mal y pensar que está perdiendo datos, ya sea porque una escritura no pudo escribir todos los datos que solicitó y no verificó el valor de retorno o porque hizo algo mal con la lectura.
La cantidad máxima de datos que puede contener depende del sistema: si intenta escribir más de eso, obtendrá una breve escritura o el escritor bloqueará hasta que haya espacio disponible. La página del manual pipe(7)
contiene mucha información útil sobre las tuberías, que incluye (al menos en Linux) qué tan grande es el búfer. Linux tiene buffers de 4K o 64K dependiendo de la versión.
edición
Tim menciona SIGPIPE, que es también un problema potencial que puede parecer a perder datos. Si el lector cierra la tubería antes de leer todo en ella, los datos no leídos se descartarán y el escritor obtendrá una señal SIGPIPE cuando escriban más o cierren la tubería, lo que indica que esto ha ocurrido. Si bloquean o ignoran el SIGPIPE, recibirán un error EPIPE. Esto cubre la situación que Pablo mencionó.
PIPE_BUF
es una constante que le dice que el límite de atomic escribe en el búfer. Cualquier escritura de este tamaño o menor tendrá éxito por completo o se bloqueará hasta que pueda tener éxito por completo (o le dará EWOULDBLOCK/EAGAIN si la tubería está en modo no bloqueante). No tiene relación con el tamaño real del buffer de tuberías del kernel, aunque obviamente el buffer debe tener al menos un tamaño PIPE_BUF para cumplir con la garantía de atomicidad.
De hecho, abandoné mi respuesta después de cargar esta. Es posible que desee mencionar SIGPIPE, http://en.wikipedia.org/wiki/SIGPIPE –
. ¿Puede haber un escenario en el que mata al escritor o al lector para que el escritor piense que está escrito algo que el lector no ha leído? –
PIPE_BUF en limits.h le dirá qué tan grande es el límite. sysconf() con _PC_PIPE_BUF puede decirle en tiempo de ejecución (en Linux de todos modos) – frankc
Si se refiere a utilizar el operador |
en el shell, entonces no, no perderá datos. Simplemente conecta la aplicación en el flujo de salida estándar del lado izquierdo a la aplicación en el flujo de entrada estándar del lado derecho. Si está canalizando datos entre aplicaciones y no obtiene los resultados que espera, intente usar >
para redirigir la salida estándar de la primera aplicación a un archivo y luego use <
para usar ese archivo como entrada estándar para la segunda aplicación. De esta forma, puede inspeccionar el archivo y asegurarse de que los datos se envíen en el formato que espera.
Si se refiere a una tubería creada por la función pipe
, entonces la respuesta sigue siendo no. De acuerdo con this man page, escribir en una tubería completa se bloqueará hasta que se hayan leído suficientes datos para dejar espacio para los datos de escritura. También establece que el tamaño de una tubería es de 4 KB en Linux anterior a 2.6.11, y de 64 KB en 2.6.11 y posterior.
La razón por la que no perderá datos es que cuando el búfer asociado con el conducto se llena, una llamada al write
se bloqueará hasta que el lector haya vaciado el búfer lo suficiente para que se complete la operación. (También puede realizar escrituras sin bloqueo, pero luego es responsable de asegurarse de completar las escrituras que se bloquearían).
Su tubería no está perdiendo datos. Si está perdiendo datos en su aplicación, intente depurarlo con gdb. Un par de cosas que debe buscar:
1) ¿Su memoria intermedia es lo suficientemente grande como para contener todos los datos que está leyendo?
2) Compruebe los códigos de retorno de su lectura() en la tubería para ver si hay errores.
3) ¿Estás seguro de que estás escribiendo todos los datos en la tubería?
4) ¿Su operación de escritura/lectura se ve interrumpida por una señal? es decir: ¿SIGPIPE?
datos se pueden perder en una tubería cuando ocurre lo siguiente:
- un proceso (el escritor) escribe n bytes de datos a la tubería, donde n≤
PIPE_BUF
. Se garantiza que esta escritura sea atómica y nunca se bloqueará. - Un proceso (el lector) solo lee m < n bytes de datos y salidas.
- El escritor no intenta volver a escribir en la tubería.
Como resultado, la memoria intermedia de la tubería del núcleo contendrá n-m bytes que se perderán cuando se hayan cerrado todos los identificadores de la tubería. El escritor no verá SIGPIPE
o EPIPE
ya que nunca intenta volver a escribir en la tubería. Dado que el escritor nunca aprenderá que la tubería contiene datos sobrantes que simplemente desaparecerán, uno puede considerar la pérdida de estos datos.
Una forma no estándar de detectar esto sería que el escritor defina un tiempo de espera y llame al FIONREAD
ioctl para determinar el número de bytes que quedan en el buffer de tubería.
¿No debería ser FIONREAD? Nota sobre Linux al menos FIONREAD indica la cantidad de datos que no se leen en el descriptor de escritura (stdout, por ejemplo), pero no parece indicar que el lector se haya ido. Me parece útil si hubiera un modo para que el núcleo envíe un SIGPIPE al escritor si el lector se fue sin leer todos los datos. – pixelbeat
Gracias, corrigió el error tipográfico. De hecho, 'FIONREAD' no indica si el lector se ha ido, de ahí la necesidad de definir un tiempo de espera. Sí, también me resultaría útil si se enviara 'SIGPIPE'. – eigengrau82
- 1. ¿Puede fallar alguna vez una instrucción COMMIT (en SQL)? ¿Cómo?
- 2. En Delphi 5, ¿puede Free alguna vez generar una excepción?
- 3. ¿Cómo incluyo una tubería? en mi linux find -exec comando?
- 4. Can/tmp en Linux alguna vez se llenan?
- 5. Python socket.send() solo puede enviar una vez, luego socket.error: [Errno 32] Se produjo una tubería rota
- 6. Puede Object.GetType() alguna vez devolver nulo?
- 7. ¿Cómo puede (1 +) ser alguna vez una función?
- 8. C# - ¿Dividir en una tubería con una tubería escapada en los datos?
- 9. Hay una tarea ant que puede copiar sin perder permisos
- 10. ¿Por qué alguna vez usaría una DoublyLinkedList en PHP?
- 11. ¿Se puede leer kdb desde una tubería con nombre?
- 12. ¿Cómo ver cuántos datos están en cola en una tubería con nombre?
- 13. PHP ¿Puede un cliente establecer alguna vez las variables $ _SESSION?
- 14. marcos para representar el procesamiento de datos como una tubería
- 15. ¿Por qué alguna vez scrollTop/scrollLeft no se puede escribir?
- 16. tubería uso de datos enrollamiento
- 17. ¿Es necesario > alguna vez?
- 18. Multiprocesamiento en una tubería hecho bien
- 19. Cómo desinstalar Android apk sin perder datos?
- 20. Tubería de datos al programa Linux que espera un TTY (terminal)
- 21. ¿Cómo escribir datos con FileOutputStream sin perder los datos antiguos?
- 22. ¿puede encontrar todos los autores que alguna vez han cambiado una línea de código?
- 23. Leer datos sin búfer de la tubería en Perl
- 24. imágenes que empujan en una tubería GStreamer
- 25. ¿Por qué alguna vez elegiría almacenar y manipular XML en una base de datos relacional?
- 26. ¿Puede escribir en un socket de datagrama alguna vez subir SIGPIPE?
- 27. ¿Se desborda BigInteger alguna vez?
- 28. ¿Alguna vez ha usado ngen.exe?
- 29. ¿Alguna vez el controlador se ejecuta más de una vez en Jmeter?
- 30. django: actualizar esquema de base de datos sin perder datos
es perder no suelto. suelto es un diente flojo –
@intuited: mala delimiter ")" (falta el paréntesis abierto) – sleblanc
hecho mi día, 4 caracteres más van :) – Aftnix