2010-05-20 170 views
2

我必須編寫一個簡單的C應用程序來創建一個進程和一個子進程(fork()),我必須執行一個操作。父母初始化值和子計算。我寫這個:父母與子女之間的溝通

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

typedef struct { 
    int op1; 
    char op; 
    int op2; 
} Operation; 

Operation *varOP; 

void finalResult() 
{ 
    float result = 0; 
    if(varOP->op == '+') result = (varOP->op1 + varOP->op2); 
    if(varOP->op == '-') result = (varOP->op1 - varOP->op2); 
    if(varOP->op == '*') result = (varOP->op1 * varOP->op2); 
    if(varOP->op == '+') result = (varOP->op1/varOP->op2) 
    printf("%f",result); 
} 

int main() { 
    int p; 
    varOP = (Operation *)malloc(sizeof(Operation)); 
    p = fork(); 
    if(p == 0) // If child 
    { 
     signal(SIGUSR1, finalResult); 
     pause(); 
    } 

    if(p > 0) // If parent 
    { 
     varOP->op = '+'; 
     varOP->op1 = 2; 
     varOP->op2 = 3; 
     kill(p, SIGUSR1); 
     wait(NULL); 
    } 
    return 0; 
} 

但我的孩子從來沒有被稱爲。我的代碼有問題嗎? 感謝您的幫助!

+2

一時間,這聽起來像這個問題應該已經對http://answers.modernfather.com/: ) – Thorarin 2010-05-20 12:49:17

+0

Ahah不是真的一樣的問題;) – Pierre 2010-05-20 12:56:20

回答

2

你的示例代碼也有一個更基本的問題:每個進程都有自己的數據空間,所以你通過堆向孩子發送信息的技術將不起作用。一種解決方案是使用管道。這隻增加了四行代碼:

typedef struct { 
    int op1; 
    char op; 
    int op2; 
}Operation; 

Operation *varOP; 

static int pipe_fds[2]; /* <-- added */ 

static void finalResult(void) 
{ 
    float result = 0; 
    read(pipe_fds[0], varOP, sizeof(Operation)); /* <-- added */ 
    if(varOP->op == '+') result = (varOP->op1 + varOP->op2); 
    if(varOP->op == '-') result = (varOP->op1 - varOP->op2); 
    if(varOP->op == '*') result = (varOP->op1 * varOP->op2); 
    if(varOP->op == '/') result = (varOP->op1/varOP->op2); /* <-- typo */ 

    printf("%f\n",result); 
} 

int main (void) 
{ 
    int p; 
    pipe(pipe_fds); /* <-- added */ 
    varOP = (Operation *)malloc(sizeof(Operation)); 
    p = fork(); 

    if(p == 0) // If child 
    { 
     signal(SIGUSR1, finalResult); 
     pause(); 
    } 

    if(p > 0) // If parent 
    { 
     varOP->op = '+'; 
     varOP->op1 = 2; 
     varOP->op2 = 3; 
     write(pipe_fds[1], varOP, sizeof(Operation)); /* <-- added */ 
     kill(p, SIGUSR1); 
     wait(NULL); 
    } 

    return 0; 
} 
+0

我試過你的解決方案,它運行良好。謝謝 !我發佈了一個使用內存分割但不成功的代碼:( – Pierre 2010-05-20 15:42:43

+0

)完全放棄信號處理程序並直接調用子句當前調用signal();暫停()的'finalResult()'函數會更可靠。 '在這種情況下,管道將負責同步;對於當前的代碼,孩子可能會錯過信號,因爲不能保證在父執行kill()之前它會執行'signal()'。 – caf 2010-05-21 00:33:36

+0

@ caf:我同意你的觀點:信號在這裏是不必要的也可能是錯誤的,通過調用signal()太遲,代碼是不正確的。我的意思是提到第二個,這可能是原始問題的原因 - '我的孩子從來沒有被稱爲' - 而只是集中在主要的誤解,這是令人驚訝的普遍。 – 2010-05-21 02:44:46

0

當父母呼叫kill()時,可能是孩子尚未執行signal()調用。

+0

是的,我同意你,但我不知道如何解決它:( – Pierre 2010-05-20 12:48:22

+0

你可以發送一個信號從孩子到父母 – Rudi 2010-05-20 12:57:07

+0

是的,但我不認爲它是解決方案,因爲這是最後必須讀的孩子,我有點失落...... – Pierre 2010-05-20 13:01:13

1

謝謝約瑟夫它工作得很好! 我試圖與內存segementation做到這一點和我有同樣的問題-_-


#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 

typedef struct { 
    int op1; 
    char op; 
    int op2; 
}Operation; 


int id; 

void hand() 
{ 
    Operation *varOP = (Operation*) shmat(id, NULL, SHM_R); 
    shmdt((char *) varOP): 
    float result = 0; 

    switch (varOP->op) { 
     case '+': 
      result = (varOP->op1 + varOP->op2); 
      break; 
     case '-': 
      result = (varOP->op1 - varOP->op2); 
      break; 
     case '*': 
      result = (varOP->op1 * varOP->op2); 
      break; 
     case '/': 
      result = (varOP->op1/varOP->op2); 
      break; 
     default: 
      result = 0; 
      break; 
    } 

    printf("%f",result); 
    exit(0); 
} 

int main() { 

    int p; 
    key_t cle; 

    p = fork(); 

    cle = ftok(getenv("titi"), 'A'); 
    id = shmget(cle, sizeof(Operation),0); 

    if(p == 0) // Si fils 
    { 
     signal(SIGUSR1,hand); 
     while (1); 
     exit(0); 
    } 

    if(p > 0) 
    { 
     Operation *varOP = (Operation*) shmat(id, NULL, SHM_W); 
     varOP->op = '+'; 
     varOP->op1 = 2; 
     varOP->op2 = 3; 
     shmdt((char *) varOP); 
     kill(p, SIGUSR1); 

     wait(NULL); 
    } 

    return 0; 
} 
+0

我認爲t他在這裏的問題是手頭()你太快調用shmdt()(用CYGWIN測試)。 – 2010-05-20 18:22:15

+0

是的你是對的。現在很好。謝謝 ! – Pierre 2010-05-21 05:41:36