8

我对它的第一印象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

这是怎么回事?是否只是contentsGC 的值以及不再引用的文件描述符?还是有一些单独的机制来管理文件描述符资源?无论机制是什么,它似乎都运行得很好——你怎么知道什么时候最好hClose显式使用?

4

2 回答 2

8

最好自己显式关闭资源,只有当您有一些可以手动强制执行的低级别资源约束时。

需要考虑的案例:

  • 通过惰性 IO 获取的资源:必须使用 GC 来释放资源
  • 严格 IO:一旦读取输入就可以手动关闭;或使用包围组合器(例如finallybracket
  • 增量 IO(管道、迭代器):让框架为您关闭它。
于 2012-05-29T21:58:42.543 回答
6

Haddock 文档System.IO有这样的说法:

GHC 注意:当垃圾收集器检测到它已被程序未引用时,Handle 将自动关闭。但是,通常不建议依赖这种行为:垃圾收集器是不可预测的。如果可能,在不再需要句柄时使用显式的 hClose 来关闭句柄。GHC 目前不会在文件描述符用完时尝试释放它们,您有责任确保不会发生这种情况。

于 2012-05-29T21:58:15.080 回答