2013-05-11 22 views
1

我一直想弄清楚如何從文件中循環stdin,然後將它發送給使用execl()排序int的子進程。下面的代碼的作用在於它需要文件&對行進行排序,但是我沒有看到我添加的「句末」調試字符串。不知何故,這部分代碼被繞過。我可以使用一些幫助來理解從文件中獲取的數據流,然後將其打印到屏幕上。如何通過標準輸入和管道輸出循環到C中的子execl命令?

int main(int argc, char *argv[]) 
{ 
    pid_t p; 
    int status; 
    int fds[2]; 
    FILE *writeToChild; 
    char word[50]; 

    if(pipe(fds) == -1) { 
    perror("Error creating pipes"); 
    exit(EXIT_FAILURE); 
    } 

    switch(p = fork()) { 
    case 0: //this is the child process 
    close(fds[1]); //close the write end of the pipe 
    execl("/usr/bin/sort", "sort", (char *) 0); 
    break; 
    case -1: //failure to fork case 
    perror("Could not create child"); 
    exit(EXIT_FAILURE); 
    default: //this is the parent process 
    close(fds[0]); //close the read end of the pipe 
    writeToChild = fdopen(fds[1], "w"); 
    wait(&status); 
    break; 
    } 

    while (fscanf(stdin, "%s", word) != EOF) { 
    //the below isn't being printed. Why? 
    fprintf(writeToChild, "%s end of sentence\n", word); 
    } 

    return 0; 
} 

回答

2

您的主要問題是您的wait()位置錯誤。在你寫下任何東西之前,你等待孩子死亡。您還有一個第二個問題,那就是不會將管道的讀取端重定向到標準輸入的sort

你並沒有在孩子中關閉fds[0];清潔建議你應該。在等待之前你需要fclose(writeToChild);排序不會停止,直到父母已關閉管道給孩子。

這些變化(以及一些其他的)導致:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

int main(void) 
{ 
    pid_t p; 
    int status; 
    int fds[2]; 
    FILE *writeToChild; 
    char word[50]; 

    if (pipe(fds) == -1) 
    { 
     perror("Error creating pipes"); 
     exit(EXIT_FAILURE); 
    } 

    switch (p = fork()) 
    { 
     case 0: //this is the child process 
      close(fds[1]); //close the write end of the pipe 
      dup2(fds[0], 0); 
      close(fds[0]); 
      execl("/usr/bin/sort", "sort", (char *) 0); 
      fprintf(stderr, "Failed to exec sort\n"); 
      exit(EXIT_FAILURE); 

     case -1: //failure to fork case 
      perror("Could not create child"); 
      exit(EXIT_FAILURE); 

     default: //this is the parent process 
      close(fds[0]); //close the read end of the pipe 
      writeToChild = fdopen(fds[1], "w"); 
      break; 
    } 

    if (writeToChild != 0) 
    { 
     while (fscanf(stdin, "%49s", word) != EOF) 
     { 
      //the below isn't being printed. Why? 
      fprintf(writeToChild, "%s end of sentence\n", word); 
     } 
     fclose(writeToChild); 
    } 

    wait(&status); 

    return 0; 
} 
+0

這是一個巨大的幫助。謝謝。我有幾個跟進問題。 'dup2(fds [0],0)'行復制了fds管道的讀取結束?它也看起來像你關閉管道的讀取結束之後close(fds [0]);'?如果是這樣,爲什麼在調用excel進行排序之前關閉它? – user2227422 2013-05-11 23:26:32

+1

'dup2()'確保該排序的標準輸入是管道,但只需要打開兩個文件描述符(0和fds [0])中的一個,因此關閉第二個描述符。將管道複製到標準輸入或標準輸出時,這是正常的;如果使用'dup2()'將該管道連接到標準輸入或標準輸出,則關閉'pipe()'返回的管道的兩端。由於父進程寫入管道(不使用'dup2()'),它不會關閉正在寫入的管道的末端,直到完成。你可以在父文件中使用'dup2(fds [1],1)'並關閉'fds [1]'。 – 2013-05-11 23:57:12