0
# Shared Memory
1
2
POSIX named shared memory segments provide high-performance inter-process data sharing through memory mapping. Shared memory segments appear as files in the filesystem and can be memory-mapped for direct access, making them ideal for sharing large amounts of data between processes with minimal overhead.
3
4
## Capabilities
5
6
### Shared Memory Creation and Management
7
8
Create and manage named POSIX shared memory segments with configurable size, permissions, and access modes.
9
10
```python { .api }
11
class SharedMemory:
12
def __init__(self, name, flags=0, mode=0o600, size=0, read_only=False):
13
"""
14
Create or open a named shared memory segment.
15
16
Parameters:
17
- name: str or None. If None, a random name is chosen. If str, should start with '/' (e.g., '/my_shared_memory')
18
- flags: int, creation flags (O_CREAT, O_EXCL, O_CREX, O_TRUNC)
19
- mode: int, permissions (octal, default 0o600)
20
- size: int, size in bytes (0 to use existing size)
21
- read_only: bool, whether to open in read-only mode
22
23
Notes:
24
- If size > 0, segment will be resized using ftruncate() regardless of new/existing status
25
- O_TRUNC can be used to truncate existing segment to zero bytes (not supported on macOS)
26
- On macOS, ftruncate() can only be called once during segment lifetime
27
"""
28
```
29
30
### Resource Management
31
32
Properly close file descriptors and clean up shared memory resources.
33
34
```python { .api }
35
def close_fd(self):
36
"""
37
Close the file descriptor associated with this SharedMemory object.
38
39
Equivalent to calling os.close() on the fd attribute. Must be called explicitly -
40
file descriptor is not closed automatically on garbage collection.
41
42
Note: Closing the file descriptor has no effect on any mmap objects created from it.
43
"""
44
45
def fileno(self):
46
"""
47
Returns the file descriptor for the shared memory segment.
48
49
Returns:
50
int: File descriptor (same as the fd property)
51
52
This method allows SharedMemory objects to be used with functions
53
that expect file-like objects with a fileno() method.
54
"""
55
56
def unlink(self):
57
"""
58
Mark the shared memory segment for destruction.
59
60
The segment is destroyed once all processes have unmapped it. Per POSIX spec,
61
after unlinking, subsequent shm_open() calls with the same name will either
62
fail (if O_CREAT not set) or create a new segment (if O_CREAT set).
63
64
Note: Implementation behavior may vary across operating systems.
65
"""
66
67
def __str__(self):
68
"""
69
String representation of the shared memory segment.
70
71
Returns:
72
str: Human-readable representation including name and size
73
"""
74
75
def __repr__(self):
76
"""
77
Detailed string representation for debugging.
78
79
Returns:
80
str: Technical representation with class name and key attributes
81
"""
82
```
83
84
### Shared Memory Properties
85
86
Access shared memory metadata and file descriptor.
87
88
```python { .api }
89
@property
90
def name(self):
91
"""
92
The name provided in the constructor.
93
94
Returns:
95
str: Shared memory segment name
96
"""
97
98
@property
99
def mode(self):
100
"""
101
The mode (permissions) provided in the constructor.
102
103
Returns:
104
int: File mode/permissions (e.g., 0o600)
105
"""
106
107
@property
108
def fd(self):
109
"""
110
File descriptor representing the shared memory segment.
111
112
Returns:
113
int: File descriptor that can be used with os.read(), os.write(), mmap.mmap(), etc.
114
"""
115
116
@property
117
def size(self):
118
"""
119
Current size of the shared memory segment in bytes.
120
121
Returns:
122
int: Size in bytes
123
"""
124
```
125
126
### Module Function
127
128
Convenience function for unlinking shared memory segments by name.
129
130
```python { .api }
131
def unlink_shared_memory(name):
132
"""
133
Convenience function to unlink a shared memory segment by name.
134
135
Parameters:
136
- name: str, shared memory segment name (e.g., '/my_shared_memory')
137
138
Equivalent to opening the segment and calling unlink(), but more convenient
139
when you only need to remove an existing segment.
140
"""
141
```
142
143
## Usage Examples
144
145
### Basic Shared Memory Usage
146
147
```python
148
import posix_ipc
149
import os
150
151
# Create a 1KB shared memory segment
152
shm = posix_ipc.SharedMemory('/my_shm', posix_ipc.O_CREAT, size=1024)
153
154
# Write data using file descriptor
155
data = b'Hello, shared memory!'
156
os.write(shm.fd, data)
157
158
# Read data back
159
os.lseek(shm.fd, 0, os.SEEK_SET) # Reset to beginning
160
read_data = os.read(shm.fd, len(data))
161
print(f"Read: {read_data.decode()}")
162
163
# Clean up
164
shm.close_fd()
165
shm.unlink()
166
```
167
168
### Memory Mapping for High Performance
169
170
```python
171
import posix_ipc
172
import mmap
173
import struct
174
175
# Create shared memory segment
176
shm = posix_ipc.SharedMemory('/mapped_shm', posix_ipc.O_CREAT, size=4096)
177
178
# Memory map the segment
179
mm = mmap.mmap(shm.fd, shm.size)
180
181
# Write structured data directly to memory
182
mm[0:4] = struct.pack('i', 42) # Write integer at offset 0
183
mm[4:12] = b'Hello!!!!' # Write string at offset 4
184
185
# Read structured data
186
value = struct.unpack('i', mm[0:4])[0] # Read integer
187
text = mm[4:12].rstrip(b'!') # Read string
188
189
print(f"Value: {value}, Text: {text.decode()}")
190
191
# Clean up
192
mm.close()
193
shm.close_fd()
194
shm.unlink()
195
```
196
197
### Multi-Process Data Sharing
198
199
```python
200
import posix_ipc
201
import mmap
202
import os
203
import time
204
205
# Producer process
206
def producer():
207
# Create shared memory
208
shm = posix_ipc.SharedMemory('/data_shm', posix_ipc.O_CREAT, size=1024)
209
mm = mmap.mmap(shm.fd, shm.size)
210
211
# Write data periodically
212
for i in range(10):
213
data = f"Message {i}".encode()
214
mm[0:len(data)] = data
215
mm[len(data)] = 0 # Null terminator
216
time.sleep(1)
217
218
mm.close()
219
shm.close_fd()
220
# Don't unlink - consumer will do it
221
222
# Consumer process
223
def consumer():
224
# Open existing shared memory
225
try:
226
shm = posix_ipc.SharedMemory('/data_shm')
227
mm = mmap.mmap(shm.fd, shm.size)
228
229
# Read data
230
for i in range(10):
231
# Find null terminator
232
null_pos = mm.find(b'\x00')
233
if null_pos > 0:
234
data = mm[0:null_pos].decode()
235
print(f"Consumer read: {data}")
236
time.sleep(1)
237
238
mm.close()
239
shm.close_fd()
240
shm.unlink() # Consumer cleans up
241
242
except posix_ipc.ExistentialError:
243
print("Shared memory not found")
244
```
245
246
### Using with Different Size Operations
247
248
```python
249
import posix_ipc
250
import os
251
252
# Create segment with initial size
253
shm = posix_ipc.SharedMemory('/resizable_shm', posix_ipc.O_CREAT, size=512)
254
print(f"Initial size: {shm.size}")
255
256
# Resize using os.ftruncate() (alternative to size parameter)
257
os.ftruncate(shm.fd, 2048)
258
print(f"Resized to: {shm.size}")
259
260
# Note: On macOS, you can only call ftruncate() once per segment lifetime
261
262
shm.close_fd()
263
shm.unlink()
264
```
265
266
### Read-Only Access
267
268
```python
269
import posix_ipc
270
import mmap
271
272
# First process creates and writes data
273
shm_writer = posix_ipc.SharedMemory('/readonly_shm', posix_ipc.O_CREAT, size=1024)
274
mm_writer = mmap.mmap(shm_writer.fd, shm_writer.size)
275
mm_writer[0:12] = b'Hello World!'
276
mm_writer.close()
277
shm_writer.close_fd()
278
279
# Second process opens read-only
280
shm_reader = posix_ipc.SharedMemory('/readonly_shm', read_only=True)
281
mm_reader = mmap.mmap(shm_reader.fd, shm_reader.size, access=mmap.ACCESS_READ)
282
283
# Read data
284
data = mm_reader[0:12]
285
print(f"Read: {data.decode()}")
286
287
# Clean up
288
mm_reader.close()
289
shm_reader.close_fd()
290
posix_ipc.unlink_shared_memory('/readonly_shm')
291
```
292
293
### Error Handling
294
295
```python
296
import posix_ipc
297
298
try:
299
# Try to open non-existent shared memory
300
shm = posix_ipc.SharedMemory('/nonexistent')
301
except posix_ipc.ExistentialError:
302
print("Shared memory does not exist")
303
304
try:
305
# Try to create exclusive segment that already exists
306
shm1 = posix_ipc.SharedMemory('/existing', posix_ipc.O_CREAT)
307
shm2 = posix_ipc.SharedMemory('/existing', posix_ipc.O_CREX)
308
except posix_ipc.ExistentialError:
309
print("Shared memory already exists")
310
shm1.close_fd()
311
shm1.unlink()
312
313
try:
314
# Try to access segment without proper permissions
315
shm = posix_ipc.SharedMemory('/restricted', posix_ipc.O_CREAT, mode=0o000)
316
# Another process without permissions would get PermissionsError
317
except posix_ipc.PermissionsError:
318
print("Permission denied")
319
```