Разделяемая память System V

Содержание

Слайд 2

Введение

Разделяемая память является наиболее быстрым средством межпроцессного взаимодействия. После отображения области памяти

Введение Разделяемая память является наиболее быстрым средством межпроцессного взаимодействия. После отображения области
в адресное пространство процессов, совместно ее использующих, для передачи данных между процессами больше не требуется участие ядра. Обычно, однако, требуется некоторая форма синхронизации процессов, помещающих данные в разделяемую память и считывающих ее оттуда.
Рассмотрим по шагам работу программы копирования файла типа клиент-сервер, которую мы использовали в качестве примера для иллюстрации различных способов передачи сообщений.

Слайд 3

Введение

Сервер считывает данные из входного файла. Данные из файла считываются ядром в

Введение Сервер считывает данные из входного файла. Данные из файла считываются ядром
свою память, а затем копируются из ядра в память процесса.
Сервер составляет сообщение из этих данных и отправляет его, используя именованный или неименованный канал или очередь сообщений. Эти формы IPC обычно требуют копирования данных из процесса в ядро.
Клиент считывает данные из канала IPC, что обычно требует их копирования из ядра в пространство процесса.
Наконец, данные копируются из буфера клиента (второй аргумент вызова write) в выходной файл.

Слайд 4

Введение

Видно, что для копирования файла обычно требуются четыре операции копирования данных. Эти

Введение Видно, что для копирования файла обычно требуются четыре операции копирования данных.
операции копирования осуществляются между процессами и ядром и являются дорогостоящими операциями (более дорогостоящей, чем копирование данных внутри ядра или внутри одного процесса). На рис. 1 изображено перемещение данных между клиентом и сервером через ядро.

Слайд 5

Введение

Недостатком этих форм IPC — именованных и неименованных каналов — яв­ляется то,

Введение Недостатком этих форм IPC — именованных и неименованных каналов — яв­ляется
что для передачи между процессами информация должна пройти через ядро. Разделяемая память дает возможность обойти этот недостаток, поскольку ее использование позволяет двум процессам обмениваться данными через общий участок памяти. Процессы, разумеется, должны синхронизировать и координировать свои действия. Одновременное использование участка памяти во многом аналогично совместному доступу к файлу, например к файлу с последовательным номером.

Слайд 6

Введение

Теперь информация передается между клиентом и сервером в такой последовательности:
сервер получает доступ

Введение Теперь информация передается между клиентом и сервером в такой последовательности: сервер
к объекту разделяемой памяти, используя для синхронизации семафор (например);
сервер считывает данные из файла в разделяемую память. Второй аргумент вызова read (адрес буфера) указывает на объект разделяемой памяти;
после завершения операции считывания клиент уведомляется сервером с помощью семафора;
клиент записывает данные из объекта разделяемой памяти в выходной файл.
Этот сценарий иллюстрирует рис. 2.

Слайд 7

Введение

Из рисунка видно, что копирование данных происходит лишь дважды: из входного файла

Введение Из рисунка видно, что копирование данных происходит лишь дважды: из входного
в разделяемую память и из разделяемой памяти в выходной файл. Два прямоугольника штриховыми линиями подчеркивают, что разделяемая память принадлежит как адресному пространству клиента, так и адресному пространству сервера.

Слайд 8

Введение

Основные принципы разделяемой памяти System V совпадают с концепцией разделяемой памяти Posix.

Введение Основные принципы разделяемой памяти System V совпадают с концепцией разделяемой памяти
Вместо вызовов shm_open и imap в этой системе использу­ются вызовы shmget и shmat.
Для каждого сегмента разделяемой памяти ядро хранит нижеследующую структуру shimd_ds, определенную в заголовочном файле :
Структура ipc_perm содержит разрешения доступа к сегменту разделяемой памяти.

Слайд 9

Введение

struct shimd_ds {
struct ipc_perm shm_perm; /* структура разрешений */
size_t shm_segsz; /* размер

Введение struct shimd_ds { struct ipc_perm shm_perm; /* структура разрешений */ size_t
сегмента */
pid_t shm_lpid; /* идентификатор процесса, выполнившего последнюю операцию*/
pid_t shm_cpid; /*идентификатор процесса-создателя*/
shmatt_t shm_nattch; /*текущее количество подключений*/
shmat_t shm_cnattch; /* количество подключений in-core */
time_t shm_atime; /* время последнего подключения */
time_t shm_dtime; /* время последнего отключения */
time_t shm_ctime; /*время последнего изменения данной структуры */
};

Слайд 10

Функция shmget

С помощью функции shmget можно создать новый сегмент разделяемой памяти

Функция shmget С помощью функции shmget можно создать новый сегмент разделяемой памяти
или подключиться к существующему:
#include
int shmget(key_t key, size_t size, int oflag);
/* Возвращает идентификатор разделяемой памяти в случае успешного завершения, -1 в случае ошибки */
Возвращаемое целочисленное значение называется идентификатором разделяемой памяти. Он используется с тремя другими функциями shmXXX.
Аргумент key может содержать значение, возвращаемое функцией ftok, или константу IPC_PRIVATE.

Слайд 11

Функция shmget

Аргумент size указывает размер сегмента в байтах. При создании нового сег­мента

Функция shmget Аргумент size указывает размер сегмента в байтах. При создании нового
разделяемой памяти нужно указать ненулевой размер. Если производится обращение к существующему сегменту, аргумент size должен быть нулевым.
Флаг oflag представляет собой комбинацию флагов доступа на чтение и за­пись. К ним могут быть добавлены с помощью логического сложения флаги IPC_CREAT или IPC_CREAT | IPC_EXCL. Новый сегмент инициализируется нулями.
Функция shmget создает или открывает сегмент разделяемой памяти, но не дает вызвавшему процессу доступа к нему. Для подключения сегмента памяти предназначена функция shmat, описанная далее.

Слайд 12

Функция shmat

После создания или открытия сегмента разделяемой памяти вызовом shmget его

Функция shmat После создания или открытия сегмента разделяемой памяти вызовом shmget его
нужно подключить к адресному пространству процесса вызовом shmat:
#include
void *shmat(int shmid, const void *shmaddr, int flag);
/* Возвращает начальный адрес полученной области в случае успешного завершения. -1 -в случае ошибки */
Аргумент shmid — это идентификатор разделяемой памяти, возвращенный shmget. Функция shmat возвращает адрес начала области разделяемой памяти в адресном пространстве вызвавшего процесса.

Слайд 13

Функция shmat

Правила, по которым формируется этот адрес, таковы:
если аргумент shmaddr представляет собой

Функция shmat Правила, по которым формируется этот адрес, таковы: если аргумент shmaddr
нулевой указатель, система сама выбирает начальный адрес для вызвавшего процесса. Это рекомендуемый (и обеспечивающий наилучшую совместимость) метод;
если shmaddr отличен от нуля, возвращаемый адрес зависит от того, был ли указан флаг SHM_RND (в аргументе flag);
если флаг SHM_RND не указан, разделяемая память подключается непосред­ственно с адреса, указанного аргументом shmaddr ;
если флаг SHM_RND указан, сегмент разделяемой памяти подключается с адреса, указанного аргументом shmaddr, округленного вниз до кратного кон­станте SHMLBA. Аббревиатура LBA означает lower boundary address — нижний граничный адрес.

Слайд 14

Функция shmat

По умолчанию сегмент подключается для чтения и записи, если процесс обадает

Функция shmat По умолчанию сегмент подключается для чтения и записи, если процесс
соответствующими разрешениями. В аргументе flag можно указать константу SHM_RDONLY, которая позволит установить доступ только на чтение.

Слайд 15

Функция shmdt

После завершения работы с сегментом разделяемой памяти его следует отключить

Функция shmdt После завершения работы с сегментом разделяемой памяти его следует отключить
вызовом shmdt:
#include
int shmdt(const void *shmaddr);
/* Возвращает 0 в случае успешного завершения, -1 - в случае ошибки */
При завершении работы процесса все сегменты, которые не были отключены им явно, отключаются автоматически.
Обратите внимание, что эта функция не удаляет сегмент разделяемой памяти. Удаление осуществляется функцией shmctl с командой IPC_RMID.

Слайд 16

Функция shmctl

Функция shmctl позволяет выполнять различные операции с сегментом разделяемой памяти:
#include

Функция shmctl Функция shmctl позволяет выполнять различные операции с сегментом разделяемой памяти:

int shmctl(int shmid, int cmd, struct shmid_ds *buff);
/* Возвращает О в случае успешного завершения, -1 в случае ошибки */

Слайд 17

Функция shmctl

Команд (значений аргумента cmd) может быть три:
IPC_RMID — удаление сегмента разделяемой

Функция shmctl Команд (значений аргумента cmd) может быть три: IPC_RMID — удаление
памяти с идентификатором shmid из системы;
IPC_SET — установка значений полей структуры shmid_ds для сегмента разделяемой памяти равными значениям соответствующих полей структуры, на которую указывает аргумент buff: shm_perm.uid, shm_perm.gid, shm_perm.mode. Значение поля shm_ctime устанавливается равным текущему системному времени;
IPC_STAT — возвращает вызывающему процессу (через аргумент buff) текущее значение структуры shmid_ds для указанного сегмента разделяемой памяти.

Слайд 18

Простые программы

Приведём несколько примеров простых программ, иллюстрирующих работу с разделяемой памятью

Простые программы Приведём несколько примеров простых программ, иллюстрирующих работу с разделяемой памятью
System V.
Программа shmget, текст которой приведен в листинге 1, создает сегмент разделяемой памяти, принимая из командной строки полное имя и длину сегмента.

Слайд 19

Простые программы

Вызов shmget создает сегмент разделяемой памяти указанного размера. Полное имя, передаваемое

Простые программы Вызов shmget создает сегмент разделяемой памяти указанного размера. Полное имя,
в качестве аргумента командной строки, преобразуется в ключ IPC System V вызовом ftok. Если указан параметр -е, наличие существующего сегмента с тем же именем приведет к возвращению ошибки. Если мы знаем, что сегмент уже существует, в командной строке должна быть указана нулевая длина.
Вызов shmat подключает сегмент к адресному пространству процесса. После этого программа завершает работу. Разделяемая память System V обладает по меньшей мере живучестью ядра, поэтому сегмент разделяемой памяти при этом не удаляется.

Слайд 20

Простые программы

В листинге 2 приведен текст тривиальной программы shmrmid, которая вызывает shmctl

Простые программы В листинге 2 приведен текст тривиальной программы shmrmid, которая вызывает
с командой IPC_RMID для удаления сегмента разделяемой памяти из системы.
В листинге 3 приведен текст программы shmwrite, которая заполняет сегмент разделяемой памяти последовательностью значений 0,1,2,…,254,255,0,1…
10-12 Сегмент разделяемой памяти открывается вызовом shmget и подключается вызовом shmat. Его размер может быть получен вызовом shmctl с командой IPC_STAT.
13-15 В разделяемую память записывается последовательность значений.

Слайд 21

Простые программы

Программа shmread, текст которой приведен в листинге 4, проверяет последо­вательность значений,

Простые программы Программа shmread, текст которой приведен в листинге 4, проверяет последо­вательность
записанную в разделяемую память программой shmwrite.
10-12 Открываем и подключаем сегмент разделяемой памяти. Его размер может быть получен вызовом shmctl с командой IPC_STAT.
13-15 Проверяется последовательность, записанная программой shmwrite.

Слайд 22

Простые программы

Создадим сегмент разделяемой памяти длиной 1234 байта в системе ASPlinux 9.0.

Простые программы Создадим сегмент разделяемой памяти длиной 1234 байта в системе ASPlinux
Для идентификации сегмента используем полное имя нашего исполняемого файла shmget. Это имя будет передано функции ftok. Имя исполняемого файла сервера часто используется в качестве уникального идентификатора для данного приложения:
[root@gun_linux_vm]# ./shmget shmget 1234

Слайд 23

Простые программы

[root@gun_linux_vm]# ipcs –m
Программу ipcs мы запускаем для того, чтобы убедиться, что

Простые программы [root@gun_linux_vm]# ipcs –m Программу ipcs мы запускаем для того, чтобы
сегмент разделяемой памяти действительно был создан и не был удален по завершении программы shmcreate. Количество подключений (хранящееся в поле shm_nattch структуры shmid_ds) равно нулю, как мы и предполагали.

Слайд 24

Простые программы

Теперь запустим программу shmwrite, чтобы заполнить содержимое разделяемой памяти последовательностью значений.

Простые программы Теперь запустим программу shmwrite, чтобы заполнить содержимое разделяемой памяти последовательностью
Затем проверим содержимое сегмента разделяемой памяти программой shmread и удалим этот сегмент:
[root@gun_linux_vm]# ./shmwrite shmget
[root@gun_linux_vm]# ./shmread shmget
[root@gun_linux_vm]# ./shmrmid shmget
[root@gun_linux_vm]# ipcs –m
Мы используем программу ipcs, чтобы убедиться, что сегмент разделяемой памяти действительно был удален.

Слайд 25

Ограничения, накладываемые на разделяемую память

На разделяемую память System V накладываются определенные

Ограничения, накладываемые на разделяемую память На разделяемую память System V накладываются определенные
ограничения точно так же, как и на семафоры и очереди сообщений System V. В табл. 1 приведены значения этих ограничений для разных реализаций. В первом столбце приведены традиционные для System V имена переменных ядра, в которых хранятся эти ограничения.

Слайд 26

Ограничения, накладываемые на разделяемую память

Ограничения, накладываемые на разделяемую память
Имя файла: Разделяемая-память-System-V.pptx
Количество просмотров: 46
Количество скачиваний: 3