2012-03-08 18 views
10

Devo tenere traccia delle chiamate di sistema per i file specifici di read e al momento sto analizzando l'output di strace. Poiché read funziona su descrittori di file, devo tenere traccia dell'attuale mappatura tra fd e path. Inoltre, è necessario monitorare seek per mantenere aggiornata la posizione corrente nella traccia.Come tracciare le operazioni IO per file in Linux?

Esiste un modo migliore per ottenere tracce IO per file percorso per ogni applicazione in Linux?

risposta

5

In primo luogo, probabilmente non è necessario tenere traccia perché la mappatura tra fd e path è disponibile in /proc/PID/fd/.

In secondo luogo, è possibile utilizzare il trucco e il sovraccarico LD_PRELOAD nella chiamata di sistema C open, seek e read. Ci sono alcuni articoli here e there su come sovraccaricare malloc/free.

Suppongo che non sarà troppo diverso per applicare lo stesso tipo di trucco per quelle chiamate di sistema. Deve essere implementato in C, ma dovrebbe richiedere molto meno codice ed essere più preciso rispetto all'analisi dell'output strace.

+0

concordato. Ora sto usando LD_PRELOAD come alternativa, ma speravo che esistessero alcune soluzioni out-of-the-box. Grazie. –

7

Si potrebbe attendere che i file che devono essere aperti in modo da poter imparare il fd e allegare strace dopo il lancio processo come questo:

strace -p pid traccia -e = -e file leggere = fd

1

Penso sovraccarico open, seek e read è una buona soluzione. Ma solo FYI se vuoi analizzare e analizzare l'output di strace a livello di codice, ho fatto qualcosa di simile prima e ho inserito il mio codice in github: https://github.com/johnlcf/Stana/wiki

(l'ho fatto perché devo analizzare il risultato strall del programma eseguito da altri, che non è facile chiedere loro di fare LD_PRELOAD.)

5

systemtap - una sorta di re-implementazione di DTrace per Linux - potrebbe essere di aiuto qui.

Come con strace hai solo il fd, ma con l'abilità di scripting è facile mantenere il nome del file per un file fd (a meno che non ci siano cose divertenti come il dup). C'è lo script di esempio iotime che è illustates it.

#! /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] 
} 

Funziona solo fino a un certo numero di file perché la mappa di hash è limitata.

0

Probabilmente il modo meno brutto per farlo è usare fanotify. Fanotify è una funzionalità del kernel di Linux che consente di monitorare a basso costo gli eventi del filesystem. Non sono sicuro se permette il filtraggio da PID, ma fa passare il PID al vostro programma in modo da poter verificare se si tratta di quello che ti interessa

Ecco un esempio di codice bella:. http://bazaar.launchpad.net/~pitti/fatrace/trunk/view/head:/fatrace.c

Tuttavia, sembra essere poco documentato al momento.Tutti i documenti che ho trovato sono http://www.spinics.net/lists/linux-man/msg02302.html e http://lkml.indiana.edu/hypermail/linux/kernel/0811.1/01668.html

+0

[Ecco un po 'di più su fanotify] (http://stackoverflow.com/questions/1835947/) – Tobu

0

L'analisi della riga di comando utilizza come strace è ingombrante; potresti usare invece syscall ptrace(). Vedi man ptrace per i dettagli.

Problemi correlati