Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Межпроцессное взаимодействие (IPC)
Межпроцессное взаимодействие (Inter-Process Communication, IPC) — это механизм, который позволяет двум или более независимым процессам обмениваться данными и синхронизировать свои действия. В операционной системе каждый процесс имеет собственное изолированное адресное пространство памяти, поэтому для коммуникации между ними необходимо использовать специальные механизмы, предоставляемые ОС.
Основные механизмы IPC
В Python и операционных системах существует несколько основных подходов к IPC:
1. Трубы (Pipes)
Трубы — это самый простой механизм, позволяющий одному процессу писать данные, а другому их читать. Существуют безымянные трубы (используются между родительским и дочерним процессами) и именованные трубы (FIFO).
import subprocess
import os
# Безымянная труба
process1 = subprocess.Popen(
["cat", "/etc/passwd"],
stdout=subprocess.PIPE
)
process2 = subprocess.Popen(
["wc", "-l"],
stdin=process1.stdout,
stdout=subprocess.PIPE
)
output, _ = process2.communicate()
print(f"Lines: {output.decode().strip()}")
# Именованная труба (FIFO)
os.mkfifo("/tmp/my_fifo")
writer_process = subprocess.Popen(["python", "writer.py"])
reader_process = subprocess.Popen(["python", "reader.py"])
2. Сокеты (Sockets)
Сокеты — это более универсальный механизм, позволяющий процессам взаимодействовать как в пределах одной машины (Unix domain sockets), так и по сети (TCP/UDP).
import socket
import os
# Unix domain socket
socket_path = "/tmp/python_socket"
# Сервер
server_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
if os.path.exists(socket_path):
os.remove(socket_path)
server_socket.bind(socket_path)
server_socket.listen(1)
while True:
connection, _ = server_socket.accept()
try:
data = connection.recv(1024)
print(f"Received: {data.decode()}")
connection.sendall(b"OK")
finally:
connection.close()
# Клиент
client_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
client_socket.connect(socket_path)
client_socket.sendall(b"Hello")
response = client_socket.recv(1024)
print(f"Response: {response.decode()}")
client_socket.close()
3. Очереди сообщений (Message Queues)
Очереди сообщений позволяют асинхронно обмениваться сообщениями между процессами. Python предоставляет модуль queue для работы с очередями в пределах одного приложения.
import multiprocessing
from queue import Queue
def producer(queue):
for i in range(5):
queue.put(f"Message {i}")
print(f"Sent: Message {i}")
def consumer(queue):
while True:
message = queue.get()
if message is None:
break
print(f"Received: {message}")
queue.task_done()
if __name__ == "__main__":
queue = multiprocessing.Queue()
p1 = multiprocessing.Process(target=producer, args=(queue,))
p2 = multiprocessing.Process(target=consumer, args=(queue,))
p1.start()
p2.start()
p1.join()
queue.put(None) # Сигнал завершения
p2.join()
4. Разделяемая память (Shared Memory)
Разделяемая память позволяет нескольким процессам обращаться к одной области памяти. Python предоставляет модуль multiprocessing.shared_memory.
import multiprocessing
from multiprocessing import shared_memory
import numpy as np
def writer():
shm = shared_memory.SharedMemory(name="my_shm", create=True, size=100)
buffer = np.ndarray((10,), dtype=np.int32, buffer=shm.buf)
buffer[:] = np.arange(10)
print(f"Wrote: {buffer}")
shm.close()
def reader():
import time
time.sleep(1) # Дождёмся создания памяти
shm = shared_memory.SharedMemory(name="my_shm")
buffer = np.ndarray((10,), dtype=np.int32, buffer=shm.buf)
print(f"Read: {buffer}")
shm.close()
shm.unlink() # Удаляем
if __name__ == "__main__":
p1 = multiprocessing.Process(target=writer)
p2 = multiprocessing.Process(target=reader)
p1.start()
p2.start()
p1.join()
p2.join()
5. Сигналы (Signals)
Сигналы — это простой механизм асинхронной коммуникации для уведомления процесса о возникновении события.
import signal
import os
import time
def signal_handler(signum, frame):
print(f"Received signal {signum}")
exit(0)
signal.signal(signal.SIGUSR1, signal_handler)
print(f"PID: {os.getpid()}")
while True:
print("Waiting...")
time.sleep(1)
# В другом терминале: kill -SIGUSR1 <PID>
Сравнение механизмов
| Механизм | Скорость | Простота | Надёжность | Синхронизация |
|---|---|---|---|---|
| Трубы | Высокая | Высокая | Хорошая | +/- |
| Сокеты | Средняя | Средняя | Отличная | +/- |
| Очереди | Средняя | Средняя | Отличная | +++ |
| Разделяемая память | Очень высокая | Низкая | +/- | - |
| Сигналы | Низкая | Средняя | +/- | ++ |
Практические рекомендации
- Используйте очереди для асинхронной передачи сообщений между процессами
- Сокеты подходят для сетевого взаимодействия и сложных протоколов
- Разделяемую память применяйте только для обмена большими объёмами данных, требующих синхронизации
- Сигналы используйте для простых уведомлений о событиях
- Трубы идеальны для конвейеризации команд в shell-скриптах
Выбор механизма зависит от требований вашего приложения: скорости, надёжности, простоты реализации и типа данных, которые нужно передавать.