You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在mRuby中实现$stdin.gets()的非阻塞读取?

在mRuby中实现$stdin的非阻塞读取

确实,mRuby砍掉了Ruby标准库中的Thread和Queue,mruby-thread也没法满足非阻塞读stdin的需求,不过我们可以借助底层的文件操作来实现,不用写自定义扩展。下面给你两个实用的方案:

方案一:设置stdin为非阻塞模式

这个思路是通过修改stdin的文件描述符属性,让它变成非阻塞模式,读取时如果没有输入就抛出Errno::EAGAIN异常,我们捕获这个异常就可以继续执行其他逻辑。

# 获取stdin的文件描述符
fd = $stdin.fileno

# 获取当前文件状态标志,添加非阻塞标志
flags = Fcntl.fcntl(fd, Fcntl::F_GETFL)
Fcntl.fcntl(fd, Fcntl::F_SETFL, flags | Fcntl::O_NONBLOCK)

# 封装非阻塞读取方法
def non_blocking_gets
  begin
    $stdin.gets
  rescue Errno::EAGAIN
    # 无输入时返回nil
    nil
  end
end

# 使用示例
loop do
  input = non_blocking_gets
  if input
    puts "收到输入: #{input.chomp}"
    break if input.chomp == 'exit'
  end
  # 这里可以放你的业务逻辑
  puts "处理其他任务中..."
  sleep 0.5
end

不过要注意,默认的gets是按行读取的,如果输入没有换行符,即使有部分数据也会返回nil。如果需要处理不完整的输入,可以自己维护一个缓冲区:

fd = $stdin.fileno
flags = Fcntl.fcntl(fd, Fcntl::F_GETFL)
Fcntl.fcntl(fd, Fcntl::F_SETFL, flags | Fcntl::O_NONBLOCK)

@input_buffer = ""

def non_blocking_gets
  begin
    # 每次读取最多1024字节的数据
    data = $stdin.read(1024)
    @input_buffer += data if data
  rescue Errno::EAGAIN
    # 没有新数据,跳过
  end

  # 检查缓冲区里是否有完整的行
  if line_end = @input_buffer.index("\n")
    line = @input_buffer[0..line_end]
    @input_buffer = @input_buffer[line_end + 1..-1] || ""
    line
  else
    nil
  end
end

# 使用示例
loop do
  line = non_blocking_gets
  if line
    puts "读取到完整行: #{line.chomp}"
    break if line.chomp == 'exit'
  end
  puts "执行其他操作..."
  sleep 0.5
end

方案二:用IO::Select检查可读状态

如果你不想修改stdin的阻塞模式,可以用IO::Select来监听stdin是否有可读数据,超时设为0就是非阻塞检查,只有当有数据时才去读取。

def non_blocking_gets
  # 创建监听stdin的选择器
  read_monitor = IO::Select.new([$stdin])
  # 非阻塞检查是否有可读数据
  ready = read_monitor.select(0)
  ready ? $stdin.gets : nil
end

# 使用示例
loop do
  input = non_blocking_gets
  if input
    puts "收到输入: #{input.chomp}"
    break if input.chomp == 'exit'
  end
  puts "等待输入的同时处理其他事情..."
  sleep 0.5
end

注意事项

  • 确保你的mRuby编译时包含了mruby-fcntl和mruby-io模块,这两个都是标准库的一部分,一般默认编译会包含,如果没有的话,需要在build_config.rb里添加对应的gem。
  • 两种方案都不需要写C扩展,纯Ruby代码就能实现。

内容的提问来源于stack exchange,提问作者Rick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:25:49