Ответ
Разделяемая память (Shared Memory) — это один из самых быстрых механизмов межпроцессного взаимодействия (IPC) в Linux. Он позволяет нескольким независимым процессам получить доступ к одной и той же области оперативной памяти для чтения и записи данных. Это достигается за счет отображения одного физического сегмента памяти в виртуальное адресное пространство каждого из участвующих процессов.
Преимущества:
- Скорость: Данные не копируются между процессами (как в pipes или message queues), а напрямую читаются/пишутся в общую область. Это критически важно для высокопроизводительных систем (СУБД, кэши вроде Redis/Memcached, научные вычисления).
- Гибкость: Можно передавать данные любого типа и сложной структуры.
Недостатки и сложности:
- Синхронизация: Поскольку процессы работают с одной областью памяти, необходимы механизмы синхронизации (например, семафоры SysV или POSIX, мьютексы в разделяемой памяти) для предотвращения состояний гонки (race conditions) и повреждения данных.
- Управление жизненным циклом: Необходимо явно создавать, подключать и удалять сегменты разделяемой памяти.
Основные API:
- System V Shared Memory (
shmget,shmat,shmdt): Классический, но несколько устаревший интерфейс. - POSIX Shared Memory (
shm_open,mmap): Более современный и гибкий подход, интегрирующийся с файловой системой (/dev/shm).
Практический пример на C с использованием SysV IPC и семафоров для синхронизации:
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <stdio.h>
#include <string.h>
// Простая структура для общих данных
struct shared_data {
int counter;
char message[256];
};
int main() {
key_t key = ftok("/tmp", 'R');
// 1. Создаем сегмент разделяемой памяти
int shmid = shmget(key, sizeof(struct shared_data), IPC_CREAT | 0666);
// 2. Присоединяем сегмент к адресному пространству процесса
struct shared_data *data = (struct shared_data*) shmat(shmid, NULL, 0);
// 3. Работаем с данными (в реальности здесь нужна синхронизация!)
data->counter++;
strcpy(data->message, "Hello from Process A");
printf("Counter: %d, Message: %sn", data->counter, data->message);
// 4. Отсоединяем сегмент
shmdt(data);
// (В одном из процессов нужно будет вызвать shmctl(shmid, IPC_RMID, NULL) для удаления)
return 0;
}
В современных системах часто используются более высокоуровневые абстракции, построенные поверх разделяемой памяти, такие как memory-mapped files с помощью mmap() или специализированные библиотеки.