【问题标题】:Non-blocking readline for STDIN?STDIN 的非阻塞读行?
【发布时间】:2014-09-08 14:15:25
【问题描述】:

当正确设置为非阻塞模式时,我无法弄清楚为什么 IO 方法无法在 STDIN 上工作:

  require 'fcntl'

  stdin_flags = STDIN.fcntl(Fcntl::F_GETFL)
  p stdin_flags   #32770
  p STDIN.fcntl(Fcntl::F_SETFL, stdin_flags | Fcntl::O_NONBLOCK) # 0
  p STDIN.fcntl(Fcntl::F_GETFL)    # 34818
  #at_exit { STDIN.fcntl(Fcntl::F_SETFL, stdin_flags & ~Fcntl::O_NONBLOCK) }
  STDIN.readline    # this call blocks, IO::EAGAINWaitReadable expected
  exit

IO.fcntl 成功设置非阻塞模式,但所有 IO 函数,如 readreadlinegetsreadchar 忽略该模式并在未收到输入时挂起读取。

将同步模式设置为 true 无效。

如果我用 shell 调用 system('read line') 替换 STDIN.readline,它确实可以正常工作。它不会等待或将等待输入,具体取决于是否设置了非阻塞模式。

我知道IO.read_nonblock,但正在寻找一种有效的方法来读取换行符终止的字符串。为每个字符调用read_nonblock 非常缓慢。

谁能解释这种(错误)行为?

【问题讨论】:

  • @the Tin Man 感谢文字更正

标签: ruby unix stdin pipe


【解决方案1】:

有点遗憾,IO 模块的标准函数似乎不尊重与文件描述符关联的状态标志。

其中一个可行的解决方案是使用IO.select 类方法进行输入轮询,然后在可用时使用常规方法读取数据。 请注意,当使用行处理方法时,代码可能会挂起,直到终止换行符被消耗。当事情失控时,建议将轮询代码包含在Timeout 块中。

如果事先知道字符/字节的数量,库存IO.read_nonblock 就可以很好地发挥作用。

【讨论】:

    猜你喜欢
    • 2012-03-10
    • 2011-06-25
    • 2015-07-24
    • 2014-11-17
    • 2016-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-06
    相关资源
    最近更新 更多