Haskell:从/ proc读取。严格和懒惰的问题。流程统计

时间:2012-04-17 02:14:11

标签: linux haskell system

从/ proc读取文件时,我的行为非常奇怪 如果我使用prelude的readFile懒惰地阅读/ proc / pid / stat - 它可以工作但不是我想要的方式。 使用Data.ByteString.readFile切换到严格读取会给我一个空字符串。

我需要严格阅读,以便能够在短时间内比较两次读取的结果。

因此使用System.IO.readFile来读取/ proc / pid / stat根本不起作用。它在0.5秒的间隔内给出了相同的结果。我认为这是由于懒惰和半闭手柄或其他东西...... 打开和关闭文件句柄显然有效。

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

但是为什么上面的内容如果我们有bytestring严格读取。正确?

这就是我被困住的地方。

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

这总是返回一个空字符串。也在GHCI中测试过。 有什么建议。感谢。

--- 更新 ---

感谢Daniel的建议。

这是我实际需要做的。这可能有助于充分显示我的困境,并提出更多一般性建议。

我需要计算流程统计信息。以下是代码的一部分(仅作为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中的严格函数不起作用。感谢Daniel的解释。
  3. 如果我将整个计算填入其中,那么
  4. withFile会正常工作(它会正确关闭句柄)但是由于计算需要时间,因此间隔不会严格为0.5。
  5. 显式打开和关闭句柄并使用hGetContents不起作用!出于同样的原因,readFile没有。
  6. 在这种情况下唯一可行的方法是在上面的代码片段中用hGetLine显式打开和关闭句柄。但这还不够好,因为一些proc文件比/ proc / meminfo更像一行。

    所以我需要一个能严格读取整个文件的函数。像hGetContents这样的东西,但严格。

    我试图这样做:

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

    希望这些行会触发它完整地读取文件。没运气。仍然得到一个空列表。

    任何帮助,建议都非常感谢。

2 个答案:

答案 0 :(得分:5)

ByteString代码

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

但是/proc/whatever不是真正的文件,它是按需生成的,当你stat获取文件大小时,你得到0.所以ByteString的{​​{1}成功读取0个字节。

答案 1 :(得分: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