【问题标题】:communication between parent and child through pipe父子之间通过管道进行通信
【发布时间】:2022-02-06 16:28:50
【问题描述】:

我想要一个父母和孩子互相交谈的程序。 所以输出将是:

  • p:值
  • c: 值
  • p: 单词
  • c: 字

等等……

下面是一个代码示例,其中输出首先与父级对话,然后在子级对话。 如何更正代码?

    for(int i=0; i<N; i++){
            pid=fork();
            if(pid==-1){
                    perror("fork\n");
                    exit(EXIT_FAILURE);
            }
            else if(pid==0){
                    srand(time(NULL));
                    int c;
                    read(fd[i][0], &c, 1);
                    printf("c: value: %d\n", c);
                    char word[c];
                    read(fd[i][0],&word, sizeof(word));
                    printf("c: word: %s\n", word);
                    int sum;
                    sum=c*i;
                    write(fd[i][1], &sum, sizeof(int));
                    printf("c: sended %d\n", sum);
                    int flag=0;
                    printf("flag :%d\n", flag);
                    read(fd[i][0], &flag, sizeof(int));
                    printf("c: flag= %d ->exit\n", flag);
                    exit(1);
            }else{
                    int c;
                    c=rand()%100+1;
                    write(fd[i][1], &c, sizeof(int));
                    printf("p: value: %d\n", c);
                    char word[c];
                    write(fd[i][1], &word, sizeof(word));
                    printf("p: word: %s\n", word);
                    int sum;
                    read(fd[i][0], &sum, sizeof(int));
                    printf("p: sum is: %d\n", sum);
                    int flag=1;
                    write(fd[i][1], &flag, sizeof(int));
                    printf("par: flag exit %d\n", flag);
                    wait(NULL);
            }
    }

【问题讨论】:

  • 首先,您需要在分叉之前为随机数生成器播种。在子进程中调用srand 不会影响父进程在调用rand 时。其次,您应该始终检查readwrite 返回的内容。第三,您只将 一个 字节读入c,但c 是多字节类型(int 通常是四个字节)。这意味着c 中的大多数位将是indeterminate(将它们视为垃圾)。这也意味着父进程写入的三个字节不会在第一次read 调用中被读取,而是稍后用于错误的数据。
  • 我已经纠正了这些错误,但没有改变任何东西。输出首先让父母“交谈”,然后是孩子,所以他们不交换任何信息。
  • 请记住,管道只有一种方式。如果您需要发送和接收,则需要 两个 管道。
  • 为此我有一个二维数组,值 0->read, 1->write
  • 不,这是不对的,索引01 是同一管道的一部分。您需要两个独立的管道,它们由对pipe 的两个不同调用创建。喜欢int pipes[2][2]; pipe(pipes[0]); pipe(pipes[1]); 然后父母可以使用例如pipes[0][0] 阅读和pipes[1][1] 写作,而孩子使用pipes[1][0]pipes[0][1]

标签: c process synchronization pipe parent-child


【解决方案1】:

要在两个进程之间进行双工通信,您需要两个管道:

  1. 一个用于父母与孩子之间的交流;
  2. 还有一个供孩子与父母交流

如果您对两者使用相同的管道,那么您最终可能会遇到这样的情况,例如孩子向管道写入内容,然后直接再次读回(而父级将永远看不到数据)。

这可能发生在例如

write(fd[i][1], &sum, sizeof(int));
// ...
// Could read sum that was written just above in the same process
read(fd[i][0], &flag, sizeof(int));

在您的子进程中。

对于上面显示的 writeread 调用的示例,您可以有类似的内容:

int parent_to_child[2];  // Pipe where parent process write and child reads
int child_to_parent[2];  // Pipe where parent process reads and child writes

pipe(parent_to_child);
pipe(child_to_parent);

// ...

pid = fork();
if (pid == 0)
{
    // Other code...

    // Child writes to parent
    write(child_to_parent[1], &sum, sizeof(int));

    // Child reads from parent
    read(parent_to_child[0], &flag, sizeof(int));

    // ...
}
else
{
    // Other code...

    // Parent reads from child
    read(child_to_parent[0], &sum, sizeof(int));

    // Parent writes to child
    write(parent_to_child[1], &flag, sizeof(int));

    // ...
}

【讨论】:

  • 非常感谢。现在很清楚了!
猜你喜欢
  • 2011-12-22
  • 2020-04-09
  • 2022-12-10
  • 2010-12-26
  • 1970-01-01
  • 1970-01-01
  • 2017-09-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多