Process.fork应该影响Ruby中的文件io吗?
我在一个可观察对象中使用了Process.fork应该影响Ruby中的文件io吗?,ruby,fork,Ruby,Fork,我在一个可观察对象中使用了Process.fork,但发现它干扰了观察对象文件输出的输出 当我注释掉过程行时,输出的文件包含16行,每行的顺序为0-15。但是,当取消注释时,文件包含136行0-15之间的无序数字。无论过程是否被注释掉,正确的数字都会打印到屏幕上 这是部分预期的行为,还是一个bug?有人知道怎么避开这件事吗 下面的代码再现了这个问题,它是通过剥离原始代码创建的,直到有足够的代码来演示这个问题。使用Process.fork的最初原因是创建几个进程以加快处理速度 需要“观察者” 课堂
Process.fork
,但发现它干扰了观察对象文件输出的输出
当我注释掉过程
行时,输出的文件包含16行,每行的顺序为0-15。但是,当取消注释时,文件包含136行0-15之间的无序数字。无论过程
是否被注释掉,正确的数字都会打印到屏幕上
这是部分预期的行为,还是一个bug?有人知道怎么避开这件事吗
下面的代码再现了这个问题,它是通过剥离原始代码创建的,直到有足够的代码来演示这个问题。使用Process.fork
的最初原因是创建几个进程以加快处理速度
需要“观察者”
课堂记录员
def初始化(通知程序,文件名)
通知者。添加观察者(自身)
@save_file=file.open(文件名“w”)
@i=0
终止
def更新
放置@i
@保存_file.puts@i
@i+=1
终止
def停止
@保存文件。关闭
终止
终止
类通知程序
包括可观察的
def运行
16.5倍
#当以下两个流程行未注释时,
#上述记录器的文件输出不稳定
Process.fork{exit}
等等
改变
通知观察员
终止
终止
终止
notifier=notifier.new
recorder=recorder.new(通知程序'test.data')
通知程序.run
停
分叉时,子进程将包含父进程打开的文件的克隆,其缓冲区中有任何挂起的数据。当子级退出时,它将刷新此数据并关闭其打开的文件。这不会影响父级或同级打开的文件,但因为它们都映射到同一内核fd,所以所有数据都会转到同一输出文件
第一次通过fork时,没有挂起的输出,这样子级就不会在它存在时写入任何内容。第二次,有一个“0\n”挂起,它将在退出时写入,下一次,有一个“0\n1\n”缓冲区,等等。分叉进程可能不会按创建顺序退出(它们是异步的),因此会产生混乱的结果
分叉保留打开的文件和套接字,因此需要小心管理它们
您可能可以通过告诉ruby在每次写入时刷新输出而不是缓冲来修复此行为
class Recorder
def initialize(notifier, filename)
notifier.add_observer(self)
@save_file = File.open(filename, 'w')
@save_file.sync = true # don't buffer this file
@i = 0
end
end
分叉时,子进程将包含父进程打开的文件的克隆,其缓冲区中有任何挂起的数据。当子级退出时,它将刷新此数据并关闭其打开的文件。这不会影响父级或同级打开的文件,但因为它们都映射到同一内核fd,所以所有数据都会转到同一输出文件 第一次通过fork时,没有挂起的输出,这样子级就不会在它存在时写入任何内容。第二次,有一个“0\n”挂起,它将在退出时写入,下一次,有一个“0\n1\n”缓冲区,等等。分叉进程可能不会按创建顺序退出(它们是异步的),因此会产生混乱的结果 分叉保留打开的文件和套接字,因此需要小心管理它们 您可能可以通过告诉ruby在每次写入时刷新输出而不是缓冲来修复此行为
class Recorder
def initialize(notifier, filename)
notifier.add_observer(self)
@save_file = File.open(filename, 'w')
@save_file.sync = true # don't buffer this file
@i = 0
end
end
谢谢,上面的工作。我编辑了你的答案,因为同步线没有什么区别,但原理是正确的,可以用flush代替。奇怪的是,IO#sync=不适合你。我用你的代码尝试了@save_file.sync=true,它与ruby 1.9.2p180(2011-02-18修订版30909)[x86_64-linux]和ruby 1.8.7(2010-01-10 patchlevel 249)[x86_64-linux]一起工作,谢谢,上面的工作正常。我编辑了你的答案,因为同步线没有什么区别,但原理是正确的,可以用flush代替。奇怪的是,IO#sync=不适合你。我在你的代码中尝试了@save_file.sync=true,它与ruby 1.9.2p180(2011-02-18修订版30909)[x86_64-linux]和ruby 1.8.7(2010-01-10 patchlevel 249)[x86_64-linux]