¿Hay alguna forma más rápida de verificar si un archivo está en uso?

8

Estoy buscando una función de línea de comando o función c que me permita saber si un archivo está abierto / en uso por algo.

lsofy fuserdigo esto, pero proporcionan mucha otra información que resulta en tomar hasta 300 ms en algunas situaciones (como cuando uso este código en MAC OS X, me estoy dedicando a Linux y OS X) (tengo una ventana solución que tarda 5 ms, así que estoy tratando de encontrar algo en Unix que también sea muy rápido y solo devuelva verdadero o falso si el archivo está en uso)

Noitidart
fuente

Respuestas:

9

Si está usando esto como un candado, no funcionará como ninguno lsofni fuserevitará las condiciones de carrera.

El proceso básico que lo lsofhace es rastrear todos los procesos en /proc/*/fsbusca de descriptores de archivos abiertos. Esto tomará tiempo sin importar lo que hagas.

Puede hacerlo usted mismo, pero no es probable que sea más rápido, ya que debe verificar cada proceso abierto en el sistema.

Si lo que está haciendo es crucial para el tiempo, descubra otra forma de hacerlo.

  • Si controla el archivo a través de un programa que escribió; usa un archivo de bloqueo.
  • Si está ejecutando algún comando que opera en el archivo, mire y vea qué documentación ofrece ese comando / programa y vea si no puede crear un archivo de bloqueo. De lo contrario, vea si no puede hacer un archivo con su PID dentro. Luego puede mirar /proc/<PID>/fspara ver si su archivo está actualmente abierto o no. Mirar solo un proceso de descriptores de archivos abiertos será mucho más rápido que mapearlos en todos.
  • De lo contrario, para ayudarlo, necesitaré más información sobre lo que está haciendo.

Dio más información en un comentario que desea determinar si Firefox se está ejecutando en un sistema determinado. La mejor manera de hacerlo es buscar los archivos de bloqueo de Firefox. Estos se almacenan en ubicaciones predeterminadas especificadas en la wiki de Mozilla.

Por ejemplo, en Linux, haga que su programa haga lo siguiente:

  • Abre el ~/.mozilla/firefox/directorio.
  • Lista todos los directorios, filtrando los directorios que terminan en .default. (Creo que todos los perfiles terminan con .default, si no solo rastrear en cada directorio).
  • En cada directorio anterior, busque la existencia de un archivo llamado locko .parentlock. Si ve uno o ambos archivos, Firefox está abierto.

Este algoritmo debería ejecutarse más rápido que lo que hace en Windows actualmente.

nixeagle
fuente
Excelente respuesta gracias. ¿Hay alguna forma de decirle a lsof y fuser que solo verifiquen la carpeta pid si es firefox? Eso haría saltar todos los contenidos de las carpetas excepto las carpetas de Firefox (tengo 3 casos separados de modo que los medios sólo chequea 3 carpetas ¿verdad?)
Noitidart
El archivo está bloqueado, pero no puedo entender cómo probar si está bloqueado. Se está abriendo con éxito para lectura / escritura. Es tan raro. Intenté fcntl desde c pero siempre regresa -1 :(
Noitidart
3
@Noitidart ¿Cuál es su problema real que está tratando de resolver? Para buscar los descriptores de archivos abiertos de cualquier proceso, debe conocer su PID. Esto cambia para cada instancia del programa. Una forma sencilla de obtenerlo "manualmente" es con ps aux firefox. Tome esos PID y búsquelos en el /proc/sistema de archivos.
nixeagle
Ah, gracias, es una buena idea ps aux firefox. Bueno, mi situación exacta es: tengo la ruta a un archivo. Está bloqueado si Firefox se está ejecutando. Quiero ver si está bloqueado o no para saber si Firefox se está ejecutando.
Noitidart
1
@Noitidart He editado mi comentario para incluir cómo detectar Firefox mirando los archivos de bloqueo. Puede repetir este proceso en todos los sistemas.
nixeagle
1

TL; DR

En uno de sus comentarios , declara:

Bueno, mi situación exacta es: tengo la ruta a un archivo. Está bloqueado si Firefox se está ejecutando. Quiero ver si está bloqueado o no para saber si Firefox se está ejecutando.

Su pregunta original sobre los archivos de bloqueo parece el camino largo cuando hay formas más fáciles de averiguar si Firefox se está ejecutando para un usuario determinado y de inspeccionar su estado de proceso.

Examen del estado del proceso

Una forma más sensata de encontrar el PID de un proceso dado es usar pgrep del paquete procps . Por ejemplo:

$ pgrep -u $LOGNAME firefox
5671

Luego puede inspeccionar el estado del PID con ps :

$ ps 5671
  PID TTY      STAT   TIME COMMAND
 5671 ?        Sl   105:47 /usr/lib/firefox/firefox

o simplemente obtener las banderas estatales sin ninguna otra migaja:

$ ps -ho stat $(pgrep -u $LOGNAME firefox)
Sl

En mi sistema, la línea anterior de arriba consistentemente solo tarda 1.4 milisegundos en completarse. Su experiencia puede ser diferente.

Procesar códigos de estado

La sección CÓDIGOS DE ESTADO DEL PROCESO de ps (1) detalla lo que significan los diversos indicadores de estado. En Ubuntu 14.04, la página del manual dice:

PROCESS STATE CODES
       Here are the different values that the s, stat and state output
       specifiers (header "STAT" or "S") will display to describe the state of
       a process:

               D    uninterruptible sleep (usually IO)
               R    running or runnable (on run queue)
               S    interruptible sleep (waiting for an event to complete)
               T    stopped, either by a job control signal or because it is
                    being traced
               W    paging (not valid since the 2.6.xx kernel)
               X    dead (should never be seen)
               Z    defunct ("zombie") process, terminated but not reaped by
                    its parent

       For BSD formats and when the stat keyword is used, additional
       characters may be displayed:

               <    high-priority (not nice to other users)
               N    low-priority (nice to other users)
               L    has pages locked into memory (for real-time and custom IO)
               s    is a session leader
               l    is multi-threaded (using CLONE_THREAD, like NPTL pthreads
                    do)
               +    is in the foreground process group
CodeGnome
fuente
1
el problema es que necesita saber en qué sesión se encuentra actualmente Firefox. En Linux, simplemente busca ~/.mozilla/firefox/*/lock. Luego puede identificar la sesión mirando el nombre del directorio principal de cada archivo de bloqueo. En otras plataformas esto no funciona. Nuestro chat trata más sobre cómo hacerlo funcionar en Mac (lo cual es un poco irrelevante para ubuntu, pero ahí lo tienes). Para ser justos, realmente debería actualizar la pregunta para que sea más específica. : P
nixeagle