fork 和 Windows 不能很好地结合在一起。 Unix 和 Windows 中处理进程的理念非常不同。
在 Unix 中,进程是功能分解的主要机制。 IE。在 Unix 中,应用程序或服务将由多个协作进程组成的管道组成。进程在 Unix 中的使用方式与对象在 Ruby 中的使用方式相似。为了使其发挥作用,流程便宜且轻量级。
在 Windows 中,组件是功能分解的主要机制。 IE。在 Windows 中,应用程序或服务将由一个单个进程组成,使用多个组件实现。 组件 的使用类似于 Ruby 中的对象或 Unix 中的进程。这意味着 Windows 中的进程不需要廉价或轻量级,事实上,它们非常昂贵、沉重且创建和销毁速度慢。
除了使用非常不同且成本更高的流程之外,它们的交互方式也非常不同。用于创建、管理和销毁进程的 API 非常不同。在 Windows 中没有与 fork 完全等效的方法,也没有简单、高效的方法来实现它。
不幸的是,使用 TruffleRuby 或 JRuby 也无济于事:虽然 TruffleRuby 和 JRuby 的 Windows 支持传统上往往比 YARV 更好,但这不适用于fork,因为 JVM 支持不允许:JVM 上的forking 创建了一个分支,其中只有主线程,但没有 GC、编译器、I/O 或其他帮助程序和辅助线程,这会让你的 JVM 崩溃。只有当您立即 exec 一个不同的进程,它才真正起作用,从而退出 JVM。
话虽如此,Kernel#fork 的这种特殊用法可能可以在 JRuby 上实现,因为(如果我没记错的话),您可以在相同的JVM。因此,对于这种特殊用途,您只在后台执行一些 Ruby 代码,您实际上并不需要到fork,您可以在不同的线程中启动一个新的 JRuby 实例。
但据我所知,这并没有实现。 (不过可能会为第一次贡献做一个有趣的项目!)
与您在 Windows 中使用 Kernel#spawn 的代码最接近的等价物可能类似于:
spawn(RbConfig.ruby, '-e' << <<~BLOCK_END)
#Example background code
x = 0
while x < 100 do
File.write("./example_file.txt", x.to_s, Mode: "a")
end
BLOCK_END
但这不是解决问题的正确方法。您将其视为 X/Y 问题:您有问题 X。您知道在 Unix 中的解决方案是 Y。现在,不是问“我如何在 Windows 上解决 problem X”这个问题,而是问“我如何实施解决方案” Y on Windows”,甚至没有质疑 Y 是否是正确的解决方案。
所以,您的问题不应该是 Windows 中的 fork 等价物是什么,而是如何在 Windows 中设计应用程序。