2012-04-03 104 views
0

這個程序應該計算的值2^1 + 2^2 + ... + 2^10:計算N個功率的總和

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <stdbool.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <signal.h> 
#include <math.h> 

#define N 10 

// sommatoria per i che va da 1 a N di 2^i, ogni processo calcola un singolo valore 

int main(int argc, char** argv) 
{ 
    pid_t figli[N]; 
    unsigned int i; 
    int status; 
    int fd[N][2]; 
    int msg1=0,msg2; 
    int risultato=0; 
    bool padre=true; 
    for(i=0;i<N && padre;i++) 
    { 
     pipe(fd[i]); 
     figli[i]=fork(); 
     if(figli[i]<0) 
     { 
      fprintf(stderr,"Una fork ha fallito\n"); 
     } 
     else if(figli[i]==0) 
     { 
      padre=false; 
     } 
     else 
     { 
      msg1=i+1; 
      write(fd[i][1],&msg1,sizeof(int)); 
     } 
    } 
    if(!padre) 
    { 
     read(fd[i][0],&msg2,sizeof(int)); 
     msg2=pow(2.0,msg2); 
     write(fd[i][1],&msg2,sizeof(int)); 
     exit(0); 
    } 
    else 
    { 
     for(i=0;i<N;i++) 
     { 
      read(fd[i][0],&msg2,sizeof(int)); 
      risultato+=msg2; 
     } 
    } 
    if(padre) 
     fprintf(stderr,"%d\n",risultato); 
    return 0; 
} 

但當即xecute程序,父進程55打印。 爲什麼?

+4

您試圖以最複雜的方式解決一個簡單的問題,並想知道爲什麼它不起作用。爲什麼不嘗試簡單地做? – ugoren 2012-04-03 08:24:53

+3

它聞起來像家庭作業 – 2012-04-03 08:25:55

+0

這就是爲什麼你編程時需要數學。 – Matt 2012-04-03 08:27:25

回答

2

有趣的是,55是所有號碼從1到10的總和:應該給你的即時線索:

管()創建一個管道,單向數據通道,可以用於進程間通信。數組pipefd用於返回兩個指向管道末端的文件描述符。 pipefd [0]指的是管道的讀取結束。 pipefd [1]指的是管道的寫入結束。

注意井:單向。換句話說,padre正在讀取它寫入的相同值(因此爲55)。

您通常會設置兩個雙向流量管道,每個方向一個。所以我把管子的數量增加了一倍,甚至對於另一個方向使用padre-to-child和odd的管子。

另外,你的孩子繼續與神僕循環,而應立即退出該循環,使他們的i值是正確的。你確實有循環出口基於padre但這發生i已更改。您可以打破padre設置爲false或簡單地將i--設置爲if(!padre)位,以將i恢復爲該子項的正確值。我已經完成了後者。

下面的代碼(有標記顯示發生了什麼變化)工作好:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <assert.h> 
#include <stdbool.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <signal.h> 
#include <math.h> 

#define N 10 

int main(int argc, char** argv) 
{ 
    pid_t figli[N]; 
    unsigned int i; 
    int status; 
    int fd[N*2][2]; // CHANGED: two unidirectional pipes 
    int msg1=0,msg2; 
    int risultato=0; 
    bool padre=true; 
    for(i=0;i<N && padre;i++) 
    { 
     pipe(fd[i*2]); 
     pipe(fd[i*2+1]); // ADDED: create second pipe 
     figli[i]=fork(); 
     if(figli[i]<0) 
     { 
      fprintf(stderr,"Una fork ha fallito\n"); 
     } 
     else if(figli[i]==0) 
     { 
      padre=false; 
     } 
     else 
     { 
      msg1=i+1; 
      write(fd[i*2][1],&msg1,sizeof(int)); // CHANGED: pipe number 
     } 
    } 
    if(!padre) 
    { 
     i--; // ADDED: to restore i for the child 
     read(fd[i*2][0],&msg2,sizeof(int)); // CHANGED: pipe number 
     msg2=pow(2.0,msg2); 
     write(fd[i*2+1][1],&msg2,sizeof(int)); // CHANGED: pipe number 
     exit(0); 
    } 
    else 
    { 
     for(i=0;i<N;i++) 
     { 
      read(fd[i*2+1][0],&msg2,sizeof(int)); // CHANGED: pipe number 
      risultato+=msg2; 
     } 
    } 
    if(padre) 
     fprintf(stderr,"%d\n",risultato); 
    return 0; 
} 

這會產生2046的正確答案,因爲20 + 21 + ... 210 = 211 - 1和,因爲你留出兩到了零長期(等於1):21 + 22 + ... 210 is 211 - 2 (211 = 2048)

2

上面代碼的問題在於,同一個進程使用同一個管道進行寫入和讀取。 (這裏是父進程)。

父級將要計算的值通過管道傳遞給子級。孩子在同一管道中寫回答。父母讀回答。在這裏,你沒有考慮這種情況:父母將值寫入管道並自己讀取回復。因此,孩子從來沒有獲得價值。

爲了解決上述問題,必須創建兩個管道:

  1. 從父母管孩子
  2. 管,從孩子到家長

這將防止不同比賽條件和代碼會更可讀。 以下是執行相同操作的代碼。 PS:由於這可能是一項家庭作業,我不是給你確切的解決方案,而是給出了這個問題的概念。下次請使用英文作爲命名方案。這有助於人們調試你的代碼。

#include <stdio.h> 

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


int main(void) 
{ 
int msg; 
int child_pid; 
int parent_to_child[2]; 
int child_to_parent[2]; 



// my_pipe 
int ret_val = pipe(parent_to_child); 
if(ret_val!=0){ 
    printf("pipe command failed !!\n"); 
    exit(1); 
} 

// my_lock 
ret_val = pipe(child_to_parent); 
if(ret_val!=0){ 
    printf("pipe command failed !!\n"); 
    exit(1); 
} 

child_pid = fork(); 
if(child_pid==-1){ 

    printf("fork() failed !!\n"); 
    exit(1); 

}else if(child_pid==0){ 

    // i am child 
    read(parent_to_child[0], &msg, sizeof(int)); 
    printf("child got %d from parent \n", msg); 
    msg = 34; 
    write(child_to_parent[1], &msg, sizeof(int)); 

}else{ 

    // i am parent 
    msg = 24; 
    write(parent_to_child[1], &msg, sizeof(int)); 
    //sleep(2); 
    read(child_to_parent[0], &msg, sizeof(int)); 
    printf("parent got %d from child \n", msg); 

} 

return 0; 
}