【问题标题】:Pipe with printf command使用 printf 命令进行管道
【发布时间】:2013-09-12 22:46:12
【问题描述】:

我在 C 中创建了历史命令,用于存储和从文件中获取命令。现在我正试图通过管道在它上面运行“头”。即历史|头-3

为此,我首先 dup2() 将标准输出写入管道末端。然后使用 printf 打印历史记录(obv 不会显示在屏幕上)。现在,我已将标准输入重定向到读取该管道和 execvp() 头命令。它正确显示前 3 行。但它仍在等待用户输入。我必须按 Ctrl C 终止。知道为什么会这样。即使我在显示历史记录后尝试将所有内容刷新到标准输出中。似乎没有任何效果。

pid=fork();
if(pid==0){
    if(...first time..){
        if(dup2(fd[1],1)<0){
              printf("Error in Dup!!");
        }
        printHistory();
        for(k = 0;k < totalfds; k++){
              close(fd[k]);
        }
        return;
    }
    if(...second time..){
        if(dup2(fd[0],0)<0){
            printf("Error in Dup!!");
            }
    }   
    ...
    execvp(subcomm[0],subcomm);
    ...
}

【问题讨论】:

  • 代码在哪里?为什么会列出shell
  • 它是 C 中的 shell 实现。这就是原因。我想代码不会是必需的,我会编辑它。
  • 这可能更多地与head 的工作方式有关。它期望它的输入如何结束?
  • 关闭管道?那应该发送 eof。
  • 用换行符结束你的消息;它有助于。这可能不是所有必要的,但它是一个开始。还可以考虑将错误消息发送到stderr 而不是stdout

标签: c shell unix


【解决方案1】:

命令未在 EOF 上终止的常见问题是您没有关闭足够多的文件描述符。如果head 命令仍然打开了管道的写文件描述符,那么它可能会尝试读取并挂起,因为管道的写端是打开的——即使是head 进程打开了它并且它在读取返回之前不会写入。

此外,您的孩子在完成 printHistory() 后可能应该做 exit(0)(或者可能是 _exit(0))——不要返回。如果它返回,它可能会回到读取循环。如果execvp() 失败,您还应该确保退出进程(状态非零)。永远不需要检查execvp()exec*() 函数的其他成员的返回状态。如果他们回来了,他们就失败了;如果它们成功了,原来的进程会被新的进程替换,并且函数永远不会返回。

此外,作为一般性评论,请以换行符结束您的消息;它有助于确保它们及时出现。还可以考虑将错误消息发送到 stderr 而不是 stdout

【讨论】: