2012-04-17 33 views
8

我真的很奇怪的現象,而從/ proc 讀取文件。如果我讀與前奏的READFILE的/ proc/PID/STAT懶洋洋地 - 它的工作原理,但不是我想要的方式。 使用Data.ByteString.readFile切換到嚴格讀取會給我一個空字符串。Haskell:從/ proc讀取。嚴格和懶惰的問題。進程統計

我需要嚴格的閱讀在這裏能夠比較短的時間內兩次讀取的結果。

因此,使用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中進行了測試。 任何建議。謝謝。

--- 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不起作用由於懶惰
  2. 從字節串嚴格的功能不起作用。謝謝丹尼爾的解釋。
  3. withFile會工作(它正確地關閉句柄)如果我塞進了整個計算中,但隨後的時間間隔不會嚴格如0.5計算需要時間。
  4. 明確打開和關閉句柄並使用hGetContents不起作用!出於同樣的原因,readFile不會。

在這種情況下工作的唯一的事情是在上面的代碼片段中用hGetLine明確地打開和關閉句柄。但是這不夠好,因爲一些proc文件比/ proc/meminfo多一行。

所以我需要將嚴格讀取整個文件的功能。像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,所以ByteStringreadFile成功讀取0字節。

+1

好的。現在有點清楚了。那麼這種情況下的解決方案是什麼?我需要在0.5秒的時間間隔內讀取stat文件。懶惰只是殺死了演出。我是否必須明確地打開和關閉文件句柄?謝謝。 – 2012-04-17 02:34:08

+0

我認爲你必須明確地打開和關閉。雖然也許你可以打開一次並保持打開狀態。無論如何,我認爲'hGetNonBlocking'是要走的路。 'hGetNonBlocking k'嘗試讀取'k'個字節,如果可用更少,則需要該字節。或者'hGetLine'。 – 2012-04-17 02:38:17

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

有趣......謝謝。你知道當你學習時是什麼樣的,你只是想嘗試和做你自己的事情。我應該看看。 – 2012-04-17 06:32:34