Межпроцессное взаимодействие (IPC)
Очереди сообщений
Реализованы как специальный файл. В адресном пространстве ядра ведётся таблица всех очередей. Каждое сообщение имеет тип (целое положительное число) и текст.
struct msgbuf {
long mtype; /* тип сообщения (> 0) */
char mtext[MSGMAX]; /* текст (обычно до 2048 байт) */
};
Системные вызовы
int msgget(key_t key, int flag); /* создать/открыть */ int msgsnd(int fd, const void *buf, size_t len, int flag); /* отправить */ ssize_t msgrcv(int fd, void *buf, size_t len, long mtype, int flag); /* получить */ int msgctl(int fd, int cmd, struct msqid_ds *buf); /* управление */
Параметр mtype в msgrcv():
0— принять самое старое сообщение любого типа.> 0— принять сообщение указанного типа.< 0— принять сообщение с типом ≤ |mtype|.
/* Создать очередь с ключом 15 */ int fd = msgget(15, IPC_CREAT | 0644); /* Отправить */ msg.mtype = 1; strcpy(msg.mtext, "Hello"); msgsnd(fd, &msg, strlen(msg.mtext) + 1, 0); /* Получить */ msgrcv(fd, &msg, 2048, 0, 0); /* Удалить */ msgctl(fd, IPC_RMID, NULL);
ipcs -q # показать очереди ipcrm -q <id> # удалить по id ipcrm -Q <key> # удалить по ключу
Семафоры
Переменная с целым неотрицательным значением для синхронизации процессов. В UNIX семафоры организованы в наборы (массивы).
Атрибуты каждого семафора:
semval— текущее значение.sempid— PID процесса, последним изменившего.semncnt— число процессов, ожидающих увеличения.semzcnt— число процессов, ожидающих обнуления.
Системные вызовы
int semget(key_t key, int nsems, int flag); /* создать/открыть набор */ int semop(int fd, struct sembuf *ops, size_t nops); /* операции */ int semctl(int fd, int semnum, int cmd, union semun arg); /* управление */
struct sembuf {
unsigned short sem_num; /* номер семафора */
short sem_op; /* операция: >0 (V), <0 (P), =0 (ждать нуля) */
short sem_flg; /* 0, IPC_NOWAIT, SEM_UNDO */
};
SEM_UNDO — отменить изменения семафора при завершении процесса. Защита от зависания при аварийном завершении.
ipcs -s # показать семафоры ipcrm -s <id> # удалить по id
Разделяемая память
Наиболее быстрый способ IPC. Несколько процессов отображают один сегмент памяти в свои адресные пространства.
Системные вызовы
int shmget(key_t key, size_t size, int flag); /* создать/открыть */ void *shmat(int fd, const void *addr, int flag); /* присоединить */ int shmdt(const void *addr); /* отсоединить */ int shmctl(int fd, int cmd, struct shmid_ds *buf); /* управление */
int fd = shmget(5, 4096, IPC_CREAT | 0644); char *addr = (char *)shmat(fd, NULL, 0); strcpy(addr, "Привет из разделяемой памяти!"); shmdt(addr); shmctl(fd, IPC_RMID, NULL);
Удаление сегмента (
IPC_RMID) происходит только после отсоединения всех процессов. Для синхронизации доступа используют семафоры.
ipcs -m # показать сегменты памяти ipcrm -m <id> # удалить
Сравнение механизмов IPC
| Механизм | Скорость |
|---|