2009-04-03 4 views
8

Ho due processi separati: un programma C che emette valori separati da virgola seguiti da una nuova riga ogni secondo e un programma Perl che accetta i dati (nello stesso formato) e li elabora.Come consentire a due processi concorrenti di comunicare?

Le uscite di programma C (via printf) valori come tale:

1, 2, 3, 4, 5, 6 
7, 8, 9, 10, 11, 12 
... 

Il programma Perl si trova in un ciclo infinito attesa con il metodo per STDIN per elaborare questi dati:

while ($line = <STDIN>) 
{ 
    chomp($line) # Line should now read "1,2,3,4,5,6" 
    # Process data 
} 

Voglio che questi due processi comunichino in tempo reale. Le pipe bash standard non funzionano (ad esempio process1 | process2) perché il programma Perl attende che il primo programma finisca prima di elaborare l'input.

Qualcuno ha idee, suggerimenti o informazioni su una soluzione a questo problema? Grazie in anticipo!

+0

in senso stretto, questo non ha nulla a che fare con "tempo reale" – andersoj

+0

Hai assolutamente ragione, ho scritto questo in fretta e non riuscivo a pensare a un modo migliore per spiegare come volevo che questi processi funzionassero. Concorrente potrebbe essere stata una scelta migliore. –

+0

Concorrente è molto meglio, e c'è un pulsante di modifica per voi per risolverlo. – derobert

risposta

16

I tubi dovrebbero andare bene per questo; devi solo controllare quando l'output del tuo programma C viene svuotato per renderlo disponibile allo script perl in modo incrementale. Puoi farlo nel programma C usando fflush(), che forzerà il buffer del tuo programma C a essere espulso in modo che il programma perl possa leggerlo.

Non c'è nulla di intrinseco nelle pipe che faccia sì che il programma perl attenda che il programma C termini la scrittura prima di elaborare il suo output. Il vostro programma Perl è scritto in modo che i processi STDIN una riga alla volta:

while ($line = <STDIN>) { ... } 

<> in questo contesto si legge una riga da STDIN, ma se non c'è una disposizione che bloccherà fino a quando si è. Una chiamata a fflush() dal programma C farà in modo che ciò accada.

Dai uno sguardo allo Wikipedia article on Pipelines. La sezione sull'implementazione fornisce una breve descrizione di come vengono bufferate le pipe, che dovrebbe aiutarti a capire come i tuoi processi comunicano. Le tubature do consentono la concomitanza tra processi e i processi di lettura e scrittura su pipe sono gestiti dallo scheduler proprio come altri processi. Il tuo problema qui è con il buffering.

+0

Pensavo che i programmi C cancellassero tutto l'output ogni volta che stampavano una nuova riga. –

+0

Avevi ragione con questa risposta - avevo persino esplorato fflush ma non ho mai pensato di usarlo sullo stdout.E a causa della natura del comportamento del programma perl, l'avevo scambiato per "aspettare" sul programma c. Ho aggiunto fflush (stdout) dopo le mie dichiarazioni printf e ha funzionato perfettamente! Grazie!! –

+0

@Chris Lutz, lo svuotamento automatico avviene solo se lo stream è in modalità bufferizzata linea, che di solito è true solo se lo stream è aperto su un tty. Una volta che lo stdout è una pipe, per impostazione predefinita è completamente bufferizzato per le migliori prestazioni. – RBerteig

5

Il programma C deve fflush() i suoi buffer di uscita esplicitamente o utilizzare una pty. Quest'ultimo è molto più imbarazzante, ma mantiene il codice C più semplice. Prova "man 3 fflush" se questo non ti è familiare.

+0

L'utilizzo di una pty è eccessivo; svuotare l'output è importante se si utilizza stdio nel codice C (e non materiale se si utilizza write() direttamente). –

+0

Una pty è necessaria solo se i due processi devono interagire, e quindi solo se uno o entrambi devono essere ignari di avere un non umano come parte interagente. I Pty non sono molto portabili al di fuori delle piattaforme unix-like. – RBerteig

+0

Sono d'accordo sul fatto che pty è eccessivo, ma inganna il programma C per l'autoflush dopo ogni nuova riga. In questo senso (e solo in questo senso!) Rende il programma C più semplice a spese di un ambiente più complicato. –