cat打破程序,手动stdin输入没有

时间:2017-04-07 12:38:54

标签: c shell fork stdin cat

我有这个小程序:

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

int main() {
    int orig = 1;
    for (int i = 0; (i != 3) && orig; ++i) {
        orig = orig && fork();
    }
    if (orig) {
        for (int i = 0; i != 3; ++i) {
            wait(NULL);
        }
    } else {
        int num;
        scanf("%8d", &num);
        printf("%d\n", num*num);
    }
}

这应该简单地对从stdin读取的三个数字进行平方。如果我在自己输入数字,它就有效:

akiiino$ ./out.out
12345678
12345678
12345678
260846532
260846532
260846532

但是如果我出于同样的目的使用cat,它就无法正常工作:

akiiino$ cat in.txt
12345678
12345678
12345678

akiiino$ cat in.txt | ./out.out
260846532
0
0

这种奇怪的行为背后的原因是什么,它是否可以解决?我一直认为cat个文件与将它们输入stdin没有区别。

2 个答案:

答案 0 :(得分:3)

不同之处在于,当您手动输入3个数字 时,您正在从终端读取数据,而低级别读取将在换行符上终止。让我们来看看幕后发生了什么。

  1. 手动输入:

    • 3个孩子已经开始并正在等待输入
    • 您输入一个号码和一个新行
    • 由于您从终端
    • 读取,因此新线会终止基础read来电
    • 第一个孩子(获得阅读的孩子)的scanf调用解码输入和处理

    好的,我们为其他2个孩子迭代

  2. 从文件或管道中读取

    • 3个孩子已经开始并正在等待输入
    • 3个号码和换行符立即可用
    • 第一个孩子的基础read读取并使用stdio缓冲区中的所有输入
    • 第一个孩子(获得阅读的孩子)有scanf调用解码(第一部分)输入和处理

    但是现在另外两个孩子正在从位于文件末尾的文件/管道中读取。他们的scanf返回0但你无法控制它,并且他们在num中保留了初始未确定的值。

  3. 你可以通过在循环之前添加sleep(10)来控制它不是竞争条件的问题,在第一个孩子开始阅读之前启动程序手动输入3个数字。由于低级读取将是换行符(特殊情况),即使在第一次读取之前有3行可用,您仍然可以得到第一种情况的相同输出。

答案 1 :(得分:0)

@Some程序员老兄说过,问题在于fork命令。 如果您尝试./out.out < in.txt,它应该可以正常工作。