【问题标题】:C: Using Fork() and Pipe() to add numbers in child processesC:使用 Fork() 和 Pipe() 在子进程中添加数字
【发布时间】:2016-03-08 21:11:41
【问题描述】:

我正在尝试使用 fork()pipe() 将数字从文件发送到子进程,子进程应添加这些数字并将其发送回父进程,然后父进程将添加子总和以获得总和.

对于该问题的简化版本,我有一个由 4 个数字组成的数组,并且只使用 1 个子进程(2 个管道)。

我很难看到我的程序中的控制权在哪里,这让我很难排除其他问题。

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

}


我的输出如下:

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

此外,如果我一进入for() 循环就尝试printf("%d", fork()); 之类的东西,看看它在控制什么,它会变得有点疯狂。它的作用就像使用fork() 会影响程序的运行方式,就好像它是pop() 或类似的东西。


无论如何,感谢您提供的任何见解。

-汤姆

【问题讨论】:

    标签: c pipe fork


    【解决方案1】:

    你分叉太多了。您在循环中调用了两次fork():一次在您的“孩子”if 中,一次在您的“父母”if 中。当您添加 printf("%d", fork()); 时,甚至更多。

    每个循环您应该只调用一次fork()。将返回值保存在变量中,然后打印/检查。

    【讨论】:

    • 谢谢。现在我的输出更干净了,但是父级仍然只调用一次,所有其他循环都直接转到子级。在 1 个父输出和 3 个子输出后,程序挂起。有什么想法吗?
    • 您创建了 2 个管道,但父子节点正在读取和写入同一个管道——您从不使用第二个管道。您父母的读取正在从它刚刚写入的值中窃取第一个值,从而使孩子的一个值太少;所以它永远不会退出。您应该使用管道2*i 进行一种通信,而2*i+1 用于另一种通信方式。
    • 非常感谢。这对我来说很清楚。但是,我想知道您为什么不建议我使用 ii+1 而不是 2i2i+1
    • 因为当您开始使用更多子进程时,您将使用管道 0 和 1 进行第一个循环,然后使用 1 和 2 进行第二个循环,2 和 3 进行第三个循环,依此类推。我们已经看到了在多个进程中使用同一管道的问题。使用2 * i,第一个循环有 0 和 1,第二个循环有 2 和 3,第三个循环有 4 和 5。你也可以使用ii + numChildProcesses,在第一次迭代中给你(如果你有4个numChildProcesses)0和4,在第二次中给你1和5,在第三次中给你2和6......跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-07
    • 2013-05-28
    • 1970-01-01
    • 2011-07-02
    • 2021-12-07
    • 2012-09-12
    • 1970-01-01
    相关资源
    最近更新 更多