父进程在调用waitpid后挂起

时间:2017-08-16 00:33:03

标签: c pipe

当我在gdb中运行它时,父级挂起在waitpid,我不知道为什么。父母应该从argv获取参数并通过管道将它们发送给孩子。那么父母应该通过它的回报从孩子那里得到论据的总和。不知道为什么要这样做。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/poll.h>

static int myPipe[2];

int main(int argc, char **argv)
{
    pid_t pid;
    int value;
    int status;
    // set up pipe

    if(pipe(myPipe))
    {
        printf("pipe error\n");
        return -1;
    }

    // call fork()
    printf("CS201 - Assignment 3 Premium - I. Forgot\n");
    pid = fork();
    if (pid == 0) {
        // -- running in child process --
        int     sum = 0;
        close(myPipe[1]);

        for(int i = argc; i > 1; i--)
        {
            read(myPipe[0], &value, sizeof(value));
            sum += value;
        }

        // Return sum of numbers.
        return sum;
        }
    else {
        // -- running in parent process --
        int sum = 0;
        close(myPipe[0]);

for(int i = argc; i > 1; i--)
        {
            value = atoi(argv[i-1]);
            write(myPipe[0], &value, sizeof(value));
        }
        waitpid(pid, &status, 0);
        sum = status;

        printf("sum = %d\n", sum);
        return 0;
        }

1 个答案:

答案 0 :(得分:1)

你的问题是,在父母中,你小心地关闭myPipe[0],然后神秘地决定写信给它而不是仍然打开myPipe[1]。如果您错误地检查了系统调用,则表示您未能向孩子发送任何数据。实际上,孩子仍然在等待数据到达,并且不会退出,并且父母正在等待不会退出的孩子退出,所以你有一个死锁。

我正在使用stderr.cstderr.h中的错误报告功能 - GitHub(https://github.com/jleffler/soq/tree/master/src/libsoq)提供的代码可以报告错误(和进度)。< / p>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include "stderr.h"

static int myPipe[2];

int main(int argc, char **argv)
{
    pid_t pid;
    int value;
    int status;
    err_setarg0(argv[0]);
    err_setlogopts(ERR_PID|ERR_MICRO);

    if (pipe(myPipe) != 0)
        err_syserr("pipe failed: ");

    // call fork()
    printf("CS201 - Assignment 3 Premium - I. Forgot\n");
    pid = fork();
    if (pid < 0)
        err_syserr("fork failed: ");
    else if (pid == 0)
    {
        // -- running in child process --
        int sum = 0;
        if (close(myPipe[1]) != 0)
            err_syserr("failed to close write end of pipe in child: ");

        for (int i = argc; i > 1; i--)
        {
            if (read(myPipe[0], &value, sizeof(value)) != sizeof(value))
                err_syserr("failed to read from parent: ");
            sum += value;
        }
        if (close(myPipe[0]) != 0)
            err_syserr("failed to close read end of pipe in child: ");

        err_remark("Exiting: sum = %d\n", sum);
        return sum;
    }
    else
    {
        // -- running in parent process --
        int sum = 0;
        close(myPipe[0]);

        for (int i = argc; i > 1; i--)
        {
            value = atoi(argv[i - 1]);
            err_remark("Writing: %d\n", value);
            if (write(myPipe[1], &value, sizeof(value)) != sizeof(value))
                err_syserr("failed to write to child: ");
        }
        if (waitpid(pid, &status, 0) != pid)
            err_syserr("failed to wait for child %d: ", pid);
        sum = status;

        printf("sum = %d\n", sum);
        if (WIFEXITED(status))
            printf("exit status: %d\n", WEXITSTATUS(status));
        return 0;
    }
}

示例输出(fp71.c中的源代码,程序fp71):

$ gcc -O3 -g -I./inc -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
>     -Wstrict-prototypes fp71.c -o fp71 -L./lib -lsoq 
$ fp71 1 2 4 7
CS201 - Assignment 3 Premium - I. Forgot
fp71: 2017-08-15 20:11:48.453688 - pid=86097: Writing: 7
fp71: 2017-08-15 20:11:48.454267 - pid=86097: Writing: 4
fp71: 2017-08-15 20:11:48.454275 - pid=86097: Writing: 2
fp71: 2017-08-15 20:11:48.454281 - pid=86097: Writing: 1
fp71: 2017-08-15 20:11:48.454348 - pid=86098: Exiting: sum = 14
sum = 3584
exit status: 14
$

十进制值3584对应于十六进制0x0E00。如果你使用WIFEXITED()WEXITSTATUS对其进行分析,则相当于14,正如您所期望的那样。 (另见Exit values bigger than 255 — possible?