我的第一印象readFile
是它的便利性和它让文件描述符打开时间超过需要的可能性之间的权衡,没有办法关闭它们.作为一个实验,我尝试了以下(非常实用的)程序,认为它可能会通过尝试维护一千个打开的文件描述符来阻塞:
main = do
mapM_ (\idx -> readIt) [1..1000]
where readIt = do
contents <- readFile "/etc/passwd"
putChar $ head contents
Run Code Online (Sandbox Code Playgroud)
但它实际上在回收文件描述符方面做得非常好; 计数永远不会超过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
Run Code Online (Sandbox Code Playgroud)
这是怎么回事?是仅仅contents
获得GC 的值,并且使用它们不再引用的文件描述符?或者是否有一些单独的机制来管理文件描述符资源?无论机制是什么,它似乎都运行良好 - 你怎么知道何时最好hClose
明确使用?
最好是自己显式关闭资源,只有当您有一些可以手动实施的低级资源约束时.
需要考虑的案例:
finally
或bracket
)该黑线鳕文档为System.IO
有这样一段话:
GHC注意:当垃圾收集器检测到它已被程序取消引用时,句柄将自动关闭.但是,通常不建议依赖此行为:垃圾收集器是不可预测的.如果可能,使用显式hClose在不再需要时关闭Handles.GHC目前没有尝试在文件描述符耗尽时释放文件描述符,您有责任确保不会发生这种情况.