Ответ
В Linux для создания сегмента разделяемой памяти (shared memory) используется системный вызов shmget().
Сигнатура:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
Параметры:
key(key_t): Ключ для идентификации сегмента. Можно использоватьIPC_PRIVATEдля создания нового уникального сегмента, или сгенерировать ключ с помощьюftok().size(size_t): Размер создаваемого сегмента в байтах.shmflg(int): Флаги, определяющие права доступа (например,0666) и режим создания. Часто используются комбинации:IPC_CREAT: Создать сегмент, если он не существует.IPC_EXCL: В комбинации сIPC_CREATгарантирует, что вызов завершится ошибкой, если сегмент с таким ключом уже существует.
Возвращаемое значение: При успехе — целочисленный идентификатор сегмента разделяемой памяти (shmid). При ошибке — -1, и переменная errno устанавливается соответствующим образом.
Пример создания сегмента:
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
// Создаём сегмент размером 1024 байта с правами чтения и записи для всех.
// IPC_CREAT | 0666 означает: создать, если не существует, и дать права rw-rw-rw-.
int shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget failed");
exit(EXIT_FAILURE);
}
printf("Shared memory segment created with ID: %dn", shmid);
// ... далее сегмент можно присоединить с помощью shmat()
return 0;
}
После создания сегмента процессы используют shmat() для присоединения (получения указателя на эту память) и shmdt() для отсоединения. Управление жизненным циклом (удаление) осуществляется через shmctl() с командой IPC_RMID.
Ответ 18+ 🔞
Слушай, ну вот объясняю, как в Линуксе память общую между процессами сделать. Ситуация, блядь, классическая: один процесс насчитал что-то, а другому надо эти цифры прочитать, а копировать через файлы или сокеты — овердохуища возни. Вот для этого и придумали shmget(), чтобы кусок памяти на всех один был.
Представь, что это типа общежитие для данных. Чтобы его построить, нужен вызов shmget(). Выглядит он так, ёпта:
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
Разберём по косточкам, а то нихуя не понятно.
-
key— это как номер квартиры в том самом общежитии. Все процессы, которые хотят в одну и ту же память, должны знать этот самый ключ. Можно взять специальное значениеIPC_PRIVATE— тогда система сама выделит новый уникальный сегмент, но его ID потом надо будет как-то детям-процессам передать. А можно сгенерировать ключ функциейftok()от пути к какому-нибудь файлу, чтобы все независимо могли его вычислить. Хуй с горы, в общем. -
size— это, блядь, размер твоей "комнаты" в байтах. Сколько памяти тебе надо, столько и проси. Только не жадничай, а то оперативка кончится. -
shmflg— вот тут самое интересное. Это флаги, комбинация из двух вещей:- Права доступа. Как в
chmod—0666значит, что все могут и читать, и писать.0644— только хозяин пишет, остальные читают. Ставь, что душе угодно. - Режим создания. Самые важные —
IPC_CREATиIPC_EXCL.IPC_CREAT— значит "создай сегмент, если его ещё нет". Если уже есть — просто верни его ID.IPC_EXCL— эту штуку используют вместе сIPC_CREAT. И тогда смысл такой: "Создай новый сегмент, но если он УЖЕ существует — нахуй, выдай ошибку". Это чтобы два раза не создать одно и то же, понимаешь? Защита от дурака, а дурак часто — это ты сам.
- Права доступа. Как в
Возвращает эта функция, ядрёна вошь, целое число — идентификатор сегмента (shmid). Это как пропуск в это самое общежитие. Если вернула -1 — всё, пизда, что-то пошло не так. Смотри в errno, что за косяк.
Ну а теперь, чтобы не быть пустым трёпом, вот тебе реальный код, как это делается:
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
// Создаём сегмент размером 1024 байта с правами чтения и записи для всех.
// IPC_CREAT | 0666 означает: создать, если не существует, и дать права rw-rw-rw-.
int shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget failed");
exit(EXIT_FAILURE);
}
printf("Shared memory segment created with ID: %dn", shmid);
// ... далее сегмент можно присоединить с помощью shmat()
return 0;
}
Смотри, что тут происходит: мы говорим системе — "дай нам новый уникальный сегмент (IPC_PRIVATE) на 1024 байта, создай его если надо (IPC_CREAT), и пусть все в него пишут и читают (0666)". Если получили -1 — ругаемся через perror и валим нахуй с ошибкой. Если всё ок — радостно печатаем ID.
И главное, запомни: shmget() — это только создание/получение сегмента. Чтобы им пользоваться, его надо присоединить к адресному пространству процесса функцией shmat() (она вернёт указатель, с которым можно работать как с обычной памятью). Закончил работать — отсоедини через shmdt(). А чтобы совсем удалить этот сегмент из системы (чтобы память не текла), нужна команда shmctl() с флагом IPC_RMID. Но это уже совсем другая история, блядь.