从c中读取管道

时间:2011-10-05 05:07:00

标签: c comparison pipe

场景:假设我有8个文件,我想按从最小到最大的顺序对它拥有的所有数字数据进行排序。只有叶子处理可以对文件包含的所有数字进行排序。这些叶子进程必须通过管道将已排序的数据发送到父进程。此父进程将比较接收和发送的数据,该数据对于下一个进程更小。它将执行此操作,直到管道中的所有数字都为空。

所以把它想象成一棵树。我们有一个主过程。要对8个文件进行排序,主进程将生成2个进程(左侧和右侧)。这两个新进程将产生自己的进程。直到底部有8个叶子进程才会发生这种情况。内部节点只能保留一个数字。这些将通过一系列管道传递它们的数字,直到它们到达主进程。主进程将其管道内容输出到文件。

我已经包含了代码here(因为它有点冗长但很简单)。

如果我有2个要排序的文件,这是有效的。所以我们有1个主过程,然后是两个孩子。两个孩子对文件的数字进行排序,然后将其传递出去。然后,主进程按管道顺序打印出数据。但是,如果我添加一些复杂性(4个文件),叶子进程仍然会向上发送数据,但是当主进程开始从内部节点管道读取时,它认为它是空的并且没有任何数据就完成了程序。

知道为什么主进程认为它的左右管道都是空的? 就像我说的,当有一个父母和两个孩子时,效果很好。再也没有进程了。 (假设处理将以2的幂发生。)

注意:perror用于调试目的。

完整的程序here [非常混乱,因为我已经做了很多但它会编译。

1 个答案:

答案 0 :(得分:1)

Pastebin中更新的代码不是可编译的功能 - 更不用说完整的程序了。这使得很难说出真正的错误。

然而,其中一个问题出在代码片段中:

if (pipe(upPipe) < 0 || pipe(leftPipe) < 0 || pipe(rightPipe) < 0)
    ...error exit...
if ((leftPID = fork()) < 0)
    ...error exit...

if(leftPID == 0){
    fMax = ((fMax)/2);
    dup2(leftPipe[WRITE], upPipe[WRITE]);
    pipe(leftPipe);
    pipe(rightPipe);

dup2()的调用很奇怪;您仔细地将左管道的写入通道映射到上管道的写入通道。

pipe()之后的两个dup2()调用相当快地搞砸了左子中的所有内容,打开了4个文件描述符,但丢失了leftPipe和{{1}中存储的先前值}。

您需要使问题陈述更清晰。我无法理解你所拥有的东西。有一个对rightPipe的调用,它不带任何参数并且不返回任何值;到底是做什么的?打电话给convertToInt();目前尚不清楚它的作用。

freeMem()

抱歉,您的问题无法解决,因为您没有给我们:

  1. 准确的要求。
  2. 您实际编译的代码。

  3. 您的代码没有很好的清除功能。您是否使用VCS(版本控制系统 - 例如z.c:42: error: ‘numberChar’ undeclared (first use in this function) z.c:42: error: ‘sizeNumbers’ undeclared (first use in this function) z.c:43: warning: implicit declaration of function ‘readFile’ z.c:43: error: ‘fileNames’ undeclared (first use in this function) z.c:45: warning: implicit declaration of function ‘convertToInt’ z.c:46: error: ‘i’ undeclared (first use in this function) z.c:46: error: ‘numbs’ undeclared (first use in this function) z.c:47: error: ‘numbers’ undeclared (first use in this function) z.c:48: warning: implicit declaration of function ‘freeMem’ )?如果没有,你应该。我在9个签到中进行了下面的更改版本 - 这实际上是一个完全重写 - 并且应该可以做出比这更小的签入。但使用VCS对我来说至关重要;它让我自信地做出改变,知道我不会失去任何有价值的东西。而且我没有必要对代码进行评论;我删除了我不想要的东西。以下解决方案是261行;原版总共大约687行,包括很多注释掉的代码;当我完成删除评论等时,它降至469行。

    当我运行代码(并报告每个孩子正在打开哪些文件)时,我发现有2个进程打开文件2和3(并且因为当时数据文件不存在) ,他们在那时失败了。)

    修改后的代码结构几乎干净;奇数位是'convertToString()'阶段,它从管道读取二进制整数并再次将它们转换为ASCII输出。有用;我不相信它很优雅。它不是使用硬编码文件名数组,而是从命令行获取任意文件名列表(它不必是8;它已经过0到8的测试,我没有理由去思考它不会处理20或更多)。我做了相当多的测试:

    git

    有丰富的诊断输出。我使用了两个在我的工作中非常有帮助的函数 - 我在一个更复杂的包中将它们与其他相关代码打包在一起,但./piped-merge-sort [1-8] err_error()函数的简单版本确实有帮助我。请注意,这些版本报告每个呼叫的报告过程的PID。他们还小心地将消息预先格式化为字符串,然后将字符串写入一个打印到标准错误;否则,我得到了很多交错输出,这最让人困惑。

    '努夫说 - 这是代码:

    err_remark()