|
![ein Kapitel weiter](../weiter.gif)
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 weiter](../weiter.gif)
© 2001,2002 Jürgen Wolf
|