【问题标题】:File Descriptor 0文件描述符 0
【发布时间】:2014-06-10 08:44:09
【问题描述】:

借鉴this thread讨论文件描述符和表格;

我想知道在 shell 中如何处理标准输入(即文件描述符 0,而不是 C 的标准输入 FILE 结构)。

当我在 C 中运行像 read(0, buffer, 1024) 这样的代码时,默认情况下,在 C 文件描述符 0 中连接到键盘,shell 允许我输入文本,因为我们假设 read 正在等待读取字符设备“标准输入”的内容,也就是键盘。但是,标准输入不会简单地为空并产生结果吗?好吧,让我们说“连接到键盘”路径是解释它的方式;如果是这种情况,那么这一定意味着 shell 行缓冲他们的命令,对吗?对文件描述符 0 调用读取意味着 shell 中的文件描述符 0 连接到标准输入的行缓冲缓冲区输出,而不是直接连接到键盘,那么是什么让 C 等待呢?此外,为什么我们不能在标准输入上使用lseek() - 是否说“文件”总是被每一次“写入”覆盖,因此没有什么可寻找的,因为标准输入(作为键盘)并不是真的存储设备本身上的文件?

【问题讨论】:

  • C 对“键盘”一无所知——它只知道stdin,这是一个字节流。它使用阻塞 I/O 进行读取,这意味着如果 stdin 上没有可读取的字符,则它会一直等到有字符。
  • “空虚”和“等待”并不是相互排斥的。重要的是文件描述符是否打开

标签: c linux stdin file-descriptor


【解决方案1】:
read(0, buffer, 1024)

是系统调用,是对内核代码的调用。 read 的内核实现将分派给终端(或伪终端)设备驱动程序,该驱动程序将等待您输入 1024 个字符、换行符或 EOF 标记 Ctrl+ D.

那一定意味着 shell 行缓冲他们的命令,对吧?

如果终端设置为正确模式,则在终端驱动程序中执行缓冲。否则,程序将一直等待,直到输入 1024 个字节。

另外,为什么我们不能在标准输入上使用lseek()

如果标准输入是常规文件,则可以。您只是不能在终端上搜索,因为这将要求终端驱动程序记住自创建以来通过终端设备的所有数据。

【讨论】:

  • 完全可以将0作为常规文件关闭再重新打开。或作为网络套接字,或 timerfd。结果是您无法知道它是否可搜索,除非您查询该属性。
  • 另外,stdin 与“fd 0”不同。有可能 C 说你不能在 stdin 中寻找(至少它是 UB 来刷新它),但这与 Posix 文件 API 无关。
  • @KerrekSB 我正在使用 OP 的定义,“文件描述符 0,而不是 C 的标准输入文件结构”。将 fd0 称为“stdin”是非常惯用的。你认为我的回答有什么特别错误的地方吗?
  • 你可以称它为STDIN_FILENO :-) 我只是想弄清楚 Posix API 和 C 标准库之间的区别。每个人都有自己的一套约束和规则。目前我对 C 库不是 100% 确定,但我认为 OP 正在询问 Posix。
  • Right-O:我忘了 fd0-2 通常连接到 /dev/tty。但是当我调用相同的读取函数时,我得到类似于“行缓冲”输入的东西:这就是所谓的“规范输入”吗? - gnu.org/software/libc/manual/html_node/…
猜你喜欢
  • 1970-01-01
  • 2019-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-25
相关资源
最近更新 更多