2012-05-29 44 views
8

readFile我对readFile的第一印象是在它的方便性和它将文件描述符打开时间长于需要的可能性之间进行权衡,无法关闭它们。作为一个实验我尝试以下(非常实用)计划,认为它可能是由试图维持一千打开的文件描述符呛:什么时候明确关闭文件句柄?

main = do 
    mapM_ (\idx -> readIt) [1..1000] 
    where readIt = do 
      contents <- readFile "/etc/passwd" 
      putChar $ head contents 

但它实际上回收文件描述符的一个不错的工作;计数从未超过70左右:

open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 4 
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 5 
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 6 
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 7 
... 
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 65 
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 66 
close(3)        = 0 
close(4)        = 0 
close(5)        = 0 
... 
close(54)        = 0 
close(55)        = 0 
close(56)        = 0 
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 3 
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 4 

这是怎么发生的?难道只是contents的值正在GC'd,并且它们没有被引用的文件描述符?还是有一些独立的管理文件描述符资源的机制?不管是什么机制,它似乎都工作得很好 - 你怎么知道什么时候最好明确地使用hClose

+1

我相信这只是导致文件描述符关闭的GC。 –

+0

一般来说,最好使用确保确定性资源(除内存之外)处理的机制,这在Haskell中应该是'bracket'。除了一个简单的例子,不要相信GC和文件。 –

+1

括号只对严格IO有意义 - 否则效果可能会通过惰性数据泄漏出去。 –

回答

8

只有当您有一些您可以实际手动执行的低级别资源约束时,才能自行显式关闭资源。

的情况来考虑:通过懒惰IO获得性

  • 资源:必须使用GC来释放资源
  • 严格IO:一次读取输入可以手动关闭;或使用包围组合器(例如finallybracket
  • 增量IO(管道,迭代):让框架为你关闭它。
7

Haddock docs for System.IO有这样一段话:

GHC注:把手会在垃圾收集器检测到它已成为程序未引用自动关闭。但是,通常不推荐依赖这种行为:垃圾收集器是不可预测的。如果可能,使用明确的hClose关闭句柄,当它们不再需要时。 GHC当前没有尝试释放文件描述符,因此您有责任确保这种情况不会发生。

相关问题