Tawm
Tawm

Reputation: 545

C: Using Fork() and Pipe() to add numbers in child processes

I'm trying to send numbers from a file to child processes with fork() and pipe(), which the child processes should add and send back to the parent process which will then add the child sums to get a total sum.

For a simplified version of that problem, I've got an Array of 4 numbers, and am only using 1 Child process (2 pipes).

I'm having difficulties seeing where control in my program goes, which makes it hard for me to troubleshoot what else is going wrong.

int main(int argc, char *argv[])
{
int numChildProcesses = 1;
int testArray[4] = {2,7,9,4};

printf("Will use 1 child process; %d pipes.\n", numChildProcesses*2);
int fd[numChildProcesses*2][2]; //parent and child

int val = 0, len, i;

// create all the descriptor pairs we need
for (i=0; i<numChildProcesses*2; ++i) // 2 pipes // parent + child
{
    if (pipe(fd[i]) < 0)
    {
        perror("Failed to allocate pipes.");
        exit(EXIT_FAILURE);
    }
}

for (i=0;i<numChildProcesses;i++)
{

    //CHILD/////////////////////////////////////////////////////////////////////
    if (fork() == 0)
    {
        int total = 0, xCount = 0;

        while (xCount < 4)
        {
            // wait for parent to send us a value
            len = read(fd[i][0], &val, sizeof(val));
            if (len < 0)
            {
                perror("Child: Failed to read data from pipe.\n");
                exit(EXIT_FAILURE);
            }
            else if (len == 0)
            {
                // not an error, but certainly unexpected
                fprintf(stderr, "Child: Read EOF from pipe\n");
            }
            else // Successfully read from Parent
            {
                total += val;
                xCount += 1;
                printf("Child: Recieved %d\tTotal: %d\tCount: %d\n", val, total, xCount);

            }
        }

        // send the value back to the parent
        printf("Child: Sending %d back\n", total);
        if (write(fd[i][1], &total, sizeof(total)) < 0)
        {
            perror("Child: Failed to write response value");
            exit(EXIT_FAILURE);
        }

        return EXIT_SUCCESS;
    }

    //PARENT/////////////////////////////////////////////////////////////////////
    if (fork() > 0)
    {
        int total = 0;

        // send array to child as well as starting point
        printf("\nParent: Sending numbers to child\n");
        //if (write(fd[i][1], 0, (fileNumbers/numChildProcesses)*5) != sizeof((fileNumbers/numChildProcesses)*5));
        if (write(fd[i][1], &testArray, sizeof(testArray)) != sizeof(testArray))
        {
            perror("Parent: Failed to send value to child ");
            exit(EXIT_FAILURE);
        }

        // now wait for a response
        len = read(fd[i][0], &val, sizeof(val));
        if (len < 0)
        {
            perror("Parent: failed to read value from pipe");
            exit(EXIT_FAILURE);
        }
        else if (len == 0)
        {
            // not an error, but certainly unexpected
            fprintf(stderr, "Parent: Read EOF from pipe\n");
        }
        else
        {
            // report what we received
            total += val;
            printf("Parent: Received %d\tTotal: %d\n", val, total);
        }

        // wait for child termination
        wait(NULL);
    }
}

}


My output is as follows:

Will use 1 child process; 2 pipes.

Parent: Sending numbers to child
Parent: Received 2      Total: 2
Child: Recieved 7       Total: 7        Count: 1
Child: Recieved 9       Total: 16       Count: 2
Child: Recieved 4       Total: 20       Count: 3

Furthermore, if I try something like printf("%d", fork()); as soon as I enter my for() loop to see what it taking control, it gets a little crazy. It acts like using fork() affects the way the program runs, as if it is a pop() or something of the sort.


Anyways, thank you for any insight you can offer.

-Tom

Upvotes: 0

Views: 3840

Answers (1)

Snild Dolkow
Snild Dolkow

Reputation: 6866

You're forking too much. You're calling fork() twice in your loop: once in your "child" if, and one in your "parent" if. And then even more when you add your printf("%d", fork());.

You should only call fork() once per loop. Save the return value in a variable, then print/check it.

Upvotes: 2

Related Questions