Anzeige:
Ergebnis 1 bis 10 von 10

Thema: [C] Aus Pipe direkt in Datei schreiben

  1. #1
    Registrierter Benutzer
    Registriert seit
    24.03.2003
    Beiträge
    71

    [C] Aus Pipe direkt in Datei schreiben

    Hallo,

    will das Ergebnis eines Shell-Kommandos über eine Pipe in eine Datei schreiben. Im Moment löse ich das so:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    
    int main() {
    	int pfd[2];
    	int pid;
    	pipe(pfd);
    	
    	pid=fork();
    	if(pid==-1) perror("fork"),exit(1);
    	if(pid==0) { //child
    		close(pfd[0]);
    		close(1);
    		dup(pfd[1]);
    		execlp("ls","ls","-lai",NULL);
    		perror("exec");
    		exit(3);
    	}
    	else { //parent
    		int fd,rbytes;
    		close(pfd[1]);
    		if((fd=open("blubb",O_CREAT|O_TRUNC|O_WRONLY,0644))<0)
    			perror("open"),exit(2);
    		char buf[128];
    		rbytes=read(pfd[0],buf,sizeof(buf));
    		write(fd,buf,rbytes);
    		close(fd);
    		
    		exit(0);
    	}
    	
    }
    Nun meine Frage ob es auch irgendwie möglich ist, dieses "Erst aus Pipe lesen und dann in Datei schreiben" wegzulassen und direkt irgendwie das Pipe-Ende (Leseende) mit der Datei zu verbinden. Mit dup() und vorherigem Close ist sowas ja möglich....aber ob ich damit ich auch direkt schreiben kann habe ich nicht hinbekommen und glaube auch es funktioniert nicht....

    Ist alles nur eine Übungsaufgabe, also nicht nach dem Sinn fragen

    Wäre nett wenn mir einer auf die Sprünge helfen könnte,

    Gruß,
    Ace

  2. #2
    Registrierter Benutzer
    Registriert seit
    23.05.2004
    Beiträge
    592
    Dies ist keine Antwort auf deine Frage.

    rbytes=read(pfd[0],buf,sizeof(buf));
    write(fd,buf,rbytes);
    Das ist gefährlich. Stell dir vor read liefert einen Fehler und damit den Wert -1 zurück. Dann würde der write-Aufruf danach versuchen eine große Anzahl von Bytes zu schreiben und dabei das Ende von "buf" nicht berücksichtigen. Überhaupt scheint mir die Fehlerbehandlung bei dir noch zu verbessern sein.

  3. #3
    Registrierter Benutzer
    Registriert seit
    24.03.2003
    Beiträge
    71
    Zitat Zitat von locus vivendi Beitrag anzeigen
    Dies ist keine Antwort auf deine Frage.


    Das ist gefährlich. Stell dir vor read liefert einen Fehler und damit den Wert -1 zurück. Dann würde der write-Aufruf danach versuchen eine große Anzahl von Bytes zu schreiben und dabei das Ende von "buf" nicht berücksichtigen. Überhaupt scheint mir die Fehlerbehandlung bei dir noch zu verbessern sein.
    Richtig....aber darum geht's hier überhaupt nicht...ich wollte hier einfach nur kurz ein Beispiel liefern....

    Gruß,
    Ace

  4. #4
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    Schau dir mal dup2 an.

    IIRC müsste etwas in der Art gehen:
    Code:
    fd=open("blubb",O_CREAT|O_TRUNC|O_WRONLY,0644);
    dup2(fd,pfd[1]);
    close(fd);

  5. #5
    Registrierter Benutzer
    Registriert seit
    24.03.2003
    Beiträge
    71
    Zitat Zitat von Joghurt Beitrag anzeigen
    Schau dir mal dup2 an.

    IIRC müsste etwas in der Art gehen:
    Code:
    fd=open("blubb",O_CREAT|O_TRUNC|O_WRONLY,0644);
    dup2(fd,pfd[1]);
    close(fd);
    Mit dup2 hatte ich auch schon rumexperimentiert. Sollte das bei deinem Beispiel dann automatisch in die Datei geschrieben werden? Und du meintest dup2(fd,pfd[0]), oder? Ich will ja das lesende Ende der Pipe mit der Datei verbinden.

    Gruß,
    Ace

  6. #6
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    Oh, jetzt sehe ich erst das Problem.

    Du brauchst keine Pipe!
    In dem Prozess, der execlp aufruft (was soll da eigentlich der nutzlose dup?) biegst du einfach stdout auf die Datei um, so wie es auch die Shell macht, also in etwa so:
    Code:
    fd = open(...);
    dup2(1,fd); // oder lesbarer: dup2(STDOUT_FILENO, fd); dafür musst du unistd.h includen
    execlp(...);

  7. #7
    Registrierter Benutzer
    Registriert seit
    24.03.2003
    Beiträge
    71
    Zitat Zitat von Joghurt Beitrag anzeigen
    Oh, jetzt sehe ich erst das Problem.

    Du brauchst keine Pipe!
    In dem Prozess, der execlp aufruft (was soll da eigentlich der nutzlose dup?) biegst du einfach stdout auf die Datei um, so wie es auch die Shell macht, also in etwa so:
    Code:
    fd = open(...);
    dup2(1,fd); // oder lesbarer: dup2(STDOUT_FILENO, fd); dafür musst du unistd.h includen
    execlp(...);
    Dass das so funktioniert weiss ich schon, aber in der Aufgabe steht halt explizit, dass ich das Zeug erst über die PIPE jagen soll.
    Und wieso ist der dub()-Aufruf sinnlos? Ich schliesse STDOUT und hänge da per dup() das schreibende Ende der PIPE dran....

    Gruß,
    Ace

  8. #8
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    Zitat Zitat von AceTheFace Beitrag anzeigen
    Dass das so funktioniert weiss ich schon, aber in der Aufgabe steht halt explizit, dass ich das Zeug erst über die PIPE jagen soll.
    Tja, diese Aufgabenstellung lese auch ich als "Erst aus Pipe lesen und dann in Datei schreiben". Da wirst du das mit dem Umweg machen müssen.
    Bei Hausaufgaben nicht nach einem praktischen Sinn fragen.

    Und wieso ist der dub()-Aufruf sinnlos? Ich schliesse STDOUT und hänge da per dup() das schreibende Ende der PIPE dran....
    Nein. dup erzeugt eine Kopie des übergebenen Deskriptors und gibt jenen zurück. Dein "dup(pfd[1])" erzeugt eine Kopie von pfd[1] und schmeisst das Ergebnis weg. Was du wolltest, geht mit "dup2(pfd[1], 1)"

  9. #9
    Registrierter Benutzer
    Registriert seit
    24.03.2003
    Beiträge
    71
    Den Umweg gehe ich gerne. Meine Frage war ja nur ob es nicht vielleicht doch irgendwie geht, aber ich denke das hat sich dann geklärt, danke

    Zitat Zitat von Joghurt Beitrag anzeigen
    Nein. dup erzeugt eine Kopie des übergebenen Deskriptors und gibt jenen zurück. Dein "dup(pfd[1])" erzeugt eine Kopie von pfd[1] und schmeisst das Ergebnis weg. Was du wolltest, geht mit "dup2(pfd[1], 1)"
    Nein, das funktioniert auch mit dup() allein. Probiere doch mein kleines Beispiel einfach mal aus. Unser Prof. hat das so auch zig mal in seinen Beispielprogrammen gemacht. Da ich vorher STDOUT schliesse liefert dup() zwar 1 zurück, aber das Ergebnis brauche ich nur wenn ich später irgendwie selbst was da reinschreiben will. Implizit wird der Zeiger umgehängt.
    dup2() bringt ja eigentlich nur etwas wenn ich gezielt umhängen will, also nicht automatisch den kleinsten freien haben will.

    Gruß,
    Ace

  10. #10
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    Zitat Zitat von AceTheFace Beitrag anzeigen
    Da ich vorher STDOUT schliesse liefert dup() zwar 1 zurück, aber das Ergebnis brauche ich nur wenn ich später irgendwie selbst was da reinschreiben will.
    Au! Böse! OK, laut Doku liefert dup immer den kleinsten freien FD zurück, ich weiss aber nicht, ob das explizit in der POSIX-Spezifikation festgelegt ist. Und das fliegt dir um die Ohren, wenn du mal auch stdin schließen solltest...

    Meiner Meinung nach ist das sehr schlechter Programmierstil. Man sollte besser auch das coden, was man erreichen will. Die paar Prozessortakte mehr machen heutzutage nichts mehr aus. Und du verstehst den Code auch noch in 5 Jahren.

    Heutzutage schreibt ja auch keiner mehr
    Code:
    a ^= b;
    b ^= a;
    a ^= b;

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •