当前位置: 首页 > 知识库问答 >
问题:

管道和叉,不会显示在标准输出上

姚高韵
2023-03-14

我正在做我的家庭作业,那就是用C语言复制unix命令shell。

我已经实现了直到后台运行的单个命令执行(

现在我正处于实现管道的阶段,我面临这个问题,对于大于1的管道,带有管道的子命令已经完成,但是最终输出不会显示在stdout上(最后一个命令的标准输入被替换为最后一个管道的读取)

dup2(pipes[lst_cmd], 0);

我也在家长那里尝试了fflush(STDIN\u FILENO)

我的程序的出口是CONTROL-D,当我按下该键时,将显示输出(也将退出,因为我对CONTROL-D的操作是退出(0))。

我认为管道的输出在标准输出缓冲区中,但没有显示出来。除了fflush之外,还有其他方法可以将缓冲区中的内容获取到stdout吗?

共有1个答案

汪和悌
2023-03-14

看过代码(不公平优势)后,主要问题是过程结构和没有彻底关闭管道相结合。

管道的过程结构为:

main shell
    - coordinator sub-shell
        - ps
        - sort

主shell正在创建N个管道(N=1,用于ps|排序)。然后创建了协调器shell;它将启动N1子级。然而,它没有等待它们终止,也没有关闭它的管道副本。主外壳也没有关闭它的管道副本。

更正常的流程结构可能不需要协调器子shell。产生孩子有两种机制。经典地说,主shell将派生一个子进程;它将协调管道中的前N个进程(包括首先创建管道),然后执行管道中的最后一个进程。主shell等待一个子进程完成,管道的退出状态是子进程的退出状态(也称为管道中的最后一个进程)。

最近,bash提供了一种机制,让主shell获取管道中每个子级的状态;它负责协调。

主要修复程序(除了一些较小的编译警告外)包括:

  1. 分叉后,主壳体关闭所有管道
  2. 主shell等待协调器完成
  3. 协调员在分叉管道后关闭所有管道
  4. 协调器等待管道中的所有进程完成
  5. 协调员退出(而不是返回以提供决斗双重提示)

更好的修复方法是消除协调器子shell(它的行为类似于所描述的经典系统)。

 类似资料:
  • 问题内容: 我有这个简单的脚本: 在这里,我只需执行一个命令即可编译咖啡脚本文件。但是stdout永远不会显示在控制台中,因为该命令永远不会结束(因为coffee的- w选项)。如果我直接从控制台执行命令,则会收到如下消息: 我的问题是:是否可以使用node.js exec显示这些消息?如果是,怎么办?! 谢谢 问题答案: 不要使用。使用哪个是对象。然后,您可以在事件 发生时 收听/ event(

  • 问题内容: 在Linux 3.0 / C ++下: 我想要一个执行以下操作的函数: 显然上述方法不起作用,但是您可以理解。我有一个字符串s,我希望将其作为应用程序“ foo”的子进程执行的标准输入传递,然后将其标准输出记录到字符串r中,然后将其返回。 我应该使用linux syscall或posix函数的什么组合? 问题答案: eerpini提供的代码无法正常工作。请注意,例如,之后将使用在父级中

  • 问题内容: 当传递Python程序的输出的管道时,Python解释器对编码感到困惑,并将其设置为None。这意味着这样的程序: 正常运行时可以正常工作,但失败: 编解码器无法在位置编码字符:序数不在范围内(128) 以管道顺序使用时。 使管道工作的最佳方法是什么?我能告诉它使用外壳程序/文件系统/正在使用的任何编码吗? 到目前为止,我所看到的建议是直接修改你的,或使用此hack硬编码: 有更好的方

  • 问题内容: 我需要在Hudson中运行Shell脚本。该脚本需要用户回答。为了给出自动答案,我做了以下命令行: 这在Ubuntu终端中运行良好。但是,当我在Hudson作业中使用相同的命令时,脚本将自动执行所需的所有工作,但是最后,我得到了这两行错误: 这导致我的哈德森工作失败。 如何更改命令行以在Hudson中正常工作? 问题答案: 但是,您如何解释我在 本地 运行脚本时没有收到此错误,而从Hu

  • 我是Java的初学者。学习罗伯特·塞奇威克的《Java导论》 我尝试在Netbeans中编译以下代码。 } 我收到了这个错误。我已将文件放置在标准位置。java 线程“main”java.lang.RuntimeException中的异常:无法编译的源代码-错误的sym类型:示例。StdIn.is在示例中为空。verage.main(verage.java:16)Java结果:1 BUILD SU

  • 问题内容: 我有一个奇怪的问题,如果可以解决,那就太好了。出于调试目的(以及其他一些目的),我在标准输出上编写了控制台Java应用程序的日志。在标准输出上写一些内容,在标准错误上打印一些错误,例如错误。问题是这两个没有完全同步,因此打印线的顺序并不总是正确的。我猜这是因为打印了很多东西,并且碰巧一个输出的缓冲区已满,所以其他输出在第一个输出刷新其缓冲区之前就已打印出来。 例如,我想这样写: 有时打