Haskell: Reading from / proc. Questions with rigor and laziness. Process statistics

I have really strange behavior when reading files from / proc. If I read / proc / pid / stat lazily with prelude readFile - it works, but not the way I want. Switching to strict reading with Data.ByteString.readFile gives me an empty string.

I need a rigorous reading here to be able to compare the results of two readings in a short amount of time.

So using System.IO.readFile to read / proc / pid / stat just doesn't work. This gives me the same result at 0.5 second intervals. I suppose this is due to laziness and a half-closed pen or something else ... The file descriptor opens and closes.

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

But why above if we have a string reading bytestring. Correctly?

This is where I am stuck.

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

This always returns an empty string. Also tested at GHCI. Any suggestions. Thanks.

--- UPDATE ---

Thanks to Daniel for the suggestions.

This is what I really need to do. This can help to fully show my dilemma and provide more general suggestions.

I need to calculate process statistics. The following is part of the code (CPU usage only).

 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 
  • Prelude.readFile not working due to laziness
  • Strict functions from ByteString do not work. Thanks to Daniel for the explanation.
  • withFile will work (it closes the descriptor correctly) if I fill in all the calculations in it, but then the interval will not be strictly 0.5, since the calculations will take time.
  • Opening and closing handles explicitly and using hGetContents does not work! For the same reason, readFile does not.

The only thing that works in this situation is to explicitly open and close the descriptors using hGetLine in the code fragment. But this is not good enough, as some proc files have more than one line, for example / proc / meminfo.

So, I need a function that will strictly read the entire file. Something like hGetContents, but strict.

I tried to do this:

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

Hoping that the lines will call it to read the file completely. Bad luck. Anyway, get an empty list.

Any help, suggestion very much appreciated.

+8
linux haskell system
source share
2 answers

ByteString Code

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

But /proc/whatever not a real file, it is generated on demand, when you stat them to get the file size, you get 0. So ByteString readFile successfully reads 0 bytes.

+5
source share

Before encoding this type of thing, it is generally recommended to check if something already exists in Hackage. In this case, I found the procstat package that seems to work beautifully:

 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 
+5
source share

All Articles