【问题标题】:Odd behavior when child process gets orphaned while reading from stdin从标准输入读取时子进程成为孤立的奇怪行为
【发布时间】:2016-06-06 12:16:11
【问题描述】:

代码如下:

// after fork:
else if (pid > 0) // parent
{
    char buff[READ_SIZE];
    write(STDOUT_FILENO, "parent\n", 7);

    int r = read(STDIN_FILENO, buff, READ_SIZE);
    if (r == -1)
        perror("parent");
}
else // child
{
    char buff[READ_SIZE];
    write(STDOUT_FILENO, "child\n", 6);

    int r = read(STDIN_FILENO, buff, READ_SIZE);
    if (r == -1)
        perror("child");

    sprintf(buff, "\n%d", r);
    write(STDOUT_FILENO, buff, 2);
}

这是输出:

$ ./forktest
parent
child
abc <-- input goes to parent, parent exits
$   <-- both child and terminal waiting for input, presumably

此时,只要我按下任意键(不按 Enter),我就会得到:

$ ./forktest
parent
child
abc
$ 
1  <-- the child has read just 1 character

这意味着孩子的 read() 仅在按一次键且没有 Enter 后结束。

这是为什么呢?

PS。我知道正确的做法是让父母为孩子等待()。我只是好奇这里到底发生了什么。

【问题讨论】:

  • 你有什么问题?
  • 为什么 read() 在一个按键后结束,即使我还没有按下回车键?如果标准输入不再有效,为什么 read() 不返回 -1?

标签: c linux fork stdin system-calls


【解决方案1】:

如果标准输入不再有效,为什么 read() 不返回 -1?

stdin 始终有效,直到您关闭终端应用程序。

stdin 是由您的终端创建的,而不是 bash,不是父级。只要您的终端处于活动状态,stdin 就处于活动状态

为什么read()在一个按键后结束,即使我还没有按下回车键?

大多数 shell (bash/dash/zsh) 将 tty 设置为逐字节读取模式,当您按任意键时 read 将立即返回,因为它们正在执行自动完成。

当 shell 要启动一个程序时,它会将 tty 设置为行模式,您的程序会逐行读取。

但是一旦父级退出,shell 会将 tty 重置为字节模式,因为您的孩子和 shell 共享相同的 tty,它也会影响您的孩子,因此您的孩子会读取一个字符。

【讨论】:

    【解决方案2】:

    您的 shell 喜欢在原始模式下工作,但将终端设置为熟化模式以生成生成的程序。您可以在任何地方阅读有关生食和熟食模式的信息。但简而言之,在原始模式下输入是逐个字符的,而在熟模式下是逐行输入的。

    那么会发生什么?省略多余的事件:

    • shell 将终端设置为熟模式。
    • shell 运行您的程序。
    • 您的程序生成一个子进程并退出。
    • shell 重新获得控制权。
    • shell 将终端置于原始模式。
    • 您输入一个字符。
    • 您的子进程抢夺它。

    【讨论】:

    • 有没有办法让我验证 shell 在原始模式下运行?
    • 按向上箭头键。看到前面的命令了吗?如果是,那就是原始模式。
    猜你喜欢
    • 2016-10-02
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-20
    • 2021-07-03
    • 1970-01-01
    相关资源
    最近更新 更多