2011-06-27 18 views
10

¿Hay alguna manera de crear un canal con nombre no bloqueante/asíncrono o algo similar en shell? Para que los programas pudieran colocar líneas en él, esas líneas se mantendrían en RAM, y cuando algún programa pudiera leer algunas líneas de la tubería, mientras dejaba lo que no leía en fifo. También es muy probable que los programas puedan escribir y leer en esta fifo al mismo tiempo. Al principio pensé que tal vez esto podría hacerse usando archivos, pero después de buscar en la web por un momento parece que nada bueno puede venir del hecho de que el archivo se lee y escribe al mismo tiempo. Las tuberías con nombre casi funcionarían, solo hay dos problemas: primero bloquean las lecturas/escrituras si no hay nadie en el otro extremo, las segundas incluso si dejo que la escritura se bloquee y configuran dos procesos para escribir en la tubería mientras nadie está leyendo, tratando de escribir una línea con cada proceso, y luego intente con head -n 1 <fifo> obtengo solo una línea cuando lo necesito, pero ambos procesos de escritura terminan y la segunda línea se pierde. ¿Alguna sugerencia?fifo/named pipe no bloqueante/asincrónico en shell/filesystem?

Editar: quizá algún programa intermedia podría ser utilizado para ayudar con esto, actuando como mediador entre escritores y lectores?

+2

Se podría hacer algo como 'mkfs/dev/ram1 1048576' (o un número más grande si quieres) y montaje'/dev/ram1' en cualquier lugar a continuación. Probablemente sea lo más cercano a "no bloqueo" que pueda obtener. Por supuesto, por defecto no será para nada bloqueante, solo muy rápido (pero una tubería con nombre tampoco será, por defecto). La operación sin bloqueo es algo que un programa necesita establecer en el descriptor del archivo. – Damon

+0

Pensé en esta opción, crear archivos en tmpfs o similares, pero de nuevo persiste el problema de escribir y leer al mismo tiempo. Más como escribir y escribir desde su archivo. Un programa escribe al final del archivo, otro ha leído alguna información desde el inicio y ahora necesita eliminar las primeras líneas, por lo que al escribir al final y eliminar al frente al mismo tiempo, no pude encontrar una solución a esto, lo habría usado esta. – morphles

+1

Es difícil (si no imposible) hacer tal cosa sin escribir un programa. Algo que casi podría funcionar: Renombrar es atómico, por lo que uno podría hacer que cada productor escriba cada tarea por separado en un archivo temporal individual, cerrar el archivo y cambiarle el nombre de acuerdo con algún patrón "conocido". Cada consumidor podría cambiar el nombre del siguiente archivo a algo aleatorio (para que otro consumidor no lo recoja), leer el contenido y eliminar el archivo. Aunque eso solo funcionaría en un nivel por tarea (independientemente de lo que los productores escriban como una unidad), no en un nivel por línea. – Damon

Respuesta

5

Puede utilizar el programa especial para este propósito - búfer. Buffer está diseñado para tratar de mantener el lado del escritor continuamente ocupado para que pueda transmitir al escribir en unidades de cinta, pero puede usarlo para otros fines. El búfer interno es un par de procesos que se comunican a través de una gran cola circular almacenada en la memoria compartida, por lo que sus procesos funcionarán de forma asíncrona. El proceso de lectura se bloqueará en caso de que la cola esté llena y el proceso de escritura, en caso de que la cola esté vacía. Ejemplo:

bzcat archive.bz2 | buffer -m 16000000 -b 100000 | processing_script | bzip2> archive_processed.bz2

http://linux.die.net/man/1/buffer

+0

Gracias por señalar el programa que no sabía, parece interesante y podría ser útil en algunos casos. Aunque no es exactamente lo que quería y no podré hacer lo que quiero con esto, he decidido que lo más probable es que implemente mi propio programa/daemon para casos como el mío. – morphles

+0

Otra solución sería usar Queeon Daemon, algo así como Gearman. Sus "líneas" podrían persistir en Memcache como trabajos. –