2016-03-11 120 views
0

這是前兩個問題(醜陋的代碼;由我刪除)的更簡潔的最終版本。使用Fork()和Pipe()將文件拆分爲多個子進程

我使用pipe()fork()來總結子進程中的文件的內容。爲此,我根據孩子的數量均勻分割文件:

文件中的1000行=> 2個子進程=>第一個子項總和線1-500;第二個孩子總計第501-1000行=>將總計發回給父母以將他們的每個總數相加。因此,找到了整個文件的總數。


這裏是我的代碼:

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

int main(int argc, char *argv[]) 
{ 
int numchild; 
int fd[2*numchild][2]; //parent+child pipe 
int i, j, len, fpos=0, val, count=0, total=0; 
pid_t pid; 
int nums = 1000; 
FILE * file; 

printf("How many children to use: "); 
scanf("%d", &numchild); 
printf("\nWill use %d child process(es).\n", numchild); 

// create all pipes 
for (i=0; i<numchild; i++) 
{ 
    pipe(fd[i]); 
} 

for (i=0; i<numchild; i++) 
{ 
    if((pid = fork()) == 0) // child process 
    { 
     pid = getpid(); 

     // read from parent 
     len = read(fd[i][0], &fpos, sizeof(fpos)); 
     if (len > 0) 
     { 
      file = fopen("file1.dat", "r"); 
      fseek (file, fpos, SEEK_SET); 
      count = 0; 
      total = 0; 

      printf("Child(%d): Recieved position: %d\n", pid, fpos); 

      // read from file starting at fpos 
      // add values read to a total value 
      while (count < (nums/numchild)) 
      { 
       fscanf(file, "%i", &val); 
       total += val; 
       count++; 
      } 
      //write to parent 
      write(fd[i+numchild][1], &total, sizeof(total)); 
      printf("Child(%d): Sent %d to parent.\n", pid, total); 
     } 
     else 
     { 
      printf("Child(%d): Error with len\n", pid); 
     } 

     _exit; 
    } 

    // parent process 
    pid = getpid(); 

    fpos = ((i*nums*5)/numchild); // 5 is the offset of the file values 

    // write to child process 
    printf("Parent(%d): Sending file position to child\n", pid); 
    write(fd[i][1], &fpos, sizeof(fpos)); 

    // wait for child responce 
    len = read(fd[i+numchild][0], &total, sizeof(total)); 
    if (len > 0) 
    { 
     printf("Parent(%d): Recieved %d from child.\n", pid, total); 
     total += total; 
     printf("Parent(%d): Total: %d\n", pid, total); 
    } 
    else 
    { 
     printf("Parent(%d): Error with len\n", pid); 
    } 
} 
} 

輸出:

Will use 1 child process(es). 
Parent(5497): Sending file position to child 
Child(5498): Recieved position: 0 
▒▒Child(5498): Sent 454019 to parent. //**yes this weird mark shows up** 
Parent(5498): Sending file position to child 
//hangs 

Will use 2 child process(es). 
Parent(5898): Sending file position to child 
Child(5899): Recieved position: 0 
▒|Child(5899): Sent 228601 to parent. 
Parent(5899): Sending file position to child 
//hangs 

Will use 4 child process(es). 
Parent(5904): Sending file position to child 
Child(5905): Recieved position: 0 
▒Child(5905): Sent 118304 to parent. 
Parent(5905): Sending file position to child 
//hangs 

的代碼工作正常,一個孩子在那裏我可以看到的總和上來,但它掛起和家長從不承認來自孩子的輸入。因此,如果我使用2個孩子,我只能看到1-500行的總和。如果我使用4個孩子,我只能看到1-250行的總和。

在第一個孩子將結果發送回父母之後,我在做什麼來掛斷我的程序?

我的代碼是否允許孩子們同時工作?


感謝您的幫助。

-Tom

+3

由於所有這些複雜性,它比使用一個進程更可能慢得多 - 限制因素是讀取文件的速度 –

+0

@EdHeal目標是瞭解從文件讀取時我的程序運行速度如何受到影響非常大的尺寸:1000行,10,000行,100,000行,1,000,000行等。 – Tawm

+1

爲什麼在每個子循環結束時調用'wait(NULL)'?這會導致循環在開始子節點N + 1之前等待子節點N.該點不是多處理? – antiduh

回答

3

你不初始化所有的管道。爲了簡單起見,我們假設你有四個孩子。

然後在這裏,你一共有8管,16個文件描述符分配房間:

int fd[2*numchild][2]; //parent+child pipe 

到目前爲止好;父母需要專門的管道來寫信給孩子,反之亦然,孩子可以寫信給父母。

但是,你不正確初始化你的水管:

for (i=0; i<numchild; i++) 
{ 
    pipe(fd[i]); 
} 

這只是初始化8個文件描述符,而不是16.你需要做的是for(i = 0; i < 2*numchild; i++)。上面這個循環有初始化的效果:

fd[0][0] 
fd[0][1] 
fd[1][0] 
fd[1][1] 
fd[2][0] 
fd[2][1] 
fd[3][0] 
fd[3][1] 

然後,因爲你沒有初始化你的水管正確,你讀取和寫入錯誤的管道;具體而言,如果您足夠幸運地將fd初始化爲全零,那麼您可能正在讀寫標準輸出。

這解釋了爲什麼它會死鎖 - 您沒有閱讀到您打算寫入的管道。這就解釋了爲什麼你在標準輸出中出現奇怪的輸出:你正在將fpos寫入錯誤的文件描述符,因爲fd未完全初始化;您正在編寫fpos到文件描述符0,又名標準輸出。

+0

謝謝你的解釋。現在它運行得更好,但我仍然遇到問題。一個問題是,即使只有一個孩子要寫信給我,我的父母仍然試圖寫信給另一個孩子。父母然後獲得總數並掛起。另一個是,當我嘗試在末尾添加一些代碼'alltotal + = total'時,我需要初始化一個'int alltotal;'。 'int alltotal;'很好,但是當我把它設置爲'int alltotal = 0;'時,我得到'Segmentation fault(核心轉儲)'。你知道這些錯誤可能來自哪裏嗎?我會在原始帖子中更新我的代碼。 – Tawm

+0

@Tawm - 我們修復了一個問題 - 管道的初始化。另一個問題應該是一個全新的問題,否則,試圖追蹤每個問題和答案會變得非常混亂。所以我會編輯你的問題回到它是什麼,然後用你的新問題創建一個新的問題。爲了讓你開始:你看過核心文件嗎?確保你在你的新問題中發佈你的核心文件分析。 – antiduh

+0

我會開始一個新的問題。但之前,核心文件是什麼意思? – Tawm