在正确设置为非阻塞模式时,我无法弄清楚为什么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函数(如read,readline,gets,readchar)都忽略该模式,并在未收到任何输入时挂起.
将同步模式设置为true无效.
如果我用shell调用系统(‘read line’)替换STDIN.readline,它确实可以正常工作.如果设置了非阻塞模式,它将不会等待或等待输入.
我知道IO.read_nonblock,但寻找一种有效的方法来读取换行终止字符串.为每个单个字符调用read_nonblock非常慢.
任何人都可以解释这个(错误的)行为吗?
最佳答案 这有点不幸但IO模块的标准函数似乎不尊重与文件描述符相关的状态标志.
其中一个工作解决方案是使用IO.select
类方法进行输入轮询,然后在可用时使用常规方法读取数据.
请注意,在使用行处理方法时,代码可能会挂起,直到终止换行符被消耗为止.当事情失控时,建议将轮询代码包含在Timeout块中.
在预先知道字符/字节数量的情况下,库存IO.read_nonblock
将很好地服务.