使用Process.spawn作为Process.fork更换(Using Process.spaw

2019-06-17 22:57发布

我的开发环境是运行红宝石1.9.3p125(RubyInstaller)和轨道3.2.8在Windows机器。

,来了一次又一次,使用第三方的宝石时,是缺乏fork()的Windows上的一个问题。 这已经阻碍了最近我使用几乎任何分布式测试运行的宝石(如能力这些 ),由于他们对叉的依赖。

在计算器上一些老的问题,试图找到解决这个同样的问题,但要么加入Process.spawn到红宝石之前,还是来自人们被迫使用Ruby的旧版本,某些其他原因。

其中提出的解决方案是使用Cygwin获得fork()的支持,这简直是出了这个问题 - 我想我宁愿完全切换到Linux,在这之前。

另一个提出的解决方案已经使用Win32的过程宝石获得fork()的支持。 叉支撑从最新的版本(0.7.0)移除,并使用下一个最旧的版本(0.6.6),它不(排序的)支持叉子似乎不起作用,至少在运行任何分布式的测试宝石,我已经试过(叉勺,并行测试,水润,Specjour,几乎所有的人)。 有趣的是,宝石的作者暗示,在自述,以Process.spawn是用于Process.fork可接受的解决方法。

我已经看到了很多的信息或者暗示,或说明完全是菌种可作为叉的替代品,在Windows上,使用Ruby 1.9。 我已经花了许多时间玩这个了相当数量的,基本上是试图取代Process.fork与Process.spawn几个引用的宝石,没有成功。 在我看来,也许这个行为相似,但不完全相同。 例如,目前还不清楚产卵实际拷贝以同样的方式叉呢,或者干脆整个过程是否创建与所提供的参数的新方法。 目前还不清楚,以产卵方法是否甚至接受另一个红宝石方法作为一个参数,或仅一个系统命令。 该文档似乎暗示它只是一个命令,但在方法似乎工作(排序的),但我可能不正确地做事。 我认为,对于一些事情,叉只是用来创建一个“便宜线”,在不支持线程以前的Ruby版本。 然而,似乎这些分布式测试宝石可以合法地依赖于fork()的全部功能,以保持该项目的状态,并为每个测试不加载整个红宝石环境。 这是我的正常程序的职责和经验之外的一点,所以我可能会作出一些不正确的假设。

所以,我的问题是,可以Process.spawn相对简单地用来实现相同的效果作为Process.fork,在所有情况下? 我开始怀疑没有,但如果是这样,可能有人请张贴的一个将如何去进行转换的一个例子吗?

Answer 1:

编辑 :有一个常用的情况fork()可以被替换为spawn() -的fork() - exec()组合。 许多较旧的(现代)的UNIX应用程序,当他们想产生另一个过程中,会第一叉,然后再做一个exec调用( exec替换当前的进程与其他)。 这实际上并不需要fork() ,这就是为什么它可以替换spawn() 所以这:

if(!fork())
  exec("dir")
end

可以替换为:

Process.spawn("dir")

如果任何宝石使用fork()这样的,修复是容易的。 否则,它几乎是不可能的。


编辑 :之所以Win32的进程的执行fork()不工作是,(据我可以从文档告诉),它基本上 spawn()这是不fork()在所有。


不,我不认为这是可以做到。 你看, Process.spawn使用默认的空白状态和本机代码的新方法。 所以,虽然我可以这样做Process.spawn('dir')将开始运行一个空白工艺dir ,它不会复制任何当前进程的状态。 这只是给你的程序的连接是父 - 子连接。

你看, fork()是一个非常低的水平通话。 例如,在Linux上,什么fork()主要作用是这样的:首先,一个新的进程恰好与克隆寄存器状态下创建。 然后,Linux确实一个写入时复制引用到所有的父进程的页面。 那么Linux克隆其他进程的标志。 显然,所有这些操作只能由内核完成,Windows内核不具备的设施要做到这一点(而不能修补要么)。

从技术上讲,只有本机程序需要OS为某种fork()样的支持。 任何代码层需要层的合作它上面做类似fork() 。 因此,虽然本机C代码需要的内核到餐桌的合作,红宝石理论上只需要解释的合作做一个叉。 然而,Ruby解释器不具有快照/恢复功能,这将是必然实现一个叉。 正因为如此,一般的Ruby叉由分叉解释本身,而不是Ruby程序来实现的。

所以,虽然如果你能修补Ruby解释器添加一个启动/停止和快照/恢复功能,你可以做到这一点,但在其他方面? 我不认为如此。

所以,你有什么选择? 这是我能想到的:

  • 修补Ruby解释器
  • 修补使用该代码fork()到也许使用线程或产卵
  • 获得UNIX(我的建议是一个)
  • 使用Cygwin

编辑1:我不会建议使用Cygwin的叉,因为它涉及到特殊的Cygwin进程表, 没有写入时复制,这使得它非常低效的。 此外,它涉及到很多来回跳跃和大量复制。 避免它,如果可能的。 此外,因为Windows不提供任何设施,以复制地址空间,叉很可能会失败,并且将相当多的时间(见这里 )。



文章来源: Using Process.spawn as a replacement for Process.fork