2010-05-20 98 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