r.s*_*cky 8 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
Run Code Online (Sandbox Code Playgroud)
但是,如果我们对bytestring进行严格读取,为什么还要这样做呢?对?
这是我被卡住的地方.
import qualified Data.ByteString as B
B.readFile "/proc/pid/stat" >>= print
Run Code Online (Sandbox Code Playgroud)
这总是返回一个空字符串.也在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
Run Code Online (Sandbox Code Playgroud)
在这种情况下唯一可行的方法是在上面的代码片段中使用hGetLine显式打开和关闭句柄.但这还不够好,因为一些proc文件比/ proc/meminfo更像一行.
所以我需要一个能严格读取整个文件的函数.像hGetContents但严格的东西.
我试图这样做:
readProc f = do
h <- openFile f ReadMode
c <- hGetContents h
let c' = lines c
hClose h
return c'
Run Code Online (Sandbox Code Playgroud)
希望这些行会触发它完整地读取文件.没运气.仍然得到一个空列表.
任何帮助,建议非常感谢.
该ByteString码是
readFile :: FilePath -> IO ByteString
readFile f = bracket (openBinaryFile f ReadMode) hClose
(\h -> hFileSize h >>= hGet h . fromIntegral)
Run Code Online (Sandbox Code Playgroud)
但是,/proc/whatever是不是一个真正的文件,它是按需生成的,当你stat他们得到的文件大小,你得到0,所以ByteString的readFile成功读取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
Run Code Online (Sandbox Code Playgroud)