2012-04-17 24 views
8

Tôi có hành vi thực sự lạ trong khi đọc tệp từ/proc Nếu tôi đọc/proc/pid/stat lazily với readFile của prelude - nó hoạt động nhưng không theo cách tôi muốn. Chuyển sang đọc nghiêm ngặt với Data.ByteString.readFile cho tôi một chuỗi rỗng.Haskell: Đọc từ/proc. Các vấn đề nghiêm khắc và lười biếng. Thống kê quy trình

Tôi cần đọc nghiêm ngặt ở đây để có thể so sánh kết quả của hai lần đọc trong khoảng thời gian ngắn.

Vì vậy, việc sử dụng System.IO.readFile để đọc/proc/pid/stat chỉ đơn giản là không hoạt động. Nó mang lại cho tôi kết quả tương tự trong khoảng 0,5 giây. Tôi thấy điều này là do sự lười biếng và một nửa xử lý đóng cửa hoặc một cái gì đó ... Mở và đóng tập tin xử lý một cách rõ ràng hoạt động.

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

Nhưng tại sao điều trên lại xảy ra nếu chúng tôi có đọc nghiêm ngặt. Đúng?

Đây là nơi tôi gặp khó khăn.

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

Điều này luôn trả về một chuỗi trống. Cũng được thử nghiệm trong GHCI. Bất kỳ đề xuất nào. Cảm ơn.

--- CẬP NHẬT ---

Cảm ơn bạn Daniel cho các đề xuất.

Đây là những gì tôi thực sự cần làm. Điều này có thể giúp hiển thị tình trạng tiến thoái lưỡng nan của tôi đầy đủ và mang lại nhiều đề xuất chung hơn.

Tôi cần tính toán thống kê quy trình. Đây là một phần của mã (chỉ sử dụng CPU) làm ví dụ.

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 không hoạt động do sự lười biếng
  2. chức năng nghiêm ngặt từ ByteString không làm việc. Cám ơn Daniel vì lời giải thích.
  3. withFile sẽ hoạt động (nó đóng tay cầm đúng cách) nếu tôi nhồi toàn bộ tính toán vào nó nhưng sau đó khoảng thời gian sẽ không được nghiêm ngặt 0.5 khi tính toán mất thời gian.
  4. Mở và đóng các chốt xử lý một cách rõ ràng và sử dụng hGetContents không hoạt động! Vì lý do tương tự, readFile không.

Điều duy nhất hoạt động trong tình huống này rõ ràng là mở và đóng chốt bằng hGetLine trong đoạn mã trên. Nhưng điều này là không đủ tốt như một số tập tin proc được nhiều hơn sau đó một dòng như/proc/meminfo.

Vì vậy, tôi cần một hàm có thể đọc toàn bộ tệp một cách nghiêm ngặt. Một cái gì đó như hGetContents nhưng nghiêm ngặt.

Tôi đã cố gắng để làm điều này:

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

Hy vọng rằng dòng sẽ kích hoạt nó để đọc các tập tin đầy đủ. Không may mắn. Vẫn nhận được một danh sách trống.

Bất kỳ trợ giúp nào, đề xuất rất được đánh giá cao.

Trả lời

5

ByteString

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

Nhưng /proc/whatever được không phải là một tập tin thực tế, nó được tạo ra theo yêu cầu, khi bạn stat họ để có được kích thước tập tin, bạn sẽ có được 0. Vì vậy ByteString 's readFile đọc thành công 0 byte.

+1

Ok. Bắt một chút rõ ràng ngay bây giờ. Vậy giải pháp trong tình huống này là gì? Tôi cần phải đọc các tập tin stat trong khoảng 0,5 giây. Sự lười biếng chỉ giết chết chương trình. Tôi có phải mở và đóng tệp xử lý một cách rõ ràng không? Cảm ơn. –

+0

Tôi nghĩ bạn phải mở và đóng một cách rõ ràng. Mặc dù có thể bạn có thể mở một lần và giữ nó mở. Dù sao, tôi nghĩ rằng 'hGetNonBlocking' là con đường để đi. 'hGetNonBlocking k' cố gắng đọc' k' bytes, nếu ít có sẵn, nó sẽ lấy nó. Hoặc 'hGetLine'. –

5

Trước khi mã hóa loại điều này, bạn nên kiểm tra xem có điều gì đó đã tồn tại trên Hackage hay không. Trong trường hợp này, tôi đã tìm thấy gói procstat, có vẻ hoạt động độc đáo:

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

Thú vị ... Cảm ơn. Bạn biết nó là như thế nào khi bạn học, bạn chỉ muốn thử và làm những thứ tự của bạn. Tôi nên xem xét mặc dù. –

Các vấn đề liên quan