8

/procからファイルを読み取るときに本当に奇妙な動作をします。preludeのreadFileを使用して/proc/ pid / statを怠惰に読み取ると、動作しますが、希望どおりに動作しません。Data.ByteString.readFileを使用して厳密な読み取りに切り替えると、空の文字列が表示されます。

短い間隔で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でもテスト済み。助言がありますか。ありがとう。

---更新---

ダニエル、提案ありがとうございます。

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

プロセス統計を計算する必要があります。例として、コードの一部(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は、怠惰のために機能しません
  2. ByteStringの厳密な関数は機能しません。説明してくれてありがとうダニエル。
  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'

その行がファイルを完全に読み取るトリガーになることを期待しています。運がない。それでも空のリストを取得します。

どんな助け、提案も大歓迎です。

4

2 に答える 2

5

ByteStringコードは

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

しかし/proc/whatever、実際のファイルではありません。オンデマンドで生成されstatます。ファイル サイズを取得すると、0 になります。したがって、ByteString0readFileバイトを正常に読み取ります。

于 2012-04-17T02:26:35.740 に答える
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
于 2012-04-17T06:02:33.047 に答える