
fluent-bit 仓库内嵌 mruby-io 详解IO 与 File 类的实现、能力边界与在 nghttpx 扩展中的角色【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bitmruby-io 是为 mruby 提供IO与File类的 mrbgem它以极小的内存占用在嵌入式 Ruby 运行时中复刻了标准 Ruby 的文件与管道操作能力。本文以 lib/nghttp2-1.65.0/third-party/mruby/mrbgems/mruby-io/README.md 为主体结合本仓库内该 mrbgem 的源码、测试与构建配置完整梳理其安装方式、方法实现清单、底层数据结构与平台适配细节并说明它在 nghttpxnghttp2 的 HTTP/2 反向代理mruby 扩展中的实际用途。读完本文你将能判断 mruby 环境中哪些 IO/File 方法可用、哪些仅提供 FileTest 能力、它们背后的文件描述符模型是怎样的以及如何在 mruby 构建中正确启用本 gem。一、mruby-io 是什么为嵌入式 Ruby 提供文件与管道能力mruby 是轻量级 Ruby 实现官方核心类库刻意精简不内置完整的IO/File。mruby-io 正是补齐这一块的官方 mrbgemcore gem它实现了IO和File两个类让 mruby 脚本能够读写文件、操作管道、执行子进程命令IO.popen并提供了大量与 CRuby 对齐的类方法如File.basename、File.expand_path、FileTest风格的存在性/类型判断等。在本仓库中mruby-io 位于 lib/nghttp2-1.65.0/third-party/mruby/mrbgems/mruby-io/它随 mruby 一起被 nghttp2 作为第三方依赖引入最终服务于 nghttpx 的 mruby 扩展见下文第五节。因此理解 mruby-io 的能力边界是理解 nghttpx 脚本化扩展机制的前提。二、安装与构建配置mruby-io 的安装方式是在 mruby 构建配置通常是build_config.rb中把 gem 以 core 级别加入conf.gem core: mruby-iocore:关键字表示该 gem 属于 mruby 官方核心 mrbgem 集合构建系统会从 mruby 自带的mrbgems/目录中解析。本仓库内 mrbgem 的构建描述文件为 mrbgem.rake其中声明了spec.license MIT作者为 Internet Initiative Japan Inc. 与 mruby developersWindows 平台下额外链接ws2_32库因为IO.pipe/socket 相关实现依赖 Winsock测试依赖mruby-timecore用于File#atime/File#ctime/File#mtime返回Time对象。从 include/mruby/ext/io.h 可以看到一个重要的构建约束如果构建配置定义了MRB_NO_STDIO禁用标准 I/O 的精简配置编译会直接报错IO and File conflicts MRB_NO_STDIO in your build configuration——因为 mruby-io 本质上就是围绕 stdio/系统调用实现的。此外MRB_WITHOUT_IO_PREAD_PWRITE可以显式关闭pread/pwrite支持在 Unix/macOS 上未显式配置时默认启用。三、IO 类实现方法全景类方法、实例方法与差异标注README 以一张对照 CRuby 的方法表呈现IO的实现情况表中o标记表示 mruby-io 已实现memo列对部分方法做了备注。这张表应被理解为 mruby 环境的能力声明未标记o的方法调用时会抛NoMethodError因此在 mruby 中编写脚本前应先对照此表。3.1 IO 类方法Class Methodsmethodmruby-iomemoIO.binreadIO.binwriteIO.copy_streamIO.new,IO.for_fd,IO.openoIO.foreachIO.pipeoIO.popenoIO.readoIO.readlinesIO.selectoIO.sysopenoIO.try_convertIO.write已实现的类方法中IO.read在 mrblib/io.rb 中由IO.sysopenIO.openseekread组合实现支持length读取字节数与offset起始偏移参数IO.pipe/IO.popen在纯 Ruby 层先检查底层 C 方法_pipe/_popen是否存在不存在时抛出NotImplementedErrormrblib/io.rb并且都支持块形式——块结束时自动关闭流。测试 test/io.rb 验证了IO.new/IO.open/IO.for_fd三种方式打开文件描述符后都能正确读取内容并校验传入非法 fd 时抛出RuntimeError。3.2 IO 实例方法Instance Methodsmethodmruby-iomemoIO#IO#adviseIO#autocloseIO#autoclose?IO#binmodeIO#binmode?IO#bytesobsoleteIO#charsobsoleteIO#clone,IO#dupoIO#closeoIO#close_on_execoIO#close_on_exec?oIO#close_readIO#close_writeIO#closed?oIO#codepointsobsoleteIO#each_byteoIO#each_charoIO#each_codepointIO#each_lineoIO#eof,IO#eof?oIO#external_encodingIO#fcntlIO#fdatasyncIO#fileno,IO#to_ioIO#flushoIO#fsyncIO#getbyteoIO#getcoIO#getsoIO#internal_encodingIO#ioctlIO#isatty,IO#tty?oIO#linenoIO#linenoIO#linesobsoleteIO#pidoIO#pos,IO#telloIO#posoIO#printoIO#printfoIO#putcIO#putsoIO#readoIO#read_nonblockIO#readbyteoIO#readcharoIO#readlineoIO#readlinesoIO#readpartialIO#reopenIO#rewindoIO#seekoIO#set_encodingIO#syncoIO#syncoIO#sysreadoIO#sysseekoIO#syswriteoIO#to_ioIO#ungetbyteoIO#ungetcoIO#writeoIO#write_nonblock一些值得注意的实现细节IO#未出现在 C 实现中但已由纯 Ruby 层补齐见 mrblib/io.rb调用write并返回self支持链式调用。迭代器在 Ruby 层实现each/each_byte/each_line/each_char均由 mrblib/io.rb 基于gets/getbyte/getc循环实现支持无块时返回to_enum符合 Enumerable 惯例。输出方法语义与 CRuby 对齐puts自动在行末补\n数组参数递归展开、print不做换行、printf委托sprintf见 mrblib/io.rb。别名eof别名eof?、tell别名pos、to_i别名fileno、tty?别名isatty其中pos通过seek(i, SEEK_SET)实现rewind等价于seek(0, SEEK_SET)mrblib/io.rb。IO#hash被显式覆写为对象__id__注释说明这是为了防止IO混入Enumerable后Enumerable#hash误调用IO#read破坏流状态mrblib/io.rb。标准流已预置mruby-io 在加载时创建STDIN IO.open(0, r)、STDOUT IO.open(1, w)、STDERR IO.open(2, w)并同步绑定$stdin/$stdout/$stderrmrblib/io.rb。Kernel层的print/puts/printf/gets因此直接委托给这三个标准流mrblib/kernel.rb。四、File 类实现方法全景与 FileTest 分组File继承自IO源码class File IO见 mrblib/file.rb因此自动继承第三节中所有IO#实例方法。README 的 File 表如下methodmruby-iomemoFile.absolute_pathFile.atimeFile.basenameoFile.blockdev?FileTestFile.chardev?FileTestFile.chmodoFile.chownFile.ctimeFile.delete,File.unlinkoFile.directory?oFileTestFile.dirnameoFile.executable?FileTestFile.executable_real?FileTestFile.exist?,File.exists?oFileTestFile.expand_pathoFile.extnameoFile.file?oFileTestFile.fnmatch,File.fnmatch?File.ftypeFile.grpowned?FileTestFile.identical?FileTestFile.joinoFile.lchmodFile.lchownFile.linkFile.lstatFile.mtimeFile.new,File.openoFile.owned?FileTestFile.pathFile.pipe?oFileTestFile.readable?FileTestFile.readable_real?FileTestFile.readlinkoFile.realdirpathFile.realpathoFile.renameoFile.setgid?FileTestFile.setuid?FileTestFile.sizeoFile.size?oFileTestFile.socket?oFileTestFile.splitFile.statFile.sticky?FileTestFile.symlinkFile.symlink?oFileTestFile.truncateFile.umaskoFile.utimeFile.world_readable?File.world_writable?File.writable?FileTestFile.writable_real?FileTestFile.zero?oFileTestFile#atimeoFile#ctimeoFile#mtimeoFile#chmodFile#chownFile#flockoFile#lstatFile#pathoFile#sizeFile#truncate要点解读FileTest语义memo 列为FileTest的方法是“断言类”方法实际由独立的 file_test.c 提供File.directory?/File.exist?/File.file?/File.pipe?/File.size?/File.socket?/File.symlink?/File.zero?等在 mrblib/file.rb 中直接转发给FileTest。File.blockdev?、File.chardev?等未实现的方法在 CRuby 中同样属于 FileTestmruby-io 未提供。纯 Ruby 层路径工具File.join处理分隔符拼接、递归数组展开与 Windows 盘符、File.expand_path基于_concat_path解析~、.、..并兼容 Windows 的ALT_SEPARATOR与盘符前缀、File.extname基于basename取最后一个.后的扩展名都在 mrblib/file.rb 中以纯 Ruby 实现是定位与路径处理最常用的工具。File.new/File.open双模式构造器接受整数 fd 或路径字符串传路径时内部先IO.sysopen再包装默认权限perm 0666mrblib/file.rb。时间相关方法返回 TimeFile#atime/File#ctime/File#mtime底层 C 方法返回整数时间戳Ruby 层用Time.at包装依赖mruby-time见 mrblib/file.rb。File#flock平台差异Unix 下直接调用系统flockWindows 下 file.c 用LockFileEx模拟LOCK_SH/LOCK_EX/LOCK_NB/LOCK_UN语义。File.umask平台差异Windows 上为 no-op 恒返回 0Unix 上读写进程 umaskfile.c。文件操作走系统调用File.delete/File.unlink遍历参数逐个unlinkFile.rename调用rename失败时通过mrb_sys_fail抛出带 errno 的异常file.c说明 mruby-io 面向 POSIX 语义、不做 Ruby 层缓冲。五、底层实现fd 模型、缓冲区与平台适配mruby-io 的核心是 include/mruby/ext/io.h 定义的struct mrb_iostruct mrb_io { int fd; /* file descriptor, or -1 */ int fd2; /* file descriptor to write if its different from fd, or -1 */ int pid; /* childs pid (for pipes) */ struct mrb_io_buf *buf; unsigned int readable:1, writable:1, eof:1, sync:1, is_socket:1; };每个 IO 对象本质上持有一个或两个文件描述符fd -1表示已关闭io_get_open_fptr会先校验指针与 fd未初始化或已关闭时分别抛uninitialized stream/closed stream的IOErrorio.c。fd2用于管道这类读写分离的场景pid记录IO.popen子进程号供IO#pid返回。内部缓冲struct mrb_io_buf大小为MRB_IO_BUF_SIZE 4096字节支持ungetc/ungetbyte的推回操作。读写标志readable/writable由打开模式位决定io.c 定义了一组宏把O_RDONLY/O_WRONLY/O_RDWR分解为可读/可写判定模式字符串如r/w/a由io_modestr_to_flags解析为 open flags。平台宏映射Windows 下open/close/read/write/lseek/isatty全部替换为_open/_close/_read/_write/_lseek/_isatty并把O_TMPFILE映射为O_TEMPORARYUnix 下引入sys/wait.h支撑popen的子进程回收io.c。这意味着同一份 mruby 字节码可跨 Linux/BSD/macOS/Windows 编译运行但具体能力仍受目标平台限制如 iPhone 平台禁用popen见 io.c。MRB_O_*标志位常量MRB_O_RDONLY…MRB_O_DSYNC/MRB_O_RSYNC也在 io.h 中定义供 C 扩展以与平台无关的方式表达打开模式。六、测试覆盖与行为验证mruby-io 的测试分为 Ruby 层与 C 层两组是确认方法行为最直接的依据test/io.rb约 667 行覆盖IO.open/IO.new/IO.for_fd、close/closed?、eof?含空文件、写模式抛IOError、读后置 EOF 三种场景、flush、getc/getbyte、read/readlines、seek/pos/rewind、sysread/syswrite、pipe/popen、select、fileno、isatty等MRubyIOTestUtil.io_test_setup会准备测试文件Windows 与 Unix 下分别用\r\n/\n与cmd /c/空串适配test/io.rb。test/file.rb 与 test/file_test.rb覆盖File.open/File.new、basename/dirname/extname/join/expand_path、chmod/unlink/rename/readlink/realpath/symlink?/flock/umask以及 FileTest 断言组。test/mruby_io_test.cC 层测试验证mrb_io_fileno等导出接口。这些测试同时依赖mruby-time见 mrbgem.rake因此本地运行测试时该 gem 必须一并启用。七、在本仓库中的角色nghttpx 的 mruby 脚本扩展mruby-io 不是孤立存在的——它是 mruby 官方 mrbgems 集合之一随 mruby 以 third-party 方式内嵌于 nghttp2。nghttp2 的 CMake 提供WITH_MRUBY选项CMakeOptions.txt启用后会把 mruby 构建为静态库mruby-libthird-party/CMakeLists.txt并编译 nghttpx 的 mruby 模块shrpx_mruby.cc、shrpx_mruby_module.cc、shrpx_mruby_module_env.cc、shrpx_mruby_module_request.cc、shrpx_mruby_module_response.ccsrc/CMakeLists.txt最终链接进nghttpx可执行文件src/CMakeLists.txt。nghttpx 使用 mruby 实现 HTTP/2 请求/响应处理阶段的脚本钩子而脚本中读写文件、操作管道、读取环境变量等需求正由 mruby-io 支撑。换言之本仓库的 fluent-bit 构建链通过 nghttp2 间接携带了 mruby 与 mruby-io若在脚本中使用了本 README 表格之外的方法如IO.binread在 mruby 运行时中会直接失败——这正是对照实现清单的价值所在。八、实用建议以本表为准规划脚本mruby 不是 CRubyIO.write、IO.readlines、IO#read_nonblock、IO#reopen等在 mruby-io 中未实现涉及这些能力时改用已实现的组合如IO.sysopenIO#sysread。善用 Ruby 层补齐的方法、each_line、rewind、pos、ungetbyte等已在 mrblib/io.rb 提供可放心使用File.join/File.expand_path/File.basename/File.extname是纯 Ruby 路径处理利器。留意平台差异Windows 上File.umask无效、flock由LockFileEx模拟、IO.popen依赖cmd /ciPhone 平台禁用popen。构建约束启用本 gem 的构建不能同时定义MRB_NO_STDIOWindows 构建自动链接ws2_32。测试自证修改或二次开发 mruby-io 时运行 test/io.rb 与 test/file.rb 即可回归验证行为一致性。附Licensemruby-io 采用 MIT License版权归 Internet Initiative Japan Inc.2013与 mruby developers2017所有许可全文见 README.md 末尾。【免费下载链接】fluent-bitFast and Lightweight Logs, Metrics and Traces processor for Linux, BSD, OSX and Windows项目地址: https://gitcode.com/GitHub_Trending/fl/fluent-bit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考