2012-04-04 3 views
1

ich implementieren habe ein Szenario, das zwischen Kind und Eltern Prozessen Zweiweg-Kommunikation beinhaltet. Der untergeordnete Prozess verwendet execvp, um ein anderes c-Programm (z. B. XYZ) zu starten. Parent schreibt Daten an einem Ende von pipe1, und das andere Ende von pipe1 wird an die Standardeingabe von child dupliziert. So Kind liest diese Daten, führt einige Manipulationen und schreibt Daten zurück nach stdout. Dieses stdout wird dupliziert, um das Ende von pipe2 zu schreiben, und jetzt liest das übergeordnete Element vom Leseende von pipe2. Das externe Programm XYZ darf nicht geändert werden. Die Sequenz, die befolgt werden sollWie zwei-Wege-Kommunikation zwischen Kind und Eltern Verfahren unter Verwendung von Rohren implementieren, die mehrere Lese beinhaltet und schreibt

1) Mutter Daten schreibt PIPE1 2) Kinder Daten von duplizierten Ende (stdin) von PIPE1 3) Kind liest einige Modifikationen an Daten hat, und schreibt Daten zurück in stdout, die dupliziert zu lesen Ende von pipe2 4) Eltern versucht, Daten von Lese Ende von pipe2 zu lesen.

Das obige Szenario kann n-mal wiederholt werden.

Beispiel von oben beschriebenen Szenario mit Beispiel 1) Mutter schreibt 1 2) Kind 1 und tut Modifikation liest und schreibt 1 (nach Änderungen) 3) Nun stdout Eltern diese Daten und druckt lesen nach dem Drucken zurück 4) , Eltern schreibt 2 in die Standardeingabe 5) fährt fort wie oben .....

Das Problem, das ich gegenüberstelle, ist Elternteil ist nicht fähig, Daten vom gelesenen Ende von pipe2 zu lesen. Es hängt buchstäblich rum.

Imp Anmerkung: Ich habe nicht den Schreibgriff PIPE1 geschlossen, weil, ich brauche wieder Daten zu schreiben. Wenn ich den Griff schließe, kann ich ihn nicht erneut öffnen, da er nicht von Pipes unterstützt wird.

Der Code wird wie unten

void Child_write (pid_t Handle); 
void Parent_write (pid_t Handle, char c); 
void Child_read (pid_t Handle); 
void Parent_read (pid_t Handle); 

void main() 
{ 

    pid_t Pid; 
    int writepipe[2],readpipe [2]; 

    pipe(readpipe);    /* Create two file descriptors */ 
    pipe(writepipe);    /* Create two file descriptors */ 

    Pid = fork(); 

    if (Pid == 0)   
    { 
    close(writepipe[1]);    /* closing writepipe's write end */ 
    dup2(writepipe[0],0); close(writepipe[0]);  /* duplicating writepipe's read end to stdin*/ 
    close(readpipe[0]);    /* closing readpipe's read end*/ 
    dup2(readpipe[1],1); close(readpipe[1]);  /* duplicating readpipe's write end to stdout*/  
    Child_read(writepipe[0]);    /* reading data from write pipe read end and then duplicating*/ 

    } 
    else     
    { 
    close(writepipe[0]);    /* closing writepipe's read end */ 
    Parent_write(writepipe[1],'1');   /* pupming data to the writepipe */ 
    close(readpipe[1]);    /* closing the readpipes write end */ 
    Parent_read(readpipe[0]);    /* reading the data which is pumped into readpipe */ 
    //Parent_write(writepipe[1],'2');   /* pupming data to the writepipe */ 
    //Parent_read(readpipe[0]); 

    //Parent_write(writepipe[1],'3'); 
    //Parent_read(readpipe[0]); 
    puts("***** End of parent process*****"); 
    } 
} 

void Child_read(pid_t handle) 
{ 
    static char* command = "./stdoutput"; 
    execvp(command, NULL); 
} 

void Parent_write(pid_t handle, char c) 
{ 
    char Buff[] = {'\n','\n'}; 
    Buff[0] = c; 
    int n_written= write(handle, Buff, strlen(Buff)+1); 

    printf("write function has written %d no of bytes and the data written is %s",n_written,Buff); 

    //close(handle); 
} 

