2012-04-17 11 views
8

/procからファイルを読み込んでいるときに私は本当に奇妙な動作をしました /proc/pid/statをpreludeのreadFileで遅れて読んでも、動作しますが、 Data.ByteString.readFileで厳密な読み込みに切り替えると、空の文字列が返されます。ハスケル:/ procから読む。厳密さと怠惰の問題。プロセスの統計

短い間隔で2回の読み取り結果を比較できるようにするには、ここで厳密な読み取りが必要です。

したがって、System.IO.readFileを使用して/ proc/pid/statを読み込むだけでは機能しません。それは私に0.5秒の間隔の中で同じ結果を与える。私はこれが怠惰なので、半分のハンドルや何かを閉じたものだと考えています... ファイルハンドルのオープンとクローズが明示的に機能します。

h <- openFile "/proc/pid/stat" ReadMode 
st1 <- hGetLine h; hClose h 

しかし、私たちが厳密なバイトテストを行っているのであれば、なぜ上のようになりますか?右?

これは私が立ち往生したところです。

import qualified Data.ByteString as B 
B.readFile "/proc/pid/stat" >>= print 

これは、常に空の文字列を返します。また、GHCIでテストされています。 提案があります。ありがとう。

--- UPDATE ---

は提案をあなたにダニエルありがとうございました。

これは私が実際に行う必要があります。これは、私のジレンマを完全に示し、より一般的な提案をもたらすのに役立つかもしれません。

私はプロセス統計を計算する必要があります。ここでは、コードの一部(CPU使用率のみ)を例として示します。

cpuUsage pid = do 
    st1 <- readProc $ "/proc" </> pid </> "stat" 
    threadDelay 500000 -- 0.5 sec 
    st2 <- readProc $ "/proc" </> pid </> "stat" 
    let sum1 = (read $ words st1 !! 13) + 
      (read $ words st1 !! 14) 
     sum2 = (read $ words st2 !! 13) + 
      (read $ words st2 !! 14) 
    return $ round $ fromIntegral (sum2 - sum1) * jiffy/delay * 100 
    where 
    jiffy = 0.01 
    delay = 0.5 
    readProc f = do 
     h <- openFile f ReadMode 
     c <- hGetLine h 
     hClose h 
     return c 
  1. Prelude.readFileが原因延ByteStringから
  2. 厳格な機能が動作しない怠惰に動作しません。説明のためにダニエルありがとう。
  3. withFile私は全体の計算に詰め込んだ場合、(ハンドルを適切に閉じますが)計算が時間がかかるので、間隔は厳密に0.5にならないでしょう。
  4. ハンドルを明示的に開き、hGetContentsを使用しても動作しません!同じ理由から、readFileはそうではありません。

この状況で機能するのは、上記のコードスニペットでhGetLineを使用してハンドルを明示的に開閉することだけです。しかし、これは、一部のprocファイルが/ proc/meminfoのように1行以上あるため、十分ではありません。

私はファイル全体を厳密に読み取る関数が必要です。 hGetContentsのようなものですが厳しいものです。

私はこれを行うにしようとしていた。

readProc f = do 
    h <- openFile f ReadMode 
    c <- hGetContents h 
    let c' = lines c 
    hClose h 
    return c' 

はラインがフルでファイルを読むためにそれをトリガーすることを願って。運がない。まだ空リストを取得します。

ご意見、ご提案は大変ありがとうございます。

答えて

5

ByteStringコードが

readFile :: FilePath -> IO ByteString 
readFile f = bracket (openBinaryFile f ReadMode) hClose 
    (\h -> hFileSize h >>= hGet h . fromIntegral) 

しかし/proc/whateverであるが、実際のファイルではありませんあなたstat彼らは、ファイルサイズを取得するとき、それは、オンデマンドで生成されます、あなたは0だから、ByteString年代を取得readFileが正常に読み込みます0バイト。

+1

今すぐ少しクリア。だからこのような状況での解決策は何ですか?私は0.5秒間隔でstatファイルを読む必要があります。怠惰はショーを殺すだけです。ファイルハンドルを明示的に開いて閉じる必要がありますか?ありがとう。 –

+0

私はあなたが明示的に開閉しなければならないと思います。多分あなたは一度開いてそれを開いておくことができます。とにかく、私は 'hGetNonBlocking'が行く方法だと思います。 'hGetNonBlocking k'は' k'バイトを読み込もうとしますが、利用可能なバイトが少ない場合はそれを使います。または 'hGetLine'。 –

5

このタイプのものをコーディングする前に、通常、Hackageに何かが存在するかどうかを確認することをお勧めします。この場合、procstatパッケージが見つかりました。うまく動作しているようです。

import System.Linux.ProcStat 

cpuUsage pid = do 
    Just before <- fmap procTotalTime <$> procStat pid 
    threadDelay 500000 -- 0.5 sec 
    Just after <- fmap procTotalTime <$> procStat pid 
    return . round $ fromIntegral (after - before) * jiffy/delay * 100 
    where 
    procTotalTime info = procUTime info + procSTime info 
    jiffy = 0.01 
    delay = 0.5 
+0

興味深い...ありがとう。あなたが学ぶとき、それはあなたが自分のことを試してやりたいことが何であるかをあなたは知っています。私は思っていたはずです。 –

関連する問題