Domanda

Ho due programmi, Writer e Reader.

Ho un FIFO da Writer a Reader, quindi quando scrivo qualcosa su stdin in Writer, viene stampato su stdout da Reader.

Ho provato a farlo con DUE lettori aperti e ho ottenuto l'output su stdout solo da uno dei due programmi Reader. Quale programma Reader da cui Unix sceglie di stampare stdout sembra arbitrario ogni volta che eseguo questo, ma una volta scelto uno dei programmi, ogni output su stdout viene stampato dallo stesso programma Reader.

Qualcuno sa perché questo accada?

Se ho due programmi WRITER, entrambi scrivono nella stessa pipe ok.

È stato utile?

Soluzione

La O in FIF O significa " out " ;. Una volta che i tuoi dati sono & Quot; out & Quot ;, sono andati. :-) Quindi, naturalmente, se arriva un altro processo e qualcun altro ha già emesso una lettura, i dati non ci saranno due volte.

Per realizzare ciò che suggerisci, devi cercare nei socket di dominio Unix. Manpage qui . È possibile scrivere un server in grado di scrivere sui processi client, associandolo a un percorso del file system. Vedi anche socket() , bind() , listen() , accept() , connect() , che ti consigliamo di utilizzare con PF_UNIX, AF_UNIX e struct sockaddr_un.

Altri suggerimenti

Linux tee () può soddisfare le tue esigenze.
vedi qui tee

NOTA: questa funzione è specifica di Linux.

Non penso che il comportamento che hai osservato sia più che casuale. Considera questa traccia, che usa "sed" come due lettori e un loop come scrittore:

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: 

Come puoi vedere, entrambi i lettori hanno potuto leggere alcuni dei dati. Quale lettore era programmato in qualsiasi momento dipendeva dal capriccio delle o / s. Nota che ho usato con cura un'eco per stampare ogni riga del file; quelle erano scritture atomiche che venivano lette atomicamente.

Se avessi usato uno script Perl con, ad esempio, un ritardo dopo la lettura e l'eco di una riga, allora avrei potuto vedere un comportamento più determinato con (generalmente) due righe da Reader 1 per ogni 1 riga da Reader 2.

perl -n -e 'while(<>){ print "1: $_"; sleep 1; }' < fifo &
perl -n -e 'while(<>){ print "2: $_"; sleep 2; }' < fifo &

Sperimentazione eseguita su MacOS X 10.5.8 (Leopard) - ma probabilmente simile in quasi tutti i luoghi.

Vorrei aggiungere alle spiegazioni di cui sopra che le scritture (e presumibili letture, anche se non sono riuscito a confermarlo dalle manpage) alle pipe sono atomiche fino a una certa dimensione (4KiB su Linux). Quindi supponiamo di iniziare con una pipe vuota e lo scrittore scrive & Lt; = 4KiB dati nella pipe. Ecco cosa penso accada:

a) Lo scrittore scrive tutti i dati in una volta sola. Mentre ciò accade, nessun altro processo ha la possibilità di leggere (o scrivere su) la pipe.

b) Uno dei lettori è programmato per eseguire l'I / O.

c) Il lettore scelto legge tutti i dati dalla pipe in una volta sola e in un secondo momento li stampa sul suo stdout.

Penso che questo possa spiegare mentre vedi l'output di solo uno dei lettori. Prova a scrivere in blocchi più piccoli e magari a dormire dopo ogni scrittura.

Naturalmente, altri hanno risposto al motivo per cui ogni dato è letto solo da un processo.

La soluzione socket funziona, ma diventa complicata in caso di crash del server. Per consentire a qualsiasi processo di essere il server, utilizzo i blocchi dei record alla fine di un file temporaneo che contiene modifiche di posizione / lunghezza / dati al file specificato. Uso una pipa denominata temporanea per comunicare le richieste di aggiunta a qualunque processo abbia il blocco in scrittura alla fine del file temporaneo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top