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 を使用してリソースを解放する必要があります
  • strict IO: 入力が読み取られたら手動で閉じることができます。またはブラケットコンビネータを使用します (例: finallyor bracket)
  • インクリメンタル IO (コンジット、反復): フレームワークに閉じさせます。
于 2012-05-29T21:58:42.543 に答える
6

HaddockSystem.IOのドキュメントには、次のように書かれています。

GHC 注: プログラムによって参照されなくなったことをガベージ コレクターが検出すると、Handle は自動的に閉じられます。ただし、この動作に依存することは一般的に推奨されません。ガベージ コレクターは予測不能です。可能であれば、明示的な hClose を使用して、不要になったハンドルを閉じます。GHC は現在、ファイル記述子がなくなったときに解放しようとはしません。これが起こらないようにするのはあなたの責任です。

于 2012-05-29T21:58:15.080 に答える