dup2(): filedeskriptoren duplizieren



  • hi,

    ich hab hier einen code in dem in sehr einfachen Stile das pipe-verhalten von der kommandozeile mit der Verwendung von filedeskriptoren und pipes kopiert wird.

    Also wenn man das Programm mit ./a.out ls sort
    aufruft hat das den selben effekt wie auf der shell " ls | sort" einzugeben.(das ganze soll uch ohne parameter läufen, geht ums verständnis)

    hier mal der code

    int main(int argc, char ** argv)
    {
    	int fd[2];
            pipe(fd);
    
    	if (argc != 3)
    		exit(1);
    
    	pid_t f = fork();
    
    	if (f < 0 )
    	{
    		printf("Fork failed\n");
    		exit(1);
    	}
    	else if (f == 0)
    	{
    		close(fd[0]);
    		dup2(fd[1], 1);
    		close(fd[1]);
    		execlp(argv[1], argv[1], NULL);
    	}
    	else if (f > 0)
    	{
    		close(fd[1]);
    		dup2(fd[0], 0);
    		close(fd[0]);
    		execlp(argv[2],argv[2], NULL);
    	}
    
    	return 0;
    }
    

    Das Kind verarbeitet hier ja dn ersten parameter argv[1] (z.B. ls)
    das für das kind hier jetzt der fd[0] geschloßen wird verstehe ich noch, auch das kopieren des deskriptors durch dup2() von stdout nach fd[1] scheint mir noch verständlich. Aber wieso schließe ich hier direkt fd[1] wieder?
    Eigentlich will ich das fd[1] behalten um diesen als inputstrom für das parent zu nehmen, das dann den zweiten teil des befehls durchführt (z.B. sort).

    das mein denkweise falsch ist, seh ich daran das es so funktioniert - und so wie ich es mir dachte nicht. aber verstehen tu ich es nicht.



  • dup2 dupliziert den Dateideskriptor. Du hast also 2 unabhängige Deskriptoren auf das selbe Gerät. Schliesst Du eins der beiden, ist das anderen nicht betroffen.

    Sagen wir mal, Dein fd[1] hat den Wert 5. Er soll aber 1 sein, da das künftige Kind-Programm auf 1 seine Standardausgabe erwartet. Also duplizierst Du den Deskriptor, so dass der Wert 1 auch auf die Pipe zeigt. Jetzt hast Du 2 Deskriptoren: die 1 und die 5. Die 5 brauchst Du (bzw. das Kind-Programm) nicht mehr. Also schliesst Du es. Die 1 bleibt erhalten.



  • also mal anders formuliert

    dup2(fd[1], 1);

    damit sage ich das Ausgabestorm meiner pipe (fd[1]) auf den standard-ausgabestrom verweisen soll. zwei deskriptoren auf das selbe gerät.

    close(fd[1]);

    Da ich jetzt zwei Deskriptoren hab schließe ich einen, der überbleibende Deskriptor der standardausgabe (1) verweist jetzt immernoch als Ausgabestrom auf die pipe ?(ist das richtig?)

    ich hätte jetzt erwartet man sagt close(1); ich will hier gar keien Ausgabe haben, sondern das die Daten über fd[1] ausgegeben werden - und damit automatisch als Eingabestrom



  • Korrekt.

    Das "ls" oder was auch immer Programm schreibt seine Ausgabe auf den Filedeskriptor mit der Nummer 1. Woher der kommt, weiß er nicht und kann ihm auch egal sein. Wenn Du close(1) machst, dann ist der Dateideskriptor 1 geschlossen und das Kind-Programm bekommt beim Versuch, etwas darauf zu schreiben, einen Fehler.


Anmelden zum Antworten