2012-03-08 17 views
10

Necesito hacer un seguimiento de las llamadas al sistema read para archivos específicos, y actualmente estoy haciendo esto al analizar el resultado de strace. Como el read opera en los descriptores de archivos, debo hacer un seguimiento de la asignación actual entre fd y path. Además, se debe monitorear seek para mantener la posición actual actualizada en el rastreo.¿Cómo rastrear las operaciones IO por archivo en Linux?

¿Existe alguna forma mejor de obtener trazas de IO por ruta de archivo y por aplicación en Linux?

Respuesta

5

En primer lugar, es probable que no es necesario hacer un seguimiento porque mapeo entre fd y path está disponible en /proc/PID/fd/.

En segundo lugar, tal vez debería utilizar el truco y la sobrecarga LD_PRELOAD en C open, seek y read llame al sistema. Hay algunos artículos here y there sobre cómo sobrecargar malloc/free.

Supongo que no será muy diferente aplicar el mismo tipo de truco para esas llamadas al sistema. Debe implementarse en C, pero debería tomar mucho menos código y ser más preciso que analizar la salida strace.

+0

De acuerdo. Ahora estoy usando LD_PRELOAD como alternativa, pero esperaba que hubiera algunas soluciones listas para usar. Gracias. –

7

Se podía esperar a que se abran los archivos para que pueda aprender el fd y adjuntar strace después del lanzamiento proceso como este:

strace -p pid traza -e = fichero -e leer = fd

1

Creo sobrecarga open, seek y read es una buena solución. Pero solo para su información, si desea analizar y analizar la salida de la cadena programáticamente, hice algo similar antes y puse mi código en github: https://github.com/johnlcf/Stana/wiki

(Lo hice porque tengo que analizar el resultado directo del programa ejecutado por otros, lo cual no es fácil pedirles que hagan LD_PRELOAD.)

5

systemtap - una especie de reimplantación de DTrace para Linux - podría ser de ayuda aquí.

Al igual que con strace solo tienes el fd, pero con la capacidad de guiones es fácil mantener el nombre del archivo para un fd (a menos que sea con cosas divertidas como dup). Existe el script de ejemplo iotime que illustates.

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

Funciona solo hasta cierto número de archivos porque el mapa hash tiene un tamaño limitado.

0

Probablemente la forma menos fea de hacer esto es usar fanotify. Fanotify es una instalación kernel de Linux que permite ver a bajo costo los eventos del sistema de archivos. No estoy seguro de si se permite el filtrado de PID, pero sí pasa el PID a su programa para que pueda comprobar si es el que usted está interesado en

Aquí es un buen ejemplo de código:. http://bazaar.launchpad.net/~pitti/fatrace/trunk/view/head:/fatrace.c

Sin embargo, parece estar poco documentado en este momento.Todos los documentos que pude encontrar son http://www.spinics.net/lists/linux-man/msg02302.html y http://lkml.indiana.edu/hypermail/linux/kernel/0811.1/01668.html

+0

[Aquí hay un poco más sobre fanotify] (http://stackoverflow.com/questions/1835947/) – Tobu

0

El análisis de utilidades de línea de comandos como strace es engorroso; podría usar ptrace() syscall en su lugar. Vea man ptrace para más detalles.

Cuestiones relacionadas