简体   繁体   English

猫打破了程序,手动标准输入不

[英]cat breaks the program, manual stdin input doesn't

I have this small program: 我有这个小程序:

#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);
    }
}

Which is supposed to simply square three numbers that it reads from stdin . 它应该只是对从stdin读取的三个数字求平方。 And if I type the numbers in myself, it works: 如果我自己输入数字,它会起作用:

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

but if I use cat for the same purpose, it does not work as expected: 但是,如果我出于相同的目的使用cat,则无法正常工作:

akiiino$ cat in.txt
12345678
12345678
12345678

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

What is the reason behind this weird behavior and is it fixable? 这种怪异行为背后的原因是什么,它是否可以解决? I've always assumed cat ing files was no different from typing them into stdin . 我一直认为cat荷兰国际集团的文件,没有打字他们分为不同的stdin

The difference is that when you type the 3 numbers by hand , you are reading from a terminal and low level reads are terminated on newlines. 区别在于,当您手动键入3个数字时,您正在从终端读取数据,而低电平读取则在换行符处终止。 Let's look what happens under the hood. 让我们看看幕后情况。

  1. manual input: 手动输入:

    • the 3 child have started and are waiting for input 3个孩子已经开始并等待输入
    • you type one number and a new line 您键入一个数字和一个新行
    • the underlying read call is terminated by the newline because you read from a terminal 底层的read调用由换行符终止,因为您是从终端读取的
    • first child (the one that got the read) has its scanf call decode the input an does its processing 第一个孩子(被读取的孩子)进行scanf调用,对输入进行解码并进行处理

    Ok, we iterate the same for the 2 other childs 好吧,我们为其他两个孩子重复相同的操作

  2. reading from a file or a pipe 从文件或管道读取

    • the 3 child have started and are waiting for input 3个孩子已经开始并等待输入
    • the 3 numbers and the newlines are immediately available 3个数字和换行符立即可用
    • the underlying read of first child reads and consumes all the input in the stdio buffer 第一个孩子的基础read读取并消耗了stdio缓冲区中的所有输入
    • first child (the one that got the read) has its scanf call decode the (first part of the) input an does its processing 第一个孩子(被读取的孩子)对其scanf调用进行解码(输入的第一部分),并对其进行处理

    But now the 2 other childs are reading from a file/pipe positioned at end of file. 但是现在其他两个孩子正在读取位于文件末尾的文件/管道。 Their scanf returns 0 but you fail to control it, and they let the initial undeterminated value in num . 他们的scanf返回0,但是您无法控制它,并且他们将未确定的初始值设为num

You can control that it is not a problem of race condition by adding a sleep(10) before the loop, starting the program an inputting by hand 3 numbers before first child begins to read. 您可以通过在循环之前添加sleep(10) ,在第一个孩子开始阅读之前手动输入3个数字来启动程序来控制这不是竞赛条件的问题。 As the low level reads will be newline terminated (special tty case) you still get same output of the first case, even if the 3 lines are available before the first read. 由于低级读取将以换行符终止(特殊tty情况),即使在第一次读取之前有3行可用,您仍然会获得与第一种情况相同的输出。

Already said by @Some programmer dude, problem is with the fork command. @Some程序员老兄已经说过,问题出在fork命令上。 If you try ./out.out < in.txt , it should work fine. 如果尝试./out.out < in.txt ,它应该可以正常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM