c - Ctrl+D后如何重启stdin?
问题描述
运行一个期望从终端输入的程序,我可以通过 Ctrl+D 来“关闭”标准输入。之后有没有办法重新打开标准输入?
解决方案
在linux和一般的 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
这在手册页的描述部分的第一句话中进行了描述。
推荐阅读
- gradle - 推荐使用“tasks.withType(Foo) {...}”或“foo {...}”配置插件的方式?
- android - 我想在 nativescript vue 中打开意图处理程序并获取结果意图数据
- ios - UIImageview 没有得到四舍五入
- python - 需要为我的字典定义一个“搜索”功能
- javascript - 使用正则表达式将单引号更改为双引号
- python - 如何从(1 到 9)创建一个下拉列表,以便用户可以选择要预订多少张门票?
- elasticsearch - 通过(无痛)脚本进行 ElasticSearch 排序 - 数组值被神秘地重复数据删除
- vb6 - 如何在 VB6 中实现“CanRaiseEvent”属性?
- google-chrome-extension - 在 chrome 扩展中设置徽章在开发模式下有效,但在 prod 中无效(chrome 商店)
- html - 如何使用快速路由器渲染 React 组件?