void Parent_read(pid_t handle) 
{ 
    printf("PARENT PROCESS: In Parent_read function\n"); 
    int i=0; 
    int bytes_read = 0; 
    char buffer[1024]= {'\0'}; 
    while (read(handle, buffer, sizeof(buffer)) > 0) 
    { 
     printf("PARENT PROCESS:: In while loop\n"); 
     printf("The character/string read from readend of readpipe (stdout) is %s",buffer); 
    } 
    close(handle); 
} 

Das externe Programm wird wie unten

void printing() 
{ 
    int c; 
    do 
    { 
     c = getchar(); 
     printf("%c",c); 
    } while ((c != EOF) && (c != '\n')); 
} 

void main() 
{ 
    printing(); 
    printing(); 
} 

gezeigt Bitte helfen Sie mir gezeigt !!!!!!!!!

+1

Wenn Sie sich nicht masochistisch fühlen, verwenden Sie einfach 'popen'. Obwohl dies zu einer Zeit nur eine unidirektionale Kommunikation erlaubte, hat Linux bidirektional zumindest für den Fall, dass der Speicher dient, unterstützt. –

+0

@JerryCoffin: Ich habe keine Kenntnisse über popen(). Ist es möglich das Problem mit unbenannten Pfeifen selbst zu lösen !!! – chaitu

Antwort

1

Auf dem ersten I/O-Aufruf (Datei-Stream unter Verwendung von Funktionen) für eine bestimmte Datei * entscheidet die Bibliothek, ob die Stromleitung gepuffert werden soll, Block gepuffert oder ungepuffert. In Ihrem Fall, wenn stdoutput gestartet wird, ist stdoutput kein Terminal, also geht der Stream in den Block-gepufferten Modus und Ihr printf endet in einem Puffer.

Ihre Hauptfunktion ändern:

void main() 
{ 
    setvbuf(stdout, NULL, _IONBF, 0); 
    printing(); 
    printing(); 
} 

Und Ihre printf schreibt produzieren wird.

Sie shoud auch auf der setvbuf Mann Seite sehen, und lernen Strace zu verwenden:

strace -ff -o test.log ./myprog 

wird zwei Log-fil (eine für die Eltern, eine für das Kind) mit denen Sie sehen, was Systemaufruf wird von jedem Programm gemacht.

-1

In der Tat, wie Jerry Coffin kommentierte, sollten Sie popen verwenden (einige Systeme haben auch eine p2open für bidirektionale Verrohrung, eine in, eine andere aus).

Wenn Sie wirklich darauf bestehen, es selbst zu tun, sollten Sie einen Multiplex-Systemanruf wie poll (oder vielleicht den älteren select) in Betracht ziehen. Dann können Sie testen, welcher Dateideskriptor gelesen oder geschrieben werden kann, und entsprechend handeln.

+0

Wenn ich einen Dateideskriptor mit popen() erstelle und ihn mit pclose() schließe, gibt es eine Möglichkeit, denselben Dateideskriptor wieder zu öffnen !!! – chaitu

+0

'popen' * erstellen Sie nicht direkt einen Dateideskriptor *; nur die 'open',' dup', 'pipe' * Systemaufrufe * machen das. Die 'popen' Bibliotheksfunktion, wie' fopen', gibt Ihnen ein 'FILE *' * Handle *, das der C-Bibliothek bekannt ist (und einen internen Puffer und einen internen Dateideskriptor enthält). Sie können 'fileno' verwenden, um den Dateideskriptor in einem 'FILE *' - Handle abzurufen. Dateideskriptoren sind kleine nicht negative ganze Zahlen (wobei 0 stdin ist, 1 stdout, ...). Ich verstehe nicht, warum Sie den gleichen Dateideskriptor wollen (ich glaube, Sie haben eine Verwirrung). –

+0

in dem im Post beschriebenen Szenario .... Ich muss mehrere Lese- und Schreibvorgänge (interleaved). Um einen (Schreib-, Lese-) Satz erfolgreich zu machen, müssen Sie den Schreibgriff nach dem erfolgreichen Schreiben der Daten schließen. Danach, wenn ich denselben Satz erneut ausführen muss, muss ich den geschlossenen Dateideskriptor erneut öffnen. Das ist die Notwendigkeit für mich. Wenn ich den Schreibzugriff nicht schließe, wird der Lesevorgang unterbrochen. – chaitu