Python's Shared Memory Module: shm



This module provides an object interface to System V shared memory IPC, present in most Unix systems. As you probably know, shared memory is the fastest form of IPC because the data does not need to be copied between clients and servers, and does not involve any I/O operations. The only trick in using shared memory is synchronizing access to a given shared memory region among multiple processes. Most often, semaphores are used to synchronize shared memory access.

The shm module offers two types of objects:

Shared memory objects: they represent shared memory regions (segments) created with the create_memory() function. An existing shared memory segment can be obtained as a Python object with the memory() function. In order to access a shared memory region (read or write data), the shared memory segment must be attached first to the current process address space with the m.attach() method. A shared memory region is marked for deletion with the remove_memory() function and is effectively deleted when all processes detach from it with the m.detach() method.

Semaphore objects: they represent simplified System V semaphores in the sense that every semaphore object is a System V semaphore set reduced to one semaphore. New semaphores are created with create_semaphore(), while existing ones can be obtained with semaphore(). Semaphores are (unconditionaly) deallocated with remove_semaphore().

There is no documentation for the moment (sorry!), but you can refer to (1) the __doc__ strings of all available functions and object methods, and (2) the Unix man pages of ipcs, ipcrm, shmget, shmat, shctl, shmdt, semget, semctl, semop.

Here is the interface provided with the current implementation:


Module interface:

- shm.create_memory(int Key, int Size [,int Perm=0666]) --> object
- shm.create_semaphore(int Key [,int Value=1 [,int Perm=0666]]) --> object
- shm.error
- shm.ftok(string Path, int ProjId) --> int
- shm.getsemid(int Key) --> int
- shm.getshmid(int Key) --> int
- shm.memory(int Shmid) --> object
- shm.memory_haskey(int Key) --> int
- shm.remove_memory(int Shmid) --> None
- shm.remove_semaphore(int Semid) --> None
- shm.semaphore(int Semid) --> object
- shm.semaphore_haskey(int Key) --> int

Memory Objects:

+ Members:

- m.addr	- attachment address in the process address space
- m.attached	- 0|1
- m.cgid	- gid of creator
- m.cpid	- pid of creator
- m.cuid	- uid of creator
- m.gid		- gid of owner
- m.key		- segment key or IPC_PRIVATE (=0)
- m.lpid	- pid of last shmop
- m.nattch	- current # of attached processes
- m.perm	- operation permission
- m.shmid	- shared memory segment id
- m.size	- segment size
- m.uid		- uid of owner

+ Methods:

- m.attach([int Addr=0 [,int How=0]]) --> None
- m.detach() --> None
- m.read(int Nbytes [,int Offset=0]) --> string
- m.setgid(int Gid) --> None
- m.setperm(int Perm) --> None
- m.setuid(int Uid) --> None
- m.write(string Data [,int Offset=0]) --> None

Semaphore Objects:

+ Members:

- s.cgid	- gid of creator
- s.cuid	- uid of creator
- s.gid		- gid of owner
- s.key		- semaphore key or IPC_PRIVATE (=0)
- s.lpid	- pid of last semop
- s.ncnt	- current # of processes waiting for s.val > 0
- s.perm	- operation permission
- s.semid	- semaphore id
- s.uid		- uid of owner
- s.val		- value of the semaphore counter
- s.zcnt	- current # of processes waiting for s.val == 0

+ Methods:

- s.P() --> None		- blocks if s.val == 0; decrements s.val
- s.V() --> None		- increments s.val
- s.Z() --> None		- blocks until s.val == 0
- s.setblocking(0|1) --> None
- s.setgid(int Gid) --> None
- s.setperm(int Perm) --> None
- s.setuid(int Uid) --> None
- s.setundo(0|1) --> None
- s.setval(int Value) --> None

Here is an interactive session between two python interpreters:

(Interpreter 1)
>>> import shm                          # Let's create a shared memory segment
>>> shm.create_memory.__doc__
'create_memory(int Key, int Size [,int Perm=0666]) --> object | except shm.error'
>>> 
>>> m = shm.create_memory(0x100, 1024)  # with key=0x100 and size=1024
>>> m
<detached shared memory object, id=2, size=1024, addr=None>
>>> 
>>> m.attach()                          # We have to attach it in order to read/write from/to it
>>> m
<attached R/W shared memory object, id=2, size=1024, addr=0x30000000>
>>> 
>>> m.write("Python is great!")         # still not convinced?
>>> 

(Interpreter 2)
>>> import shm
>>> shm.memory.__doc__                  # We need to find the segment we've just created
'memory(int Shmid) --> object | except shm.error'
>>> shm.getshmid.__doc__                # We don't know it's id, but we know it's key
'getshmid(int Key) --> int | except KeyError'
>>> 
>>> m = shm.memory(shm.getshmid(0x100)) # got it!
>>> m
<detached shared memory object, id=2, size=1024, addr=None>
>>> 
>>> m.attach()                          # We already know that we have to attach it first
>>> m
<attached R/W shared memory object, id=2, size=1024, addr=0x30000000>
>>>
>>> m.read.__doc__
'read(int Nbytes [,int Offset=0]) --> string | except shm.error'
>>> m.read(20)
'Python is great!\000\000\000\000'      # Indeed...
>>>


Download:

Note: If your system defines union semun in <sys/sem.h> (e.g. true for Linux), compile this module with OPT="... -DHAVE_UNION_SEMUN ..." or uncomment the #define HAVE_UNION_SEMUN in the source.


Vladimir Marangozov <Vladimir.Marangozov@inrialpes.fr>
Last modified: July 17, 1997