Вопрос проверяет знание механизмов межпроцессного взаимодействия (IPC) в Linux, необходимых для разработки многопроцессных приложений и понимания системного программирования.
Межпроцессное взаимодействие (IPC) необходимо, когда процессы должны обмениваться данными или синхронизировать свою работу. Linux предоставляет несколько механизмов, каждый из которых имеет свои особенности и области применения.
Каналы — это простейший способ связи, который работает только между родственными процессами (например, родитель и потомок). Данные передаются в виде потока байтов, однонаправленно.
#include <unistd.h>
int pipe(int fd[2]); // fd[0] - чтение, fd[1] - запись
// Пример: родитель пишет, потомок читает
pid_t pid = fork();
if (pid == 0) {
close(fd[1]);
read(fd[0], buffer, size);
} else {
close(fd[0]);
write(fd[1], data, size);
}FIFO позволяют общаться процессам, не связанным родством. Они создаются как файлы в файловой системе и работают по принципу «первым вошёл — первым вышел».
mkfifo("/tmp/myfifo", 0666);
// Процесс-писатель
int fd = open("/tmp/myfifo", O_WRONLY);
write(fd, "hello", 6);
// Процесс-читатель
int fd = open("/tmp/myfifo", O_RDONLY);
read(fd, buffer, 6);Самый быстрый способ IPC, так как данные не копируются между процессами. Процессы отображают одну и ту же область памяти в своё адресное пространство. Требуется синхронизация (например, семафоры).
#include <sys/shm.h>
int shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0666);
void *data = shmat(shmid, NULL, 0);
// Процессы могут читать и писать в data
shmdt(data);Позволяют отправлять структурированные сообщения с типом. Процессы могут выбирать сообщения по типу, что удобно для асинхронной связи.
#include <sys/msg.h>
int msqid = msgget(IPC_PRIVATE, IPC_CREAT | 0666);
struct msgbuf { long mtype; char mtext[100]; };
msgsnd(msqid, &msg, sizeof(msg.mtext), 0);
msgrcv(msqid, &msg, sizeof(msg.mtext), 1, 0);Универсальный механизм, работающий как локально (Unix domain sockets), так и по сети. Поддерживают двустороннюю связь и сложные протоколы.
// Unix domain socket (локально)
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
struct sockaddr_un addr = {.sun_family = AF_UNIX, .sun_path = "/tmp/socket"};
bind(sock, (struct sockaddr*)&addr, sizeof(addr));
listen(sock, 5);
int client = accept(sock, NULL, NULL);Используются для уведомления процессов о событиях (например, SIGINT для прерывания). Ограничены — передают только номер сигнала, не данные.
kill(pid, SIGUSR1); // отправка сигнала
signal(SIGUSR1, handler); // обработкаВывод: Выбор механизма IPC зависит от задачи: для простой однонаправленной связи между родственными процессами подходят каналы, для быстрого обмена большими объёмами данных — разделяемая память, для сетевого взаимодействия — сокеты. Очереди сообщений удобны при асинхронной передаче структурированных данных, а сигналы — для простых уведомлений.