这是我在大型 ruby 脚本中遇到的错误。我设法将其归结为问题的本质。在讨论这个问题时,脚本是由某人在 OS/X 上运行而没有遇到同样的问题,所以与其说是 ruby 问题,不如说是 linux 问题。
#!/usr/bin/env ruby
require "io/console"
def read_char
state=`stty -g`
`stty raw -echo`
input = $stdin.getc.chr
input << $stdin.read_nonblock(3) rescue nil
return input
ensure
`stty #{state}`
# Have also tried `stty -raw echo`
end
system("strace -o strace.log ./trace the start")
puts "press a cursor key"
c=read_char
system("strace -o strace2.log ./trace regular key")
puts "press a regular key"
c=read_char
system("strace -o strace3.log ./trace cursor key")
puts "done press return to exit"
对于非 Ruby 主义者,需要提及的关于此代码的内容<<
附加到数组[1]中。
反引号的行为与sh
. 目前,我不知道 Ruby 是如何具体实现read_nonblock
. 我正在研究它。如果问题仍未得到解答,将提及它。
稍后我会将C++源代码发布到“跟踪”函数中,但没有源代码很容易理解。读取命令行并写入预定文件。然后请求输入。从 STDIN 读取一些输入后,将其保存到同一个文件并退出。它本质上是一个调试功能,暂时替代了一些更复杂的功能。
问题
第三个系统调用行为不当,有点像从/dev/zero
.
从 STDIN 读取的日志条目如下所示:
strace.log:read(0, "1\n", 1024) = 2
strace2.log:read(0, "2\n", 1024) = 2
strace3.log:read(0, 0x7fb388ba0000, 1024) = -1 EAGAIN (Resource temporarily unavailable)
那么为什么第三条trace读内存映射IO呢?
分配内存的命令的条目是:
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb388ba0000
为什么mmap
命令以fd
-1 作为参数?[2]
附加评论。根据我到目前为止所描述的内容,我几乎必须得出结论,当 EAGAIN 错误发生时,某些东西没有正确清理,或者标准输入状态以某种方式混乱,现在标准输入被阻塞。然后这会被系统命令继承。因此标题问题:您如何重置标准输入,以便它的行为与最初的行为一样。
[1]是的,作为一名 C++ 程序员,我知道这很烦人。
[2]我对 Unix 内存映射 IO 不是很熟悉,我自己从来没有用它写过任何东西。我很久以前使用过的 Windows 内存映射 IO。