2012-03-08 21 views
10

Tôi cần theo dõi read cuộc gọi hệ thống cho các tệp cụ thể và tôi hiện đang thực hiện việc này bằng cách phân tích cú pháp đầu ra của strace. Kể từ khi read hoạt động trên các bộ mô tả tệp, tôi phải theo dõi ánh xạ hiện tại giữa fdpath. Ngoài ra, seek phải được theo dõi để giữ vị trí hiện tại được cập nhật trong theo dõi.Cách theo dõi hoạt động IO trên mỗi tệp trong Linux?

Có cách nào tốt hơn để có được các dấu vết IO cho mỗi ứng dụng, mỗi tệp trên đường dẫn trong Linux không?

Trả lời

5

Trước tiên, có thể bạn không cần phải theo dõi vì ánh xạ giữa fdpath có sẵn trong /proc/PID/fd/.

Thứ hai, có thể bạn nên sử dụng thủ thuật và quá tải LD_PRELOAD trong C open, seekread cuộc gọi hệ thống. Có một số bài viết herethere về cách quá tải malloc/miễn phí.

Tôi đoán sẽ không quá khác biệt khi áp dụng cùng một loại mẹo cho các cuộc gọi hệ thống đó. Nó cần phải được thực hiện trong C, nhưng nó phải mất ít mã hơn và chính xác hơn việc phân tích cú pháp đầu ra strace.

+0

Đồng ý. Tôi hiện đang sử dụng LD_PRELOAD làm phương án thay thế, nhưng hy vọng có một số giải pháp vượt trội hơn. Cảm ơn. –

7

Bạn có thể chờ đợi cho các tập tin được mở để bạn có thể tìm hiểu những fd và đính kèm strace sau khi khởi động quá trình như thế này:

strace -p pid -e dấu vết = file -e đọc = fd

1

tôi nghĩ quá tải open, seekread là một giải pháp tốt. Nhưng chỉ FYI nếu bạn muốn phân tích cú pháp và phân tích đầu ra strace lập trình, tôi đã làm một cái gì đó tương tự trước và đặt mã của tôi trong github: https://github.com/johnlcf/Stana/wiki

(Tôi đã phân tích kết quả strace của chương trình do người khác chạy, không dễ dàng yêu cầu họ làm LD_PRELOAD.)

5

systemtap - một loại triển khai lại DTrace cho Linux - có thể trợ giúp ở đây.

Như với strace bạn chỉ có fd, nhưng với khả năng kịch bản nó rất dễ dàng để duy trì tên tập tin cho một fd (trừ khi với những thứ thú vị như dup). Có ví dụ kịch bản iotime rằng illustates nó.

#! /usr/bin/env stap 

/* 
* Copyright (C) 2006-2007 Red Hat Inc. 
* 
* This copyrighted material is made available to anyone wishing to use, 
* modify, copy, or redistribute it subject to the terms and conditions 
* of the GNU General Public License v.2. 
* 
* You should have received a copy of the GNU General Public License 
* along with this program. If not, see <http://www.gnu.org/licenses/>. 
* 
* Print out the amount of time spent in the read and write systemcall 
* when each file opened by the process is closed. Note that the systemtap 
* script needs to be running before the open operations occur for 
* the script to record data. 
* 
* This script could be used to to find out which files are slow to load 
* on a machine. e.g. 
* 
* stap iotime.stp -c 'firefox' 
* 
* Output format is: 
* timestamp pid (executabable) info_type path ... 
* 
* 200283135 2573 (cupsd) access /etc/printcap read: 0 write: 7063 
* 200283143 2573 (cupsd) iotime /etc/printcap time: 69 
* 
*/ 

global start 
global time_io 

function timestamp:long() { return gettimeofday_us() - start } 

function proc:string() { return sprintf("%d (%s)", pid(), execname()) } 

probe begin { start = gettimeofday_us() } 

global filehandles, fileread, filewrite 

probe syscall.open.return { 
    filename = user_string($filename) 
    if ($return != -1) { 
    filehandles[pid(), $return] = filename 
    } else { 
    printf("%d %s access %s fail\n", timestamp(), proc(), filename) 
    } 
} 

probe syscall.read.return { 
    p = pid() 
    fd = $fd 
    bytes = $return 
    time = gettimeofday_us() - @entry(gettimeofday_us()) 
    if (bytes > 0) 
    fileread[p, fd] += bytes 
    time_io[p, fd] <<< time 
} 

probe syscall.write.return { 
    p = pid() 
    fd = $fd 
    bytes = $return 
    time = gettimeofday_us() - @entry(gettimeofday_us()) 
    if (bytes > 0) 
    filewrite[p, fd] += bytes 
    time_io[p, fd] <<< time 
} 

probe syscall.close { 
    if ([pid(), $fd] in filehandles) { 
    printf("%d %s access %s read: %d write: %d\n", 
      timestamp(), proc(), filehandles[pid(), $fd], 
      fileread[pid(), $fd], filewrite[pid(), $fd]) 
    if (@count(time_io[pid(), $fd])) 
     printf("%d %s iotime %s time: %d\n", timestamp(), proc(), 
      filehandles[pid(), $fd], @sum(time_io[pid(), $fd])) 
    } 
    delete fileread[pid(), $fd] 
    delete filewrite[pid(), $fd] 
    delete filehandles[pid(), $fd] 
    delete time_io[pid(),$fd] 
} 

Chỉ hoạt động tối đa một số tệp nhất định vì bản đồ băm bị giới hạn kích thước.

0

Có lẽ cách xấu xí nhất để làm điều này là sử dụng chế độ quạt. Fanotify là một cơ sở hạt nhân Linux cho phép xem các sự kiện hệ thống tập tin với giá rẻ. Tôi không chắc chắn nếu nó cho phép lọc bởi PID, nhưng nó không vượt qua PID để chương trình của bạn, do đó bạn có thể kiểm tra xem đó là một trong những bạn đang quan tâm đến

Dưới đây là một mẫu mã đẹp:. http://bazaar.launchpad.net/~pitti/fatrace/trunk/view/head:/fatrace.c

Tuy nhiên, dường như nó không được ghi chép lại tại thời điểm này.Tất cả tài liệu tôi có thể tìm thấy là http://www.spinics.net/lists/linux-man/msg02302.htmlhttp://lkml.indiana.edu/hypermail/linux/kernel/0811.1/01668.html

+0

[Dưới đây là một chút chi tiết về cách làm mát] (http://stackoverflow.com/questions/1835947/) – Tobu

0

Phân tích cú pháp dòng lệnh như strace là cồng kềnh; bạn có thể sử dụng ptrace() syscall để thay thế. Xem man ptrace để biết chi tiết.