Prozesse mit Pipe verbinden
Pipes werden dazu verwendet, um die Kommunikation zweier Prozesse zu gewährleisten. Pipes stellen also den Verbindungskanal zwischen zwei Prozessen her! In diesem Artikel erfahren Sie, wie eine >>namenlose Pipe<< und eine >>benannte Pipe<< erstellt werden kann.
Beschreibung verwendeter Systemfunktionen
>>dup2<<
dup2() ist eine Systemfunktion, welche in der File Descriptor Table einen offenen Dateideskriptor dupliziert. Es existiert auch eine Funktion dup() (hier nicht eingesetzt). Der Unterschied der Beiden Funktionen besteht darin, dass dup2() im Gegensatz zu dup() nicht unterbrechbar ist "atomar"
>>mkfifo<<
Mit mkfifo() kann eine benannte Pipe erstellt werden.
>>unlink()<<
unlink() Löscht vorhandene Verzeichniseinträge auf eine verweisende Datei. Existieren keine Einträge mehr, wird die Datei gelöscht
Namenlose Pipe
Vorgehensweise:
int main( int argc, char **argv ) { int fileDescr[2]; // Zwei Dateideskriptoren anlegen char *message = "Hallo Welt\n"; // = 11 Zeichen char buffer[11]; // Platz für 11 Zeichen schaffen int status; // Endstatus // Pipe erzeugen pipe(fileDescr); // 1.Kind erzeugen --> Daten schreiben if( fork() == 0 ) { dup2( fileDescr[1], 1 ); // Eingang der Pipe auf stdin legen close( fileDescr[0] ); // Ausgang der Pipe schliessen write(1, message, 11); // Daten schreiben (11 Zeichen auf Konsole) } // 2.Kind erzeugen --> Daten lesen else id( fork() == 0 ) { dup2( fileDescr[0], 0 ); // Ausgang der Pipe auf auf stdout legen close( fileDescr[1] ); // Eingang der Pipe schließen read(0, buffer, 11); // Daten lesen (11 Zeichen) printf("%s", buffer); // Gelesene Daten ausgeben } // Elternprozess else { // Pipes schliessen close( fileDescr[0] ); // Ausgang der Pipe close( fileDescr[1] ); // Eingang der Pipe // Auf Kindprozesse warten wait( &status ); wait( &status ); } exit(0); }
/** * @desc Legt eine Pipe an. * Danach kann Konsument und Produzent gestartet werden */ pipe_init ( ) { int status; status = mkfifo("./pipename", 0700); // Pipeline anlegen if( status == 0 ) // Bei Erfolg { printf("Pipe wurde angelegt"); exit(0); } // Bei Misserfolg printf("Fehler beim anlegen der Pipe"); exit(-1); }
/** * @desc Dient als Produzent. * Schreibt einen Text in die Pipe */ pipe_produce ( ) { char *message; int fileDescriptor; message = "HalloWelt"; fileDescriptor = open("./pipename", O_WRONLY); // Pipe öffnen if( fileDescriptor < 0 ) // Wenn Fehler { printf("Pipe konnte nicht geöffnet werden"); exit(-1); } // Öffnen erfolgreich write(1, message, strlen(message) ); // in Pipe schreiben close(1); exit(0); }
/** * @desc Dient als Konsument. * Ließt die Daten des Produzenten aus der Pipe */ pipe_consume ( ) { int fileDescriptor; // Dateideskriptor int count; // Anzahl der ausgelesenen Zeichen in read char buffer[255]; // Speicher anlegen fileDescriptor = open("./pipename", O_RDONLY); // Pipe öffnen if( fileDescriptor < 0 ) // Öffnen Fehlgeschlagen { printf("Pipe konnte nicht geöffnet werden"); exit(-1); } // Öffnen erfolgreich if( count = read(0, buffer, 255) >= 1 ) // Wenn Daten vorhanden { for( i=0; i<count; i++ ) // gebe Daten aus printf("%c", buffer[i]); // %c = character ausgeben } unlink("./pipename"); // Löscht den Verzeichniseintrag exit(0); }