启动多个 Ruby 实例,而不必诉诸于执行 Ruby 可执行程序,存在着几种方法让你有据可循。 JRuby 允许在一个进程内部拥有多个 JRuby 实例,每个实例运行在各自拥有的本地线程之上。而对于 MRI, why the lucky stiff 则提供了沙箱版 Hack 代码来完成同样的工作。
最近, Rubinius 也为人们带来启动多个 Ruby 运行时的有效支持,用法如下:
vm = Rubinius::VM.spawn "blah", "-e", "puts 'hello\n'" vm.join p vm.stdout.gets
为了了解上述代码的含义,我们请教了 Rubinius项目的 Evan Phoenix。
在被问及多虚拟机(Multi-VM)背后的想法时,Evan 如是回答:
我一直都很清楚,我们应当以某种形式实现这样的功能。关于这项功能的计划各有千秋。是的,启动一个新的虚拟机来完成工作要容易得多,而真正的问题是具体要完成的工作是什么,是如何执行的 [……]。
接着 Evan 补充了一些实现细节:
目前,每个虚拟机都运行在各自的本地线程中(在 Unix 下是 pthread)。这使得每个虚拟机独立运行,而无须知道其它虚拟机的存在,并且保证调度在虚拟机内部完全相同。 Rubinius 是一个表现非常良好的 C 程序,因为它没有使用任何全局变量或者其它,从而使得它的多个拷贝和平共存在同一个地址空间中。
请注意上面的最后一句话对于所有其它的多虚拟机方案也是成立的——一个调用了如System.exit()
这样的全局静态方法或者使用了导致 JVM 崩溃的 JNI 代码的 JRuby 实例,也会同样关闭其它所有的 JRuby 实例。
另外一个有趣的话题是,如何使多个虚拟机相互通信:
管道是其中(的方式)之一。是的,对于子虚拟机,stdio 会被重定向到管道。我也已经加入另一个非常简单的共享消息传递系统。一个虚拟机可以使用一个顶级的单一机制向另一个发送信息。这个机制是虚拟机之间进行交互的唯一途径。并且它还将消息编组到它的共享存储区,这样在虚拟机之间就不存在指针共享了。 现有的共享消息传递机制还可以被扩展,使用共享内存来允许消息在(操作系统)进程之间轻松传递。
这项功能现已存在于 Rubinius 的 git 库中(请参见 InfoQ 关于使用 git 访问 Rubinius 代码库的报道)。如果你只想快速浏览 Rubinius 的源码,那么可以通过这个Web 界面访问Rubnius 的git 代码库。例如,这个链接就是上面提到的消息传递系统相应提交的代码。
查看英文原文: Rubinius adds Multi-VM support
评论