【问题标题】:VMIN=0 + select(), possible kernel bug?VMIN=0 + select(),可能的内核错误?
【发布时间】:2016-01-16 19:26:42
【问题描述】:

更新: Simple Proof of Concept 解释不同的行为。

假设我使用tcgetattr 和tcsetattr 设置VMIN = 0, VTIME = 0 并删除ICANON,将终端设置为原始模式。 从标准输入对read() 的调用永远不会阻塞。我说的对吗?

我的问题是:我应该期望 stdin 上的 select() 立即返回吗?
从手册页:

select() 和 pselect() 允许程序监视多个文件描述符,等待一个或多个文件描述符为某个类“准备好” I/O 操作(例如,可以输入)。如果可以执行相应的 I/O 操作(例如 read(2)),则认为文件描述符已准备就绪 不阻塞。

基于此,我的第一个答案是“是”。然而,实际上它在我测试过的大多数 Linux 系统上确实阻塞,但它不会在某些系统上阻塞。 这是内核错误吗? 是否建议这样使用VMIN = 0和select()?

【问题讨论】:

  • 其他人可以检查(并考虑您的描述是否完整)的简短示例程序将有助于获得响应。
  • 当然!我加一个。不知怎的,我之前没有看到你的消息...
  • @ThomasDickey 完成,请参阅链接。

标签: linux io terminal kernel


【解决方案1】:

问题可能是这样的:VMIN 和 VTIME 的数组条目有两个用途。参考POSIX termios:

VMIN 和 VTIME 下标可以分别与 VEOF 和 VEOL 下标具有相同的值。

程序在规范模式下读取attributes 值,然后将其更改为非规范,并将VMIN 设置为零。但是version shown 对VTIME 没有任何作用(这与问题中的描述不符)。

参见例如 Understanding UNIX termios VMIN and VTIME(同样,Linux 的 manual page 用于 termios),它指出如果 VMIN 和 VTIME 都为零,那么您可以拥有一个完全非阻塞读取。

termios 手册页将零作为VEOL 的初始值,而stty manual 页面将<undef> 等同于_POSIX_VDISABLE(非零)(与POSIX stty 一致)。 POSIX 似乎没有为 eol 指定初始值。

通常VEOL 将是<undef>,如stty -a 所示。也许在您获得非阻塞读取的机器上,情况并非如此。这不一定是 内核 错误,但可能是 TTY 的配置问题。

【讨论】:

  • PoC 现在也设置了VTIME = 0。我已经测试过,我得到了与以前相同的不同行为......
  • 请注意,如果我删除 select 调用(只留下一个“阻塞”read),PoC 的行为会相同。
  • 澄清:跨机器的行为相同,read 总是立即返回 0。
  • 非阻塞读取与文档一致,因为 VTIME 现在已显式初始化。
  • 是的。尽管如此,select 的行为在机器之间是不一致的......在某些机器上它会阻塞直到有输入,而在另一些机器上它会立即返回。
猜你喜欢
  • 2016-10-14
  • 2016-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多