unix - named pipes c#
Canalizaciones con nombre(FIFO) en Unix con mĂșltiples lectores (4)
Tengo dos programas, Writer y Reader.
Tengo un FIFO de Writer a Reader, así que cuando escribo algo para stdin en Writer, se imprime en stdout desde Reader.
Intenté hacer esto con TWO Readers abierto, y recibí salida a stdout de solo uno de los dos programas de Reader. El programa Reader que Unix elige para imprimir stdout parece ser arbitrario cada vez que lo ejecuto, pero una vez que elige uno de los programas, cada salida a stdout se imprime desde el mismo programa Reader.
¿Alguien sabe por qué pasa esto?
Si tengo dos programas de ESCRITOR, ambos escriben bien en la misma tubería.
El O en FIFO significa "fuera". Una vez que tus datos están "fuera", desaparecen. :-) Así que, naturalmente, si llega otro proceso y alguien más ya ha emitido una lectura, los datos no estarán allí dos veces.
Para lograr lo que sugiere, debe buscar en los sockets de dominio de Unix. Manpage here . Puede escribir un servidor que pueda escribir en los procesos del cliente, vinculando a una ruta del sistema de archivos. Vea también socket()
, bind()
, listen()
, accept()
, connect()
, todo lo cual querrá usar con PF_UNIX
, AF_UNIX
, y struct sockaddr_un
.
Linux tee () puede adaptarse a sus necesidades.
ver aquí tee
NOTA: esta función es específica de Linux.
Me gustaría agregar a las explicaciones anteriores que las escrituras (y lecturas presumibles, aunque no pude confirmar esto desde las páginas de manual) a las tuberías son atómicas hasta un cierto tamaño (4 KB en Linux). Supongamos que comenzamos con una tubería vacía y el escritor escribe <= 4KiB datos en la tubería. Esto es lo que creo que sucede:
a) El escritor escribe todos los datos de una vez. Mientras esto sucede, ningún otro proceso tiene la posibilidad de leer (o escribir) la tubería.
b) Uno de los lectores está programado para hacer su E / S.
c) El lector elegido lee todos los datos de la tubería de una sola vez, y en algún momento posterior los imprime en su salida estándar.
Creo que esto podría explicarlo mientras ve resultados de solo uno de los lectores. Intenta escribir en trozos más pequeños, y quizás duerma después de cada escritura.
Por supuesto, otros han respondido por qué cada dato se lee solo por proceso.
No creo que el comportamiento que observaste sea más que una coincidencia. Considere este rastro, que usa ''sed'' como los dos lectores y un bucle como el escritor:
Osiris JL: mkdir fifo
Osiris JL: cd fifo
Osiris JL: mkfifo fifo
Osiris JL: sed ''s/^/1: /'' < fifo &
[1] 4235
Osiris JL: sed ''s/^/2: /'' < fifo &
[2] 4237
Osiris JL: while read line ; do echo $line; done > fifo < /etc/passwd
1: ##
1: # User Database
1: #
1: # Note that this file is consulted directly only when the system is running
1: # in single-user mode. At other times this information is provided by
1: # Open Directory.
1: #
1: # This file will not be consulted for authentication unless the BSD local node
1: # is enabled via /Applications/Utilities/Directory Utility.app
1: #
1: # See the DirectoryService(8) man page for additional information about
1: # Open Directory.
1: ##
1: nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
1: root:*:0:0:System Administrator:/var/root:/bin/sh
1: daemon:*:1:1:System Services:/var/root:/usr/bin/false
1: _uucp:*:4:4:Unix to Unix Copy Protocol:/var/spool/uucp:/usr/sbin/uucico
1: _lp:*:26:26:Printing Services:/var/spool/cups:/usr/bin/false
2: _postfix:*:27:27:Postfix Mail Server:/var/spool/postfix:/usr/bin/false
2: _mcxalr:*:54:54:MCX AppLaunch:/var/empty:/usr/bin/false
2: _pcastagent:*:55:55:Podcast Producer Agent:/var/pcast/agent:/usr/bin/false
2: _pcastserver:*:56:56:Podcast Producer Server:/var/pcast/server:/usr/bin/false
2: _serialnumberd:*:58:58:Serial Number Daemon:/var/empty:/usr/bin/false
2: _devdocs:*:59:59:Developer Documentation:/var/empty:/usr/bin/false
2: _sandbox:*:60:60:Seatbelt:/var/empty:/usr/bin/false
2: _mdnsresponder:*:65:65:mDNSResponder:/var/empty:/usr/bin/false
2: _ard:*:67:67:Apple Remote Desktop:/var/empty:/usr/bin/false
2: _www:*:70:70:World Wide Web Server:/Library/WebServer:/usr/bin/false
2: _eppc:*:71:71:Apple Events User:/var/empty:/usr/bin/false
2: _cvs:*:72:72:CVS Server:/var/empty:/usr/bin/false
2: _svn:*:73:73:SVN Server:/var/empty:/usr/bin/false
2: _mysql:*:74:74:MySQL Server:/var/empty:/usr/bin/false
2: _sshd:*:75:75:sshd Privilege separation:/var/empty:/usr/bin/false
2: _qtss:*:76:76:QuickTime Streaming Server:/var/empty:/usr/bin/false
2: _cyrus:*:77:6:Cyrus Administrator:/var/imap:/usr/bin/false
2: _mailman:*:78:78:Mailman List Server:/var/empty:/usr/bin/false
2: _appserver:*:79:79:Application Server:/var/empty:/usr/bin/false
2: _clamav:*:82:82:ClamAV Daemon:/var/virusmails:/usr/bin/false
2: _amavisd:*:83:83:AMaViS Daemon:/var/virusmails:/usr/bin/false
2: _jabber:*:84:84:Jabber XMPP Server:/var/empty:/usr/bin/false
2: _xgridcontroller:*:85:85:Xgrid Controller:/var/xgrid/controller:/usr/bin/false
2: _xgridagent:*:86:86:Xgrid Agent:/var/xgrid/agent:/usr/bin/false
2: _appowner:*:87:87:Application Owner:/var/empty:/usr/bin/false
2: _windowserver:*:88:88:WindowServer:/var/empty:/usr/bin/false
2: _spotlight:*:89:89:Spotlight:/var/empty:/usr/bin/false
2: _tokend:*:91:91:Token Daemon:/var/empty:/usr/bin/false
2: _securityagent:*:92:92:SecurityAgent:/var/empty:/usr/bin/false
2: _calendar:*:93:93:Calendar:/var/empty:/usr/bin/false
2: _teamsserver:*:94:94:TeamsServer:/var/teamsserver:/usr/bin/false
2: _update_sharing:*:95:-2:Update Sharing:/var/empty:/usr/bin/false
2: _installer:*:96:-2:Installer:/var/empty:/usr/bin/false
2: _atsserver:*:97:97:ATS Server:/var/empty:/usr/bin/false
2: _unknown:*:99:99:Unknown User:/var/empty:/usr/bin/false
Osiris JL: jobs
[1]- Running sed ''s/^/1: /'' < fifo &
[2]+ Done sed ''s/^/2: /'' < fifo
Osiris JL: echo > fifo
1:
Osiris JL: jobs
[1]+ Done sed ''s/^/1: /'' < fifo
Osiris JL:
Como puede ver, ambos lectores tuvieron que leer algunos de los datos. El lector que se programó en cualquier momento dependía del capricho de la o / s. Tenga en cuenta que utilicé cuidadosamente un eco para imprimir cada línea del archivo; esas fueron escrituras atómicas que fueron leídas atómicamente.
Si hubiera usado un script Perl con, por ejemplo, un retraso después de leer y hacer eco de una línea, entonces bien podría haber visto un comportamiento más determinado con (generalmente) dos líneas del Reader 1 por cada 1 línea del Reader 2.
perl -n -e ''while(<>){ print "1: $_"; sleep 1; }'' < fifo &
perl -n -e ''while(<>){ print "2: $_"; sleep 2; }'' < fifo &
Experimentación realizada en MacOS X 10.5.8 (Leopard): pero es probable que sea similar en la mayoría de los lugares.