如何使用管道来保持子进程中的值?

时间:2013-11-29 20:42:55

标签: c

以下是我目前的一段代码:

pipe(pipes);
int count = 0, t = 0;
int forks[numForks];
for(j = 1; j<=numForks; j++){
    if((pid=fork()) == 0){
        count = findKey(in, key, buf, j, count);
        close(pipes[0]);
        write(pipes[1],&count, sizeof(count));
        exit(0);
    }else{ 
        close(pipes[1]);
        read(pipes[0], &t, sizeof(t));
    }
}
count = t;
printf("count = %i\n", count);

我创造了n个孩子。在每个子节点中,他们扫描文本文件的不同部分并返回它找到关键字的次数。孩子都只阅读文本文件的某个部分。有时候孩子可能在它自己的部分找不到关键字所以它显然会返回0.在我正在使用的测试用例中,count的最终值应为1但最后的值为0因为我不认为我正在使用管道正确保存每个值。我知道其中一个孩子确实找到了关键字,因为如果我在if语句中的函数调用之后放了一个print语句,那么在某个时候,count是1。

基本上我想把所有的count值加起来。

3 个答案:

答案 0 :(得分:2)

父进程

{
    close(pipes[1]);
    read(pipes[0], &t, sizeof(t));
}

numForks次。因此,只有第一个孩子获得一个开放的写入描述符pipes[1],并且每个read都会覆盖t,只留下最后一个值。

答案 1 :(得分:1)

您的父进程会覆盖循环中前一个子进程的返回值。

试试这个:

pipe(pipes);
int count = 0, t = 0;
int forks[numForks];
for(j = 1; j<=numForks; j++){
    if((pid=fork()) == 0){
        count = findKey(in, key, buf, j, count);
        close(pipes[0]);
        write(pipes[1],&count, sizeof(count));
        exit(0);
    }else{ 
        close(pipes[1]);
        read(pipes[0], &t, sizeof(t));
        count += t;
    }
}
printf("count = %i\n", count);

答案 2 :(得分:1)

您需要在其他答案和我的评论中概述的两个修补程序:

  

此时,孩子们同步执行,一次只执行一个孩子,因为在循环运行下一个孩子之前等待孩子的响应。您应该在count += t;之后使用read()。您还应该检查更多系统调用。此外,第二个和后续子节点无法写入父节点,因为父节点已关闭管道的写入端。您必须为每个子项创建(并关闭)管道,或者您必须将写入结束打开直到完成。

这导致了这样的代码:

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

enum { numForks = 5 };

static int findKey(void)
{
    return getpid() % numForks;
}

int main(void)
{
    int j;
    int pipes[2];
    pipe(pipes);
    int count = 0, t = 0;
    for (j = 1; j <= numForks; j++)
    {
        pid_t pid;
        if ((pid = fork()) == 0)
        {
            count = findKey();
            close(pipes[0]);
            write(pipes[1], &count, sizeof(count));
            exit(0);
        }
    }

    close(pipes[1]);
    while (read(pipes[0], &t, sizeof(t)) == sizeof(t))
    {
        printf("Got %d\n", t);
        count += t;
    }

    printf("count = %i\n", count);
    return 0;
}

示例运行:

Got 0
Got 1
Got 2
Got 3
Got 4
count = 10

显然,这是使用虚拟findKey()函数。另请注意最基本的调试技术:在读取数据时打印数据。它也会异步运行子进程。他们在这里做的不多。代码仍然不会检查除read()之外的任何系统调用,这是懒惰的。