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

从/ proc读取文件的时候,我的行为真的很奇怪如果我用前奏的readFile懒惰的读取/ proc / pid / stat – 它可以工作,但不是我想要的。 使用Data.ByteString.readFile切换到严格阅读给了我一个空string。

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

所以使用System.IO.readFile读取/ proc / pid / stat根本不起作用。 它在0.5秒的间隔内给了我相同的结果。 我认为这是由于懒惰和半closures句柄或什么…打开和closures文件句柄显式工作。

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

但是,为什么上面如果我们有bytestring严格阅读。 对?

这是我卡住的地方。

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

这总是返回一个空string。 还在GHCI中进行了testing。 有什么build议么。 谢谢。

更新

谢谢丹尼尔的build议。

这是我真正需要做的。 这可能有助于充分展示我的困境,并提出更多的一般性build议。

我需要计算进程统计信息。 以下是代码的一部分(仅以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. 如果我将整个计算填入其中,但如果计算耗费时间,那么文件将会工作(正确closures句柄),但间隔不会严格为0.5。
  4. 显式打开和closures句柄并使用hGetContents不起作用! 出于同样的原因,readFile不会。

在这种情况下工作的唯一的事情是在上面的代码片段中用hGetLine明确地打开和closures句柄。 但是这不够好,因为一些proc文件比/ proc / meminfo多一行。

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

我试图这样做:

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

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

任何帮助,build议非常感激。

ByteString代码是

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

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

在编写这种类型的东西之前,检查一下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