首页 > 解决方案 > Ctrl+D后如何重启stdin?

问题描述

运行一个期望从终端输入的程序,我可以通过 Ctrl+D 来“关闭”标准输入。之后有没有办法重新打开标准输入?

标签: clinux

解决方案


和一般的 POSIXy 系统上,当您在终端中按Ctrl+时,标准输入描述符不会关闭;D它只是使伪终端层变得可读,并read()返回 0。这就是 POSIXy 系统指示输入结束的方式。

这并不意味着文件描述符(甚至是 C 库在其之上提供的流句柄)被关闭。正如 Steve Summit 在评论中提到的,您只需要使用清除流的输入结束状态clearerr(),就可以读取更多数据;这告诉 C 库您注意到状态更改,但无论如何都想尝试进一步阅读。

当一个进程正在写入文件,而另一个进程读取它时,可能会发生类似的情况。当阅读器到达文件末尾时,aread()返回 0,C 库将其理解为输入结束;它设置了一个内部标志,因此除非您调用clearerr(),否则feof()该流将返回 true 。现在,如果 writer 写入更多数据,而 reader 执行 a clearerr(),则 reader 可以读取新写入的附加数据。

这是完全正常的,也是预期的行为。

总之:

  • 输入结束由read()返回 0 的操作指示,但文件描述符状态不会改变,可以正常使用。

  • Ctrl+D在终端上只会导致这种情况发生;对终端打开的文件描述符不会以任何其他方式受到影响,由前台进程读取终端输入来决定它的作用。允许简单地继续读取更多数据。

    发生这种情况时,大多数程序都会退出,但这是一种约定,根本不是技术要求。

  • C 库检测到read()返回 0,并为该流设置其内部“输入结束”标志。这会导致该流feof()返回 true、fgets()返回 NULL、fgetc()返回EOF等等。

  • 调用clearerr()流句柄会清除标志,以便下一次读取尝试实际上会尝试从描述符中读取更多数据。

    man 3 clearerr这在手册页的描述部分的第一句话中进行了描述。


推荐阅读