简体   繁体   中英

How do I use pipe to keep the value that is in a child process?

Here is a snippet of code I have currently:

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);

I create n number of children. In each child they scan through a different part of a text file and return the number of times it finds a keyword. The child are all reading only a certain portion of the text file. Sometimes the child may not find the keyword in it's own portion so it obviously returns 0. In the test case I'm using, the final value of count should be 1 but at the end the final value is 0 because I don't think I'm using pipe to save each value correctly. I know that at some point one of the children does actually find the keyword because if I put a print statement after the function call in my if statement, at some point count is 1.

Basically I want to add up all the values of count.

The parent process does

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

numForks times. So only the first child gets an open write descriptor pipes[1] , and each read overwrites t , leaving only the last value.

Your parent process is overwriting the return value from the previous child in your loop.

Try this:

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);

You need both the fixes outlined in the other answers, and in my comments:

At the moment, the children execute synchronously, one child at a time, because you wait for a response from the child before looping to run the next one. You should be using count += t; after the read() . You should also be checking more of your system calls. Also, the second and subsequent children cannot write to the parent because the parent has closed the write end of the pipe. Either you have to create (and close) the pipe for each child, or you have to leave the write end open until you've finished.

That leads to code like this:

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

Example run:

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

Clearly, this is using a dummy findKey() function. Note also the most basic of debugging techniques: print the data as you read it. It does also run the children asynchronously. They aren't doing anything much here. The code still doesn't check any system call except the read() , which is lazy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM