【问题标题】:Communication between parent and child父母与孩子之间的沟通
【发布时间】:2011-02-21 20:31:03
【问题描述】:

我必须编写一个简单的 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;
}

但是我的孩子从来没有被叫过。我的代码有问题吗? 感谢您的帮助!

【问题讨论】:

标签: c process operating-system fork parent-child


【解决方案1】:

感谢约瑟夫,它运行良好! 我试图用内存分段来做到这一点,但我遇到了同样的问题-_-


#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;
}

【讨论】:

  • 我认为这里的问题是你在 hand() 中调用 shmdt() 太快了(在使用 CYGWIN 进行测试时)。
【解决方案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;
}

【讨论】:

  • 我试过你的解决方案,效果很好。谢谢 !我发布了一个使用内存分段但不成功的代码:(
  • 完全省去信号处理程序,直接调用孩子当前调用signal(); pause();finalResult()函数会更可靠。在这种情况下,管道将负责同步;使用当前代码,子进程可能会错过信号,因为无法保证它会在父进程执行 kill() 之前执行 signal()
  • @caf:我同意你的两个观点:信号在这里是不必要的并且可以说是错误的,并且调用 signal() 太晚了代码是不正确的。我确实是想说第二个,这可能是最初问题的原因——“我的孩子从来没有被叫过”——而是只关注主要的误解,这令人惊讶地普遍存在。
  • 当然 printf() 不是信号处理程序的 POSIX.1 安全函数。
【解决方案3】:

当父调用kill()时,可能是子还没有执行signal()调用。

【讨论】:

  • 您可以从孩子向父母发送信号。
  • 是的,但我认为这不是解决方案,因为这是最后必须阅读的孩子。我有点迷路了……
  • 您可以简单地在父块的开头添加对sleep(1) 的调用。这样,您可以确保*孩子在您杀死时已准备好。 (*肯定在 99.9999999 %)也许 sleep(0) 可以解决问题?
猜你喜欢
  • 2011-02-20
  • 1970-01-01
  • 2021-04-25
  • 2020-01-29
  • 2019-02-04
  • 2019-05-22
  • 2014-02-16
  • 2017-07-01
  • 1970-01-01
相关资源
最近更新 更多