Чтение онлайн

на главную - закладки

Жанры

Linux: Полное руководство

Аллен Питер В.

Шрифт:

♦ ENOMEM — не хватает памяти для создания сегмента.

Приведем пример функции открытия/создания РСП:

int open_shms(key_t key, int size) {

 return (shmget(key, size, IPC_CREAT | 0660 )) == -1));

}

После получения идентификатора РСП мы должны «привязаться» к этому сегменту, то есть разместить сегмент в своем адресном пространстве. Для этого используется системный вызов shmat (shared memory attachment):

int shmat(int shmid, char *shmaddr, int shmflg);

Первый аргумент — это идентификатор РСП, который мы получаем с помощью предыдущего вызова. Второй аргумент — это адрес привязки. Если указать вместо адреса ноль, то ядро само найдет нераспределенную область.

Третий аргумент — это флаги. Обычно используется два флага:

♦ SHM_RND — переданный адрес будет округлен до ближайшей страницы (если вы сами указываете адрес);

♦ SHM_RDONLY — РСП будет доступен только для чтения.

В случае успеха shmat возвращает адрес, по которому сегмент был привязан к процессу, или -1, если произошла ошибка. Переменная errno может принимать всего три значения:

♦ EACCESS — нет доступа;

♦ ENOMEM — не хватает памяти;

♦ EINVAL — ошибка в параметрах, то есть неправильное значение ID или адреса привязки (shmaddr).

Пример привязки:

char *ptr;

prt = shmat(sh_id,0,0);

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

Для снятия привязки используется системный вызов shmdt:

int shmdt(char *shmaddr);

В случае ошибки данный системный вызов возвращает -1. Значение errno только одно: EINVAL, то есть вы неправильно указали адрес привязки. После отвязки значение элемента shm_nattch структуры shmid_ds уменьшается на 1. Если больше нет привязок, то есть shm_nattch = 0, сегмент будет удален ядром.

Для управления РСП используется системный вызов shmctl:

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

Первый аргумент — это идентификатор РСП, второй — команда, а третий — буфер для команд IPC_STAT/IPC_SET. Команд для управления три:

♦ IPC_STAT — сохраняет структуру shmid_ds по адресу buf;

♦ IPC_SET — берет значение элемента ipc_perm структуры shmid_ds и устанавливает его для сегмента. Значение берется из buf;

♦ IPC_RMID — помечает сегмент для удаления, само удаление произойдет, как только последний процесс отвяжется от сегмента. Если сегмент помечен на удаление, ни один процесс не сможет привязаться к сегменту.

В случае успеха системный вызов shmctl возвращает 0 или -1, если произошла ошибка. Переменная errno устанавливается так:

♦ EACCESS — нет прав;

♦ EFAULT — ошибочный адрес buf;

♦ EIDRM — сегмент помечен на удаление;

♦ EINVAL — неправильный идентификатор сегмента.

Вот теперь мы готовы к написанию демонстрационной программы для работы с разделяемыми сегментами памяти.

Листинг 26.6. Демонстрационная программа shm_demo.c

#include <stdio.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

/* размер нашего сегмента - 256 байтов */

#define SIZE 256

int main(int argc, char *argv[]) {

 key_t key; /* ключ */

 int shmid, с; /* идентификатор */

 char *ptr; /* указатель, через который мы будем

работать с сегментом */

 /* Если аргументы не указаны ... */

 if (argc == 1) {

printf("shm_demo usage:\n");

printf("shm_demo -w string записать строку в сегмент\n");

printf("shm_demo -r прочитать инф. из сегмента\n");

printf("shm_demo -d удалить сегмент\n");

printf("shm_demo -m mode изменить права доступа\n");

exit(1);

 }

 /* Генерируем ключ IPC */

 key = ftok(".", 'D');

 /* Пытаемся создать сегмент */

 if ((shmid =

shmget(key, SIZE, IPC_CREAT|IPC_EXCL|0660)) == -1) {

printf("Сегмент существует, подключаемся к нему...\n");

/* Используем shmget без IPC_EXCL */

if ((shmid = shmget(key, SIZE, 0)) == -1) {

printf("Ошибка в shmget\n");

exit(1);

}

 } else {

printf("Создаем новый сегмент\n");

 }

 /* Привязываемся к сегменту */

 if ((ptr = shmat(shmid, 0, 0)) == -1) {

perror("shmat");

exit(1);

 }

 /* Разбираем параметры командной строки:

Поделиться:
Популярные книги

Тринадцатый V

NikL
5. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Тринадцатый V

Точка Бифуркации VI

Смит Дейлор
6. ТБ
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Точка Бифуркации VI

Жена неверного ректора Полицейской академии

Удалова Юлия
Любовные романы:
любовно-фантастические романы
4.25
рейтинг книги
Жена неверного ректора Полицейской академии

Моя простая курортная жизнь

Блум М.
1. Моя простая курортная жизнь
Проза:
современная проза
5.00
рейтинг книги
Моя простая курортная жизнь

Барон переписывает правила

Ренгач Евгений
10. Закон сильного
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Барон переписывает правила

Кодекс Крови. Книга ХIV

Борзых М.
14. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Крови. Книга ХIV

Буря империи

Сай Ярослав
6. Медорфенов
Фантастика:
аниме
фэнтези
фантастика: прочее
эпическая фантастика
5.00
рейтинг книги
Буря империи

Третий Генерал: Том IV

Зот Бакалавр
3. Третий Генерал
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Третий Генерал: Том IV

Законы Рода. Том 2

Андрей Мельник
2. Граф Берестьев
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 2

Бояръ-Аниме. Романов. Том 3

Кощеев Владимир
2. Романов
Фантастика:
фэнтези
альтернативная история
6.57
рейтинг книги
Бояръ-Аниме. Романов. Том 3

Неудержимый. Книга XXXVII

Боярский Андрей
37. Неудержимый
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Неудержимый. Книга XXXVII

Я все еще барон

Дрейк Сириус
4. Дорогой барон!
Фантастика:
боевая фантастика
5.00
рейтинг книги
Я все еще барон

Первый среди равных. Книга II

Бор Жорж
2. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Первый среди равных. Книга II

Гранд империи

Земляной Андрей Борисович
3. Страж
Фантастика:
фэнтези
попаданцы
альтернативная история
5.60
рейтинг книги
Гранд империи