Проект демонстрирует межпроцессное взаимодействие (IPC) с использованием разделяемой памяти System V в Docker-контейнере. В него входят две программы на C:
writer.c
— создаёт сегмент разделяемой памяти, записывает в него "Hello world!" и выводит идентификатор памяти.reader.c
— получает идентификатор памяти из стандартного ввода, считывает из памяти сообщение, выводит его и удаляет сегмент.
Программы запускаются внутри Docker-контейнера, основанного на образе gcc:11.3.0
.
.
├── src/ # Исходные файлы программ
│ ├── writer.c # Запись данных в разделяемую память
│ ├── reader.c # Чтение данных из разделяемой памяти
├── Dockerfile # Настройка Docker-образа
├── build.sh # Скрипт сборки Docker-образа
├── run.sh # Скрипт запуска программ
└── README.md # Документация
- Docker установлен на вашей системе
Запустите build.sh
, чтобы скомпилировать программы и создать образ Docker:
./build.sh
Прим. Docker может требовать root-доступ, в таком случае необходимо собрать образ с помощью команды:
sudo ./build.sh
После выполнения создастся образ с именем shm-example
.
Выполните run.sh
, чтобы запустить программы:
./run.sh
Прим. Docker может требовать root-доступ, в таком случае необходимо запустить программы с помощью команды:
sudo ./run.sh
Скрипт выполняет:
- Запуск контейнера с флагом
--ipc=host
для того, чтобы контейнер мог использовать общую память хоста. - Запуск программы
writer
, которая создает сегмент разделяемой памяти и выводит её идентификатор в стандартный вывод. - Запуск программы
reader
, которая получает идентификатор памяти через стандартный ввод, считывает из сегмента памяти сообщение и выводит его.
-
Процесс записи (
writer.c
):-
shmget()
создает новый сегмент разделяемой памяти.
Аргументы:key_t key
— уникальный ключ для сегмента разделяемой памяти (в данном случае используетсяIPC_PRIVATE
, чтобы создать новый сегмент).size_t size
— размер сегмента разделяемой памяти (в данном случае1000
, что соответствует размеру строки).int shmflg
— флаги для создания сегмента. Мы используемIPC_CREAT | 0666
, что создаёт сегмент с правами на чтение и запись для всех пользователей.
Возвращаемое значение: идентификатор сегмента памяти или
-1
в случае ошибки. -
shmat()
подключает процесс к сегменту разделяемой памяти.
Аргументы:int shmid
— идентификатор сегмента, полученный изshmget()
.const void *shmaddr
— адрес, по которому процесс должен подключить сегмент памяти. В данном случае передаетсяNULL
, и система сама выбирает подходящий адрес.int shmflg
— флаги подключения. Передается0
, что означает стандартный режим.
Возвращаемое значение: указатель на начало сегмента памяти или
-1
в случае ошибки. -
strncpy()
копирует строку"Hello world!"
в память, ограничив её длину до заданного значения (в данном случаеSHM_SIZE
, равное1000
). -
Программа выводит идентификатор сегмента разделяемой памяти с помощью
printf()
. Этот идентификатор будет передан в программу чтения через аргумент командной строки. -
shmdt()
отключает процесс от сегмента разделяемой памяти.
Аргументы:const void *shmaddr
— указатель на сегмент памяти, от которого нужно отключиться.
Возвращаемое значение:
0
в случае успешного отключения,-1
в случае ошибки.
-
-
Процесс чтения (
reader.c
):-
Программа считывает ключ разделяемой памяти из стандартного ввода, используя
scanf()
. -
shmat()
подключает процесс к сегменту разделяемой памяти (была описана выше). -
printf()
выводит данные из разделяемой памяти на экран. -
shmdt()
отключает процесс от сегмента разделяемой памяти (описана выше). -
shmctl()
управляет сегментами разделяемой памяти.
Аргументы:int shmid
— идентификатор сегмента, который нужно удалить.int cmd
— команда управления. В данном случае используетсяIPC_RMID
, чтобы удалить сегмент.struct shmid_ds *buf
— структура для получения информации о сегменте. В данном случае передаетсяNULL
.
Возвращаемое значение:
0
в случае успеха,-1
в случае ошибки.
-