2014-09-24 68 views
1

我正在學習如何使用C管道,而且我在編寫一個字符串列表一個接一個地寫入子進程的管道時遇到了一些困難,然後在父進程中從管道讀取它們。這裏是我當前的代碼:使用管道讀取字符串數組C使用C

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <string.h> 

int main() 
{ 
    int pfd[2]; 
    char buf[1000]; 
    int cfork; 

    if (pipe(pfd) == -1) { 
     exit(1); 
    } 

    cfork = fork(); 

    if (cfork == -1) { 
     printf("Fork Failed\n"); 
     exit(1); 
    } 
    else if (cfork == 0) { 
     printf("Child Process\n"); 

     char *fruit[] = { 
      "Orange", "Apple", 
      "Banana", "Pear" 
     }; 

     int num_fruit = 4; 
     for (int i = 0; i < num_fruit; i++) { 
      printf("Current fruit: %s\n", fruit[i]); 
      write(pfd[1], fruit[i], (strlen(fruit[i]))); 
     } 
     _exit(0); 
    } 
    else { 
     printf("Parent Process\n"); 
     read(pfd[0], buf, sizeof(buf)); 
     printf("Fruit Fetched: %s\n", buf); 
     wait(NULL); 
    } 

    return 0; 

} 

我所要做的,就是在孩子讀水果串,將其寫入管道,並有家長讀這個字符串並打印出來,直到所有的字符串已被打印。我的麻煩是,孩子,因爲它在一個循環,只是不斷添加每個字符串到緩衝區,所以程序,現在,打印出「OrangeAppleBanana」。我很確定我也需要在父級循環,但是當我嘗試了一個等待子節點發送的一些結束條件字符串(例如「完成」)的while循環時,我的程序仍然卡在無限循環。

對於剛接觸C的人來說,最簡單的方法是一個接一個地在子項中寫入字符串,並讓父進程一個接一個地打印出來?

編輯

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <sys/wait.h> 
#include <string.h> 

int main() 
{ 
    int pfd[2]; 
    int cfork; 

    if (pipe(pfd) == -1) { 
     exit(1); 
    } 

    cfork = fork(); 

    if (cfork == -1) { 
     printf("Fork Failed\n"); 
     exit(1); 
    } 
    else if (cfork == 0) { 

     int numbers[] = { 
      1, 2, 
      3, 4 
     }; 

     int limit = 4; 
     close(pfd[0]); 
     for (int i = 0; i < limit; i++) { 
      printf("Child - Current Number: %d\n", numbers[i]); 
      write(pfd[1], &numbers[i], sizeof(numbers[i])); 
     } 
     close(pfd[1]); 
     _exit(0); 
    } 
    else { 

     int temp; 
     int reads = 4; 
     close(pfd[1]); 
     for (int i = 0; i < reads; i++) { 
      read(pfd[0], &temp, sizeof(temp)); 
      printf("Parent - Number Fetched: %d\n", temp); 
     } 
     close(pfd[0]); 
     waitpid(-1, NULL, 0); 
    } 

    return 0; 

這是我的新代碼,在那裏我使用整數而不是字符串。似乎工作到目前爲止。仍然不確定我在做什麼錯誤的字符串。

回答

0
//Child 
close(pfd[0]); // Close read end this blocks if parent is reading from pipe 
write(pfd[1]...); // write data into pipe 
close(pfd[1]); // close write end of pipe now the pipe is ready to read 

// Parent 
close(pfd[1]); // close write end of pipe blocks if child is writing to pipe. 
read(pfd[0] ...); 
close(pfd[0]..); // close read end so pipe is ready to write to. 
1

我相信你的問題是與「字符串」。 C中的字符串以null結尾,所以當你通過管道發送它們時,receiver(parent)不知道字符串結束的位置。 Strlen確實計算了一個字符串中的字符數,但不包括空字符。你應該這樣做:

write(pfd[1], fruit[i], (strlen(fruit[i]))+1); 

家長現在可以知道何時何地拆分你的字符串。

另一個問題是,您還需要在parrent中循環。你需要在循環中設置一個條件來檢查EOF。在你的例子中,你知道你會得到4個水果,你可以循環4次。

關閉不需要的管道讀寫端部是一個很好的做法。在你的例子中,孩子應該關閉閱讀結束,而父母應該關閉寫作結束。你可以這樣做:

close(pfd[0]); //use this in child 

close(pfd[1]); //use this in parent 

你也應該習慣關閉所有你不需要的描述符。在你的例子中,在完成寫/讀操作之後,你應該關閉子進程和父進程的管道。這樣,您可以創建一個讀取循環條件,在EOF之後關閉。 (當孩子關閉管道,接收器可以結束)

作爲一個額外的小費,嘗試錯誤與「PERROR」 http://www.tutorialspoint.com/c_standard_library/c_function_perror.htm

+0

報告我應該把close()方法的每個相應迴路內部或外部的語句?我按照你的建議改變了strlen(),爲父循環做了另一個循環來循環和讀取pipe,並且把兩個close()語句放在循環之外。仍然沒有得到正確的輸出。此外,我有點困惑,如果和在哪裏,我應該添加一個wait()或waitpid()父。在循環?外?我已經嘗試了兩種,但我一定是做錯了。 – SherMM 2014-09-24 15:12:44

+0

我現在不在家裏的電腦上,所以我無法測試你的解決方案是否有效。我會盡快回家。 您應該在您的子進程中關閉pfd [0],並關閉父進程中的pfd [1]。在你成功分叉後,你不得不關閉它們一次,而不是循環。你能告訴我你得到了什麼樣的輸出?也許寫你寫的新循環,所以我可以看到代碼? 我會在幾個小時內發佈一個工作解決方案,當我回到家時,我可以自己測試它。 – IamSneaky 2014-09-25 07:11:58

+0

現在對我來說同樣的情況。有機會的時候我會發布代碼。我運行它只是一個整數列表,而不是原來的水果列表,它的工作。我認爲這可能與正在閱讀的字符串有關係 – SherMM 2014-09-25 13:51:33