【问题标题】:Program hangs after receiving proper result from child processes through pipe()通过 pipe() 从子进程接收到正确结果后程序挂起
【发布时间】:2016-03-11 21:55:47
【问题描述】:

我正在拆分一个文件,通过pipe() 发送,让孩子找到他们指定的文件部分的总和,通过pipe() 将计算的总和返回给父母,让父母计算总和子总和。

我有一个工作程序。我的问题是它在收到显示正确的最终值后挂起。

我不确定我在做什么让父母期待更多信息,但我敢打赌这与我的 for() loop 包含我的孩子代码有关。

这是我的代码:

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

int main(int argc, char *argv[])
{
int numchild;

int i, j, len, fpos=0, val, count=0, total=0, alltotal=0;
pid_t pid;
int nums = 1000;
FILE * file;

printf("How many children to use: ");
scanf("%d", &numchild);
printf("\nWill use %d child process(es).\n", numchild);

int fd[2*numchild][2]; //parent+child pipe

// create all pipes
for (i=0; i<2*numchild; i++)
{
    pipe(fd[i]);
}

for (i=0; i<numchild; i++)
{
    if((pid = fork()) == 0) // child process
    {
        pid = getpid();

        // read from parent
        len = read(fd[i][0], &fpos, sizeof(fpos));
        if (len > 0)
        {
            file = fopen("file1.dat", "r");
            fseek (file, fpos, SEEK_SET);
            count = 0;
            total = 0;

            printf("Child(%d): Recieved position: %d\n", pid, fpos);

            // read from file starting at fpos
            // add values read to a total value
            while (count < (nums/numchild))
            {
                fscanf(file, "%i", &val);
                total += val;
                count++;
            }
            //write to parent
            write(fd[i+numchild][1], &total, sizeof(total));
            printf("Child(%d): Sent %d to parent.\n", pid, total);
        }
        else
        {
            printf("Child(%d): Error with len\n", pid);
        }

        _exit;
    }

    // parent process
    pid = getpid();

    fpos = ((i*nums*5)/numchild); // 5 is the offset of the file values

    // write to child process
    printf("Parent(%d): Sending file position to child\n", pid);
    write(fd[i][1], &fpos, sizeof(fpos));

    // wait for child responce
    len = read(fd[i+numchild][0], &total, sizeof(total));
    if (len > 0)
    {
        printf("Parent(%d): Recieved %d from child.\n", pid, total);
        alltotal += total;
        printf("Parent(%d): Total: %d\n", pid, alltotal);
    }
    else
    {
        printf("Parent(%d): Error with len\n", pid);
    }
}
}

【问题讨论】:

  • 您希望语句_exit; 做什么?你的编译器对这条线有什么看法? 你现在说什么,恶魔?
  • @EOF 我认为它表明子进程已完成。这是不必要的吗?而且我的编译器没有给我消息,因为它不会产生错误。
  • 您使用的是哪个编译器?你是如何调用编译器的? _exit 应该在哪里声明?
  • @EOF 我只是在使用 gcc。我通过 linux 终端调用它。
  • 您使用类似_exit(0); 的方式调用_exit。你只有_exit;,它获取_exit 的地址,并且什么都不做。

标签: c pipe fork


【解决方案1】:

我不能再问更多问题了,但如果这是在 Linux 或类 Unix 系统上(可能都是 posix):

您必须为您的主程序中的每个子进程执行wait (man 2 wait),否则您将创建僵尸进程。

不知道您在什么环境中运行,我无法对此进行测试以确定这是否是您无法正常退出的原因。

另外(这更像是一条评论),通过循环的每个循环,您都在分叉一个孩子,然后为其提供数据,然后得到响应,然后打印总数。这真的是你想做的吗?如果您一次只运行一个子进程,则无需创建一堆管道。

我的猜测是你想要一些实际的并发性。您可以通过创建一个循环来创建所有子级,然后是另一个循环向它们提供数据,然后是第三个循环查看结果并将它们求和,然后是第四个循环,等待每个循环终止(到避免僵尸)。

我会考虑使用pollselect 来阅读回报——毕竟,不能保证孩子们会按顺序完成。

【讨论】:

  • 您能为此举一个简短的例子吗?我有一个想法,但我对 pipe() 以及父程序和子程序如何交互非常缺乏经验。
【解决方案2】:

在其他人让我知道这可能是修复它之前,我不会选择这个作为答案,但我相信我的程序挂起,因为 main() 函数实际上没有返回任何东西。当我进入时间收集(保存开始时间、结束时间、计算差异、输出)时,它必须在我的 for 循环之外完成,所以它是我的 main() 方法中的最后一条语句。这似乎已经停止了悬挂。

【讨论】:

    【解决方案3】:

    在你的 if 语句中调用 fork() 之后,你需要调用 wait()。这会导致您的父母等待您的孩子退出,然后在孩子退出时继续执行。

    【讨论】:

      猜你喜欢
      • 2016-12-02
      • 1970-01-01
      • 2014-06-09
      • 1970-01-01
      • 2017-05-30
      • 1970-01-01
      • 2011-03-18
      • 1970-01-01
      相关资源
      最近更新 更多