2011-08-03 9 views
39

¿Hay alguna manera fácil de tener un mutex en todo el sistema en Python en Linux? Por "todo el sistema", quiero decir que el mutex será utilizado por un grupo de Python procesos; esto está en contraste con un mutex tradicional, que es utilizado por un grupo de hilos dentro del mismo proceso.Mutex en todo el sistema en Python en Linux

EDITAR: No estoy seguro de que el paquete multiprocessing de Python sea lo que necesito. Por ejemplo, puedo ejecutar el siguiente en dos diferentes intérpretes:

from multiprocessing import Lock 
L = Lock() 
L.acquire() 

Cuando ejecuto estos comandos simultáneamente en dos intérpretes independientes, quiero uno de ellos para pasar el rato. En cambio, ninguno se cuelga; parece que no están adquiriendo el mismo mutex.

+0

http://stackoverflow.com/questions/5756813/simple-but-fast-ipc-method-for-a-python-and-c-application – Anycorn

+0

usted tiene encontró una buena solución? – redice

Respuesta

22

La respuesta de Unix "tradicional" es utilizar bloqueos de archivos. Puede usar lockf(3) para bloquear secciones de un archivo para que otros procesos no puedan editarlo; un abuso muy común es utilizar esto como un mutex entre procesos. El equivalente de Python es fcntl.lockf.

Tradicionalmente se escribe el PID del proceso de bloqueo en el archivo de bloqueo, por lo que los bloqueos debido a procesos que mueren mientras se mantiene el bloqueo son identificables y corregibles.

Esto le proporciona lo que desea, ya que su bloqueo se encuentra en un espacio de nombre global (el sistema de archivos) y accesible para todos los procesos. Este enfoque también tiene la ventaja de que los programas que no son de Python pueden participar en su bloqueo. La desventaja es que necesita un lugar para vivir este archivo de bloqueo; Además, algunos sistemas de archivos en realidad no se bloquean correctamente, por lo que existe el riesgo de que silenciosamente no logre la exclusión. A veces se gana, se pierde algo.

+1

El lugar lógico para el archivo de bloqueo es '/ var/lock'; sin embargo, si va a haber un gran número de operaciones de bloqueo, sugiero'/tmp' ya que no todos los sistemas tienen '/ var/lock' en' tmpfs' ramdisk. – Kimvais

+0

No todos los sistemas tienen/tmp en tmpfs ramdisk tampoco; mi instalación de OS X no parece. Todos los puntos son buenos, sin embargo. – zmccord

+0

preguntaba por _linux_ y la mayoría (si no todas) de las principales distribuciones modernas de Linux tienen/tmp in/tmpfs - ninguna tiene/var/lock por defecto IIRC. – Kimvais

10

El estándar POSIX especifica los semáforos entre procesos que se pueden utilizar para este fin. http://linux.die.net/man/7/sem_overview

El módulo multiprocessing en Python se basa en esta API y en otras. En particular, multiprocessing.Lock proporciona un "mutex" de proceso cruzado. http://docs.python.org/library/multiprocessing.html#synchronization-between-processes

EDITAR para responder a la pregunta editado:

En su prueba de concepto cada proceso está construyendo una Lock(). Entonces tienes dos cerraduras separadas. Es por eso que ninguno de los procesos espera. Deberá compartir el mismo bloqueo entre procesos. La sección a la que se vinculó en la documentación multiprocessing explica cómo hacerlo.

+0

Gracias, pero el "multiprocesamiento" no parece ser lo que necesito; ver la pregunta editada. – emchristiansen

+0

Editando mi respuesta. – wberry

+15

La sección a la que se ha vinculado parece mostrar cómo un proceso maestro puede generar 10 procesos, pasando un objeto de bloqueo a cada uno que crea. Mi caso de uso es diferente, ya que no hay procesos maestros que generen subprocesos. En mi caso, cada proceso se invoca de manera completamente independiente, pero aún así deben coordinarse. – emchristiansen

0

Para un mutex en todo el sistema que permite la sincronización de procesos absolutamente independientes (es decir, para INCLUIR procesos Linux que NO pertenecen al mismo árbol de procesos), simplemente use fcntl.flock. Supongo que el uso de un archivo de memoria en la carpeta Linux '/ run/shm puede hacer que funcione más rápido.

Ver más here.

0

Trate ilock biblioteca:

from ilock import ILock 

with ILock('Unique lock name'): 
    # The code should be run as a system-wide single instance 
    ... 
Cuestiones relacionadas