ein Kapitel zurück                                           ein Kapitel weiter

Kommen wir nun zu der Funktion popen() die uns, im Gegensatz zu den Kapiteln zuvor, eine Menge Schreibarbeit abnimmt. Hier der Syntax zu popen......

FILE *popen(const char* command, const char* wie);  

Die Variable entspricht hier einen Funktionsaufruf von system. Intern wird dabei aber trotzdem eine Pipe angelegt. Ob sie aus diesem Prozesß Lesen oder Schreiben wollen legen sie mit 'wie' fest. "r" steht für lesen aus der Pipe und "w" für Schreiben. Im Fehlerfall liefert uns popen NULL ansonsten den FILE-Zeiger zurück. Somit nimmt uns die Funktion popen folgende Arbeiten gegenüber der Funkion pipe ab.....

  • pipe-Aufruf
  • fork-Aufruf (Erzeugung eines Kindprozesses)
  • Schließen nichtverwendeter Seiten des Kind/Elternprozesses
  • die Überlagerung einer exec-Funktion

Bevor wir zu einigen Beispielen mit der Funktion popen() kommen, soll hierzu noch eine alternative Implemtiereung erstellt werden, da nicht auf jedem System popen vorhanden ist. Also erstellen wir eine eigene popen-Funktion, damit auch andere auf den Genuss dieser Funktion kommen. Hier die Funktion popen selbstgebastelt........

/*Download:popen.c*/
#include <stdio.h> #define READ 0 #define WRITE 1 #define wr(a,b) (mode==READ?(b):(a)) FILE *p_open(char *commando, int mode) { int fd[2]; if(pipe(fd) < 0) return NULL; switch(fork()) { case -1 : return(NULL); case 0 : close(wr(fd[WRITE],fd[READ])); close(0,1); dup(wr(fd[READ],fd[WRITE])); close(wr(fd[READ],fd[WRITE])); execl("/bin/sh", "sh", "-c", commando, NULL); default : close(wr(fd[READ],fd[WRITE])); return(FILE *)(wr(fd[WRITE],fd[READ])); } }

Nun möchte ich Ihnen die Funktion popen anhand eines Beispiels näher bringen....

/*Download:pop1.c*/
#include <unistd.h> #include <sys/wait.h> #include <stdio.h> #include <sys/types.h> #include <fcntl.h> #define EXIT(s) {fprintf(stderr, "%s",s); exit(0);} #define USAGE(s) {fprintf(stderr, "%s Datei zum lesen\n",s); exit(0);} #define MAX 8192 enum {ERROR=-1,SUCCESS}; int main(int argc, char **argv) { FILE *pipe_writer, *file; char puffer[MAX]; if(argc!=2) USAGE(argv[0]); if((file=fopen(argv[1], "r")) == NULL) EXIT("Fehler bei fopen.........\n"); if(( pipe_writer=popen("./filter" ,"w")) == NULL) EXIT("Fehler bei popen...........\n"); while(1) { if(fgets(puffer, MAX, file) == NULL) break; if(fputs(puffer, pipe_writer) == EOF) EXIT("Fehler bei fputs........\n"); } pclose(pipe_writer); }

Die Programm bewirkt wirklich das selbe wie mit der Funktion pipe() im Kapitel zuvor. Sie können diese beiden Programme ruhig mal vergleichen. Wollen wir diese Funktion doch mal etwas genauer analysieren..........

Als erstes Argument der Funktion popen() geben wir das Programm ein das unseren Kindprozess überlagern soll. Und das zweite Argument stellt den Modus da. Dafür haben wir wie schon bei den Pipes die folgenden 2 Möglichkeiten.............

w - Die geschriebenen Daten in die Pipe werden an die Standardeingabe von kommandozeile weitergegeben.




r - Die gelesenen Daten aus der Pipe stammen direkt aus der Standardausgabe von kommandozeile.




Um die pipe wieder zu schließen sollte die Funktion........

int pclose(FILE *pipe_zeiger);  

...ausgeführt werden. Diese Funktion wartet auf die Beendigung des Prozesses den sie in kommandozeile angegeben haben.

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf