2011-08-03 12 views
39

Czy istnieje prosty sposób na posiadanie ogólnosystemowego muteksu w Pythonie na Linuksie? Przez "systemowy" rozumiem, że muteks będzie używany przez grupę Python procesów; jest to przeciwieństwo tradycyjnego muteksu, używanego przez grupę wątków w tym samym procesie.Systemowy muteks w Pythonie na Linuksie

EDYCJA: Nie jestem pewien, czy pakiet Pythona multiprocessing jest tym, czego potrzebuję. Na przykład, można wykonać następujące czynności w dwóch różnych tłumaczy:

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

Kiedy wykonać te polecenia jednocześnie w dwóch oddzielnych tłumaczy, chcę jeden z nich do powieszenia. Zamiast tego nie wisi; wydaje się, że nie nabywają tego samego muteksu.

+0

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

+0

masz znalazłeś dobre rozwiązanie? – redice

Odpowiedz

22

"Tradycyjna" odpowiedź Unix polega na użyciu blokad plików. Możesz użyć lockf(3), aby zablokować sekcje pliku, aby inne procesy nie mogły go edytować; bardzo częstym nadużyciem jest użycie tego jako muteksu między procesami. Odpowiednikiem Pythona jest fcntl.lockf.

Tradycyjnie piszesz PID procesu blokowania do pliku blokady, tak że zakleszczenia z powodu procesów umierających podczas trzymania blokady są możliwe do zidentyfikowania i naprawienia.

To daje ci to, czego chcesz, ponieważ twoja blokada znajduje się w globalnej przestrzeni nazw (systemie plików) i jest dostępna dla wszystkich procesów. Takie podejście ma również zalety, że programy inne niż Python mogą uczestniczyć w twoim blokowaniu. Minusem jest to, że potrzebujesz miejsca na plik blokady; również niektóre systemy plików faktycznie nie blokują się poprawnie, więc istnieje ryzyko, że po cichu nie uda się uzyskać wykluczenia. Wygrywasz, tracisz.

+1

Logicznym miejscem dla pliku blokady jest '/ var/lock' - jednak jeśli będzie duża liczba operacji blokujących, sugeruję'/tmp', ponieważ nie wszystkie systemy mają '/ var/lock' w' tmpfs' ramdysk. – Kimvais

+0

Nie wszystkie systemy mają/tmp w ramdysku tmpfs; moja instalacja OS X wydaje się nie. Mimo to, dobre punkty. – zmccord

+0

pytał o _linux_ i większość (jeśli nie wszystkie) z głównych współczesnych dystrybucji linuksowych ma/tmp w/tmpfs - żaden nie ma/var/lock domyślnie IIRC. – Kimvais

10

Standard POSIX określa między-procesowe semafory, które mogą być używane do tego celu. http://linux.die.net/man/7/sem_overview

Moduł multiprocessing w języku Python jest zbudowany na tym interfejsie API i innych. W szczególności, multiprocessing.Lock zapewnia proces krzyżowy "mutex". http://docs.python.org/library/multiprocessing.html#synchronization-between-processes

EDIT odpowiedzieć na pytanie, pod redakcją:

W swoim dowodzie koncepcji każdy proces konstruowania Lock(). Więc masz dwa oddzielne zamki. Dlatego żaden proces nie czeka. Będziesz musiał udostępniać tę samą blokadę między procesami. Sekcja I powiązana z dokumentacją multiprocessing wyjaśnia, jak to zrobić.

+0

Dzięki, ale "wieloprocesowość" nie wydaje się być tym, czego potrzebuję; zobacz edytowane pytanie. – emchristiansen

+0

Edytowanie mojej odpowiedzi. – wberry

+15

Sekcja, z którą się łączysz, pokazuje, jak proces główny może zaatakować 10 procesów, przekazując obiekt blokady do każdego z nich. Mój przypadek użycia jest inny, ponieważ nie ma głównego procesu spawnego podprocesów. W moim przypadku każdy proces jest wywoływany całkowicie niezależnie, ale muszą one nadal koordynować. – emchristiansen

0

W przypadku ogólnosystemowego muteksu, który umożliwia synchronizację całkowicie oddzielnych procesów (tj. ZAWIERA procesy Linux, które NIE należą do tego samego drzewa procesów), po prostu użyj fcntl.flock. Przypuszczam, że użycie pliku pamięci w folderze Linux/run/shm może sprawić, że będzie działać szybciej.

Zobacz więcej here.

0

Spróbuj ilock Biblioteka:

from ilock import ILock 

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