Поскольку доступ к объектам разделяемой памяти может быть получен через дескриптор, для установки размера объекта используется функция ftruncate, а информация о существующем объекте (биты разрешений, идентификаторы пользователя и группы, размер) возвращается функцией fstat.
В главах, рассказывающих об очередях сообщений и семафорах Posix, мы приводили примеры их реализации через отображение в память (разделы 5.8 и 10.15). Для разделяемой памяти Posix мы этого делать не будем, поскольку реализация тривиальна. Если мы готовы использовать отображение в файл (что и сделано в Solaris и Digital Unix), shm_open реализуется через open, a shm_unlink — через unlink.
Упражнения
1. Измените программы из листингов 12.6 и 12.7 таким образом, чтобы они работали с разделяемой памятью Posix, а не с отображаемым в память файлом. Убедитесь, что результаты будут такими же, как и для отображаемого в память файла.
2. В циклах for в листингах 13.3 и 13.4 используется команда *ptr++ для перебора элементов массива. Не лучше ли было бы использовать ptr[i]?
ГЛАВА 14
Разделяемая память System V
14.1. Введение
Основные принципы разделяемой памяти System V совпадают с концепцией разделяемой памяти Posix. Вместо вызовов shm_open и mmap в этой системе используются вызовы shmget и shmat.
Для каждого сегмента разделяемой памяти ядро хранит нижеследующую структуру, определенную в заголовочном файле
struct shmid_ds {
struct ipc_perm shm_perm; /* структура разрешений */
size_t shm_segsz; /* размер сегмента */
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; /* время последнего изменения данной структуры */
};
Структура ipc_perm была описана в разделе 3.3; она содержит разрешения доступа к сегменту разделяемой памяти.
14.2. Функция shmget
С помощью функции shmget можно создать новый сегмент разделяемой памяти или подключиться к существующему:
#include
int shmget(key_t
/* Возвращает идентификатор разделяемой памяти в случае успешного завершения. –1 –в случае ошибки */
Возвращаемое целочисленное значение называется идентификатором разделяемой памяти. Он используется с тремя другими функциями shmXXX.
Аргумент
Аргумент
Флаг
Новый сегмент инициализируется нулями.
Обратите внимание, что функция shmget создает или открывает сегмент разделяемой памяти, но не дает вызвавшему процессу доступа к нему. Для подключения сегмента памяти предназначена функция shmat, описанная в следующем разделе.
14.3. Функция shmat
После создания или открытия сегмента разделяемой памяти вызовом shmget его нужно подключить к адресному пространству процесса вызовом shmat:
#include
void *shmat(int
/* Возвращает начальный адрес полученной области в случае успешного завершения. –1 –в случае ошибки */
Аргумент
■ если аргумент