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

ЖАНРЫ

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

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

Шрифт:

В случае успеха системный вызов 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);

 }

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

w - запись в сегмент

r - чтение

d - удаление сегмента

m — изменение прав доступа */

 switch(tolower(argv[1][1])) {

 case 'w':

shm_write(shmid, ptr, argv[2]);

break;

 case 'r':

shm_read(shmid, ptr);

break;

 case 'd':

shm_rm(shmid);

break;

 case 'm':

shm_change_mode(shmid, argv[2]);

break;

 }

}

/*
Функция для записи в сегмент: ей нужно передать

ID сегмента, адрес привязки и записываемую информацию */

shm_write(int shmid, char *ptr, char *info) {

 strcpy(ptr, info);

}

/* Функция чтения информации из сегмента */

shm_read(int shmid, char *ptr) {

 printf("Информация из сегмента: %s\n", ptr);

}

/* Функция удаления сегмента */

shm_rm(int shmid) {

 shmctl(shmid, IPC_RMID, 0);

 printf("Сегмент помечен на удаление\n");

}

/* Функция изменения прав доступа. Ей нужно передать

 идентификатор сегмента и права доступа в виде строки,

 например, "0666" * /

shm_change_mode(int shmid, char *mode) {

 struct shmid_ds mds;

 shmctl(shmid, IPC_STAT, &mds);

 printf("Старые права доступа: %o\n", mds.shm_perm.mode);

 sscanf(mode, "%o", &mds.shm_perm.mode);

 shmctl(shmid, IPC_SET, &mds);

 printf("Новые права доступа: %o\n", mds.shm_perm.mode);

}

Использовать программу нужно так:

./shm_demo -w строка

запись строки в сегмент

./shm_demo -r

чтение строки из сегмента

./shmdemo -m права

изменение прав доступа

./shm_demo -d

удаление сегмента

Выполните команду

$ ./shm_demo -w string

А затем запустите утилиту ipcs. Вы увидите, что наша программа создала разделяемый сегмент памяти:

– ----- Shared Memory Segments ------

key shmid owner perms bytes nattch status

0x44063781 0 root 660 256 0

– ----- Semaphore Arrays ------

key semid owner perns nsems status

– ----- Message Queues ------

key msqid owner perms used-bytes messages

Затем выполните команду:

$ ./shm_demo -r

Вы получите информацию:

Информация из сегмента: string

Попробуем изменить права доступа, а затем просмотреть информацию командой ipcs:

Поделиться с друзьями: