2016-06-06 6 views
1

Ich bin neu in der Systemprogrammierung, und passieren Sie durch den popen() Aufruf. Dies ist ein Code-Snippet der Implementierung popen() unter Linux.popen() Aufruf auf Linux, was diese Zeilen tun?

dup2() Aufruf wird das Argument später schließen, und das vorherige Argument wird explizit in Kind geschlossen. Sieht so aus, als wären beide Deskriptoren im Kind geschlossen.

Warum funktioniert dieses Ding noch? Ich kann die Funktionsweise des Codes nicht verstehen.

switch (pid = vfork()) { 
case -1:   /* error */ 
    (void) close(pdes[0]); 
    (void) close(pdes[1]); 
    return (NULL); 
    /* NOTREACHED */ 
case 0:    /* child */ 
    if (*type == 'r') { 
     if (pdes[1] != fileno(stdout)) { 
      (void) dup2(pdes[1], fileno(stdout)); 
      (void) close(pdes[1]); 
     } 
     (void) close(pdes[0]); 
    } else { 
     if (pdes[0] != fileno(stdin)) { 
      (void) dup2(pdes[0], fileno(stdin)); 
      (void) close(pdes[0]); 
     } 
     (void) close(pdes[1]); 
    } 
    execl("/bin/sh", "sh", "-c", program, NULL); 

Antwort

1

dup2 bedeutet dup licate ein Dateideskriptor zu. dup2(pdes[1], fileno(stdout)); Als Linux dup2 (2) Handbuchseiten sagen:

dup2() macht die Kopie oldfd newfd sein, newfd Schließen erste bei Bedarf

So sind diese zwei Linien

(void) dup2(pdes[1], fileno(stdout)); 
(void) close(pdes[1]); 

Schließen Sie zuerst den alten stdout-Dateideskriptor, dann kopieren Sie den Pipe-Endpunkt pdes[1] in den stdout-Dateideskriptor - jetzt gibt es Dateideskriptoren, die auf dieselbe Pipe verweisen. Dann schließen wir den ursprünglichen Pipe-Endpunkt, der kopierte bleibt jedoch geöffnet.


BTW, streng, ist fileno(stdout) nicht korrekt. Es gibt die Dateinummer zurück, die die FILE *stdout enthält, , wenn sie überhaupt geöffnet ist. Stattdessen sollten Sie dort STDOUT_FILENO oder 0 verwenden.

+0

Dank @Antti. Klar mit dem Konzept jetzt. –