2012-07-15 79 views
1

下面是我試圖得到它的工作代碼....創建管道 - 的Unix

我期待輸出

OUTPUT from PipeAttempt(args1, args2) 

其次

I am here 

OUTPUT from PipeAttempt(args3, args4) 

但在現實中,我只從PipeAttempt(args1,args2)獲得輸出;

和程序等待輸入來自我,當我按下回車鍵,程序終止

可否請您讓我知道我錯過了?

int main() { 
    char* args1 [] = {"/usr/bin/head", "/etc/passwd", NULL}; 
    char* args2 [] = {"/bin/sort", NULL}; 

    char* args3 [] = {"/bin/cat", "piped.input", NULL}; 
    char* args4 [] = {"/usr/bin/wc", NULL}; 



    PipeAttempt(args1, args2); 

    printf("I am here\n"); 

    PipeAttempt(args3, args4); 


    return 0; 

} 


void PipeAttempt(char* args1[], char* args2[]) { 
    int pfildes[2]; <br> 
    pid_t cpid1, cpid2; <br> 
    char *envp[] = { NULL };<br> 


    if (pipe(pfildes) == -1) {perror("demo1"); exit(1);} 
    if ((cpid1 = fork()) == -1) {perror("demo2"); exit(1);} 
    else if (cpid1 == 0) {  /* child: "cat a"      */ 
      close(pfildes[0]); /* close read end of pipe    */ 
      dup2(pfildes[1],1); /* make 1 same as write-to end of pipe */ 
      close(pfildes[1]); /* close excess fildes     */ 

     execve(args1[0], args1, envp); 

      perror("demo3");  /* still around? exec failed   */ 
      exit(1);    /* no flush        */ 
     } 
    else {      /* parent: "/usr/bin/wc"    */ 
      close(pfildes[1]); /* close write end of pipe    */ 
      dup2(pfildes[0],0); /* make 0 same as read-from end of pipe */ 
      close(pfildes[0]); /* close excess fildes     */ 

     execve(args2[0], args2, envp); 
      perror("demo4");  /* still around? exec failed   */ 
      exit(1);   /* parent flushes      */ 
     } 
} 

回答

1

您的原始父項被exec調用覆蓋。所以您只能獲得/ usr/bin/head/etc/passwd的輸出。/bin/sort,你沒有得到/ bin/cat piped.input |/usr/bin/wc的輸出。

該程序實際上並沒有等待你的鍵盤輸入。發生了什麼情況是沒有顯示shell提示符。父母在孩子面前退出,提示立即顯示在shell(等待父母),並且孩子的輸出在那之後出現,這讓你認爲程序正在等待用戶輸入。

這裏要解決這個問題,可以在函數中fork另一個子項,這樣可以有效地爲每個函數(PipeAttempt)調用兩個子項來處理管道,並且在main中可以等待所有四個子項完成,這樣父母最後退出並返回shell提示符。鑑於下面修改後的代碼,下面的pl。在編譯之前包含wait,strlen等的頭文件。希望這可以解決您的問題。

void PipeAttempt(char* args1[], char* args2[]) ; 
int main() { 
int i; 
char* args1 [] = {"/usr/bin/head", "/etc/passwd", NULL}; 
char* args2 [] = {"/bin/sort", NULL}; 

char* args3 [] = {"/bin/cat", "piped.input", NULL}; 
char* args4 [] = {"/usr/bin/wc", NULL}; 

PipeAttempt(args1, args2); 
write(1, "I am here\n", strlen("I am here\n")); 
PipeAttempt(args3, args4); 
for (i=0; i < 4; i++) 
{ 

    wait(NULL); 
} 
return 0; 
} 

void PipeAttempt(char* args1[], char* args2[]) 
{ 
    int pfildes[2]; 
    pid_t cpid1, cpid2; 
    char *envp[] = { NULL }; 


    if (pipe(pfildes) == -1) {perror("demo1"); exit(1);} 

    if ((cpid1 = fork()) == -1) {perror("demo2"); exit(1);} 
    else if (cpid1 == 0) 
    {  /* child1 */ 
     close(pfildes[0]); /* close read end of pipe    */ 
     dup2(pfildes[1],1); /* make 1 same as write-to end of pipe */ 
     close(pfildes[1]); /* close excess fildes     */ 
     execve(args1[0], args1, envp); 
     perror("demo3");  /* still around? exec failed   */ 
     exit(1);    /* no flush        */ 
    } 
    else {      
    /* child2: "/usr/bin/wc"    */ 
    if (0==fork()) 
     { 
     close(pfildes[1]); /* close write end of pipe    */ 
     dup2(pfildes[0],0); /* make 0 same as read-from end of pipe */ 
     close(pfildes[0]); /* close excess fildes     */ 
     execve(args2[0], args2, envp); 
     perror("demo4");  /* still around? */ 
     exit(1); 
     } 
//Parent 
close(pfildes[0]); 
close(pfildes[1]); 
    } 
} 
+0

非常感謝Tanmoy提供的信息。我現在知道爲什麼我的早期計劃行爲不正常。我調整了我的代碼,並且它按照我希望的方式工作。你有很大的幫助。 – Josh 2012-07-15 23:01:01

+0

@Josh,歡迎喬希! – 2012-07-16 05:37:17

0

您的PipeAttempt()函數執行fork/exec - 您怎麼能期望它返回到主函數?

+1

也許是因爲fork()之後父進程繼續? – 2012-07-15 17:50:14

+0

如果父進程也執行execve會怎麼樣? – 2012-07-15 18:11:49