Ruby跟踪其打开的文件描述符在哪里?

前端之家收集整理的这篇文章主要介绍了Ruby跟踪其打开的文件描述符在哪里?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这个问题不在乎什么

这个问题不是关于如何使用File#close或File#open block语法自动关闭文件.这是一个关于Ruby在运行时存储其打开的文件描述符列表的问题.

实际问题

如果您有一个打开描述符的程序,但是您无法访问相关的File或IO对象,那么您如何找到当前打开的文件描述符的引用?举个例子:

filename='/tmp/foo'
%x( touch "#{filename}" )
File.open(filename)
filehandle = File.open(filename)

第一个File实例被打开,但对该对象的引用不存储在一个变量中.第二个实例存储在filehandle中,我可以使用#inspect或#close轻松访问它.

但是,丢弃的File对象不会消失;它只是无法以任何明显的方式访问.在对象完成之前,Ruby必须在某处跟踪它,但在哪里?

解决方法

TL; DR

所有File和IO对象都存储在ObjectSpace中.

回答

ObjectSpace课程说:

The ObjectSpace module contains a number of routines that interact with the garbage collection facility and allow you to traverse all living objects with an iterator.

我如何测试这个

我在Ruby 1.9.3p194的控制台上测试了这个.

测试夹具真的很简单.这个想法是具有两个具有不同对象标识的File对象,但只有一个可以通过变量直接访问.另一个是“在某处”.

# Don't save a reference to the first object.
filename='/tmp/foo'
File.open(filename)
filehandle = File.open(filename)

然后,我探讨了不同的方式,我可以与File对象进行交互,即使我没有使用显式的对象引用.一旦我知道ObjectSpace,这真是一件容易的事情.

# List all open File objects.
ObjectSpace.each_object(File) do |f|
  puts "%s: %d" % [f.path,f.fileno] unless f.closed?
end

# List the "dangling" File object which we didn't store in a variable.
ObjectSpace.each_object(File) do |f|
  unless f.closed?  
    printf "%s: %d\n",f.path,f.fileno unless f === filehandle
  end
end

# Close any dangling File objects. Ignore already-closed files,and leave
# the "accessible" object stored in *filehandle* alone.
ObjectSpace.each_object(File) {|f| f.close unless f === filehandle rescue nil}

结论

可能还有其他的方法可以做到这一点,但这是我想出来解决我自己的痒的答案.如果你知道一个更好的方法,请发布另一个答案.世界将是一个更美好的地方.

猜你在找的Ruby相关文章