ein Kapitel zurück                                           ein Kapitel weiter

Da dies Systemaufrufe write, read und close anders als sonst reagieren, bedürfen sie einer kurzen Erklärung.

read
read wird solange Blockiert, bis sich wieder genügend Daten in der Pipe befinden. Schreibt kein Prozeß mehr in die Pipe bleibt read solange stecken bis der schreibende Prozeß den Systemaufruf close verwendet hat. Dieses steckenbleiben von read eignet sich prima zum Syncronisieren von Prozessen.

write
write schreibt die Daten in der richtigen Reihenfolge in die Pipe. Ist die Pipe voll, wird der Schreibende Prozeß solange angehalten bis wieder genügend Platz vorhanden ist. Diese Verhalten könnten sie abschalten in dem sie das Flag O_NONBLOCK mit z.B. der Funktion fcntl setzen. In diesem Fall liefert der Schreibende Prozeß 0 zurück.

Standard-E/A-Funktionen mit pipe

Natürlich ist es auch möglich auf Pipes mit Standard E/A - Funktionen zuzugreifen. Dazu müssen sie nur die mit dem pipe() - Aufruf erhaltenen Filedeskriptoren mit der Funktion fdopen (Siehe Kapitel Low-Level-I/O) einen Dateizeiger (FILE *) zuteilen. Natürlich müssen sie fdopen mit dem richtigen Modus verwenden. Denn es ist nicht möglich.......

FILE *f;
f=fdopen(fd[0], "w"); /*falsch*/  

...zu verwenden da fd[0] für das Lesen aus einer Pipe steht. Richtig ist dagegen.....

FILE *reading, *writing;

reading=fdopen(fd[0], "r");
writing =fdopen(fd[1], "w");  

Geben sie Ihrem Dateizeiger einfach einen Aussagekräftigen Namen um Verwechslungen auszuschließen. Sehen wir uns dazu wieder ein Beispiel an........

/*Download:pip2.c*/
#include <unistd.h> #include <sys/wait.h> #include <stdio.h> #include <sys/types.h> #include <fcntl.h> #include <signal.h> #include <string.h> #define USAGE printf("usage : %s Datei\n",argv[0]); #define MAX 4096 int main(int argc, char *argv[]) { int fd[2], fd1,i, n; pid_t pid; char puffer[MAX]; FILE *reading, *writing, *newfile; if(argc !=2) { USAGE; exit(0); } if((newfile=fopen(argv[1], "a+")) < 0) { perror("fopen : "); exit(0); } /*Wir erstellen eine pipe*/ if(pipe(fd) <0) { perror("pipe : "); exit(0); } /*Wir erzeugen einen neuen Prozess*/ if((pid=fork()) < 0) { perror("pipe : "); exit(0); } else if(pid > 0) /*Elternprozess*/ { close(fd[0]); /*Leseseite schließen*/ if((writing=fdopen(fd[1], "w")) == NULL) { perror(" fdopen : "); exit(0); } fgets(puffer, MAX, stdin); fputs(puffer, writing); /*Wir schreiben in die Pipe*/ } else /*Kindprozess*/ { close(fd[1]); /*Schreibseite schließen*/ if((reading=fdopen(fd[0], "r")) == NULL) { perror(" fdopen : "); exit(0); } fgets(puffer, MAX, reading); /*Wir lesen aus der Pipe*/ fputs(puffer, newfile); } exit(0); }

Mit diesem Programm öffnen bzw. erzeugen wir eine Datei die als Argument in der Kommandozeile angegeben haben. Dann schließen wir im Elternprozess die Leseseite der Pipe und teilen den FILE-Zeiger mit fdopen die Schreibseite der Pipe zu. Dann lesen wir aus der Standardeingabe mit fgets und danach schreiben wir mit fputs in die Pipe. Der Kindprozess schließt dann die Pipe und teilt dem FILE-Zeiger die Leseseite von der Pipe zu. Anschließend lesen wir aus der Pipe mit fgets und schreiben dies mit fputs in die neue Datei.

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf