русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

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


Дата добавления: 2014-11-28; просмотров: 1812; Нарушение авторских прав


SHMGET

shmget - присваивает идентификатор разделяемому сегменту памяти

 

СИНТАКСИС

#include <sys/ipc.h>

#include <sys/shm.h>

int shmget(key_t key, int size, int shmflg);

 

ОПИСАНИЕ

shmget() возвращает идентификатор разделяемому сегменту памяти, соответствующий значению аргумента key. Создается новый разделяемый сегмент памяти с размером, округленным в большую сторону от величины size( кратный PAGE_SIZE), если значение key равно IPC_PRIVATE или если значение key не равно IPC_PRIVATE и нет идентификатора, соответствующего key; причем, выражение shmflg&IPC_CREAT истинно. Поле

shmflg состоит из:

IPC_CREAT - служит для создания нового сегмента. Если этого флага нет, то функция shmget() будет искать сегмент, соответствующий ключу key; затем она проверит, имеет ли пользователь права на получение shmid, соответствующего этому сегменту, и удостоверится, не помечен ли сегмент на удаление.

IPC_EXCL - используется совместно с IPC_CREAT для того, чтобы не создавать существующий сегмент заново.

mode_flags (младшие 9 битов) - указывают на права хозяина, группы и др. В данный момент права системой не используются.

Если создается новый сегмент, то права доступа копируются из shmflg в shm_perm, являющийся членом структуры shmid_ds, которая определяет сегмент. Структура shmid_ds выглядит так:

 

struct shmid_ds {

struct ipc_perm shm_perm; /* права функции */

int shm_segsz; /* размер сегмента (в байтах) */

time_t shm_atime; /* время последнего присоединения*/

time_t shm_dtime; /* время последнего отсоединения */

time_t shm_ctime; /* время последнего изменения */

unsigned short shm_cpid; /* идентификатор процесса создателя*/

unsigned short shm_lpid; /* идентификатор последнего пользователя*/



short shm_nattch; /* количество присоединений */

};

 

Так же, во время создания сегмента, системный вызов инициализирует структуру сегмента разделяемой памяти shmid_ds следующим образом: устанавливаемые значения

shm_perm.cuid и shm_perm.uid становятся равными значению идентификатора эффективного пользователя вызывающего процесса.

shm_perm.cgid и shm_perm.gid устанавливаются равными идентификатору эффективной группы пользователей вызывающего процесса.

Младшим 9-и битам shm_perm.mode присваивается значение младших 9-и битов shmflg.

shm_segsz присваивается значение size. Устанавливаемое значение shm_lpid, shm_nattch, shm_atime и shm_dtime становится равным нулю.

shm_ctime устанавливается на текущее время.

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

 

СИСТЕМНЫЕ ВЫЗОВЫ

fork() - После выполнения команды fork() дочерний процесс наследует подключаемые к нему разделяемые сегменты памяти.

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

exit() - По завершении exit() все подключенные разделяемые сегменты памяти отключаются (но не удаляются).

 

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При удачном завершении вызова возвращается идентификатор сегмента shmid, и -1 при ошибке.

 

SHMCTL

shmctl - производит операции по управлению разделяемыми сегментами памяти

 

СИНТАКСИС

#include <sys/ipc.h>

#include <sys/shm.h>

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

 

ОПИСАНИЕ

shmctl() позволяет пользователю получать информацию о разделяемых сегментах памяти, устанавливать владельца, группу разделяемого сегмента, права на него; эта функция может также удалить сегмент. Информация о сегменте, которая находится в shmid, возвращается в структуру shmid_ds :

 

Значения аргумента cmds могут быть следующими:

 

IPC_STAT - используется для копирования информации о сегменте в буфер buf. Пользователь должен иметь права на чтение сегмента read.

IPC_SET - используется для применения пользовательских изменений к содержимому полей uid, gid или mode в структуре shm_perms. Используются только младшие 9 битов mode. Поле shm_ctime тоже обновляется. Пользователь должен быть владельцем, создателем или суперпользователем процесса.

IPC_RMID - используется для пометки сегмента как удаленного. Сегмент будет удален после отключения (например, когда поле shm_nattch ассоциированной структуры shmid_ds равно нулю). Пользователь должен быть владельцем, создателем или суперпользователем процесса.

 

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

Вдобавок, суперпользователь может запретить или разрешить подкачку разделяемого сегмента памяти при помощи следующих команд cmds (это применимо только для Linux):

 

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

SHM_UNLOCK - разрешить подкачку сегмента.

Вызовы IPC_INFO, SHM_STAT и SHM_INFO используются программой ipcs() для получения информации о выделенных ресурсах. В будущем они могут быть по необходимости изменены или вынесены в файловую систему proc.

 

СИСТЕМНЫЕ ВЫЗОВЫ

fork() - После команды fork() дочерние процессы наследуют сегменты разделяемой памяти.

exec() - После команды exec () все подключенные сегменты разделяемой памяти отключаются (но не удаляются).

exit() - Если выполнена команда exit(), все сегменты разделяемой памяти отключаются (но не удаляются).

 

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При удачном выполнении возвращается 0, а при ошибке -1.

 

SHMOP

shmop - работает с разделяемой памятью

 

СИНТАКСИС

#include <sys/types.h>

#include <sys/shm.h>

void *shmat(int shmid, const void *shmaddr, int shmflg);

int shmdt(const void *shmaddr);

 

ОПИСАНИЕ

Функция shmat подстыковывает сегмент разделяемой памяти shmid к адресному пространству вызывающего процесса. Адрес подстыковываемого сегмента определяется shmaddr с помощью одного из перечисленных ниже критериев:

· Если shmaddr равен NULL, то система выбирает для подстыкованного сегмента подходящий (неиспользованный) адрес.

· Если shmaddr не равен NULL, а в поле shmflg включен флаг SHM_RND, то подстыковка производится по адресу shmaddr, округленному вниз до ближайшего кратного SHMLBA. В противном случае shmaddr должен быть округленным до размера страницы адресом, к которому производится подстыковка.

· Если в поле shmflg включен флаг SHM_RDONLY, то подстыковываемый сегмент будет доступен только для чтения, и вызывающий процесс должен иметь права на чтение этого сегмента. Иначе, сегмент будет доступен для чтения и записи, и у процесса должны быть соответствующие права. Сегментов "только-запись" не существует.

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

При удачном выполнении системный вызов shmat обновляет содержимое структуры shmid_ds, связанной с разделяемым сегментом памяти, следующим образом:

  • shm_atime устанавливается в текущее время.
  • shm_lpid устанавливается в идентификатор вызывающего процесса.
  • shm_nattch увеличивается на 1.

 

Заметьте, что пристыковка производится и в том случае, если пристыковываемый сегмент помечен на удаление.

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

При удачном выполнении системный вызов shmdt обновляет содержимое структуры shmid_ds, связанной с разделяемым сегментом памяти, следующим образом:

  • shm_dtime устанавливается в текущее время.
  • shm_lpid устанавливается в идентификатор вызывающего процесса.
  • shm_nattch уменьшается на 1. Если это значение становится равным 0, а сегмент помечен на удаление, то сугмент удаляется из памяти. Эта функция освобождает занятую ранее этим сегментом область памяти в адресном пространстве процесса.

 

СИСТЕМНЫЕ ВЫЗОВЫ

fork() - При исполнении fork() дочернии процесс наследует пристыкованные сегменты разделяемой памяти.

exec() - При исполнении exec() все подстыкованные сегменты памяти отстыковываются от процесса.

exit () - При исполнении exit() все подстыкованные сегменты памяти отстыковываются от процесса.

 

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При ошибке обе функции возвращают -1, а переменной errno присваивается номер ошибки. При удачном выполнении shmat возвращает адрес подстыкованного сегмента памяти, а shmdt возвращает 0.

 

Пример программы

 

Программа client читает данные (числа) из файла и записывает их в область разделяемой памяти. Программа server читает данные из разделяемой памяти, суммирует их и записывает результат в файл. Внимание! Для получения ключа необходимо создать файл с именем “sem” в каталоге программы.

 

 

Текст программы

 

Файл server.c

 

#include"shmem.h" //описание структуры семафоров и памяти

 

FILE *fd; //дескриптор файла результатов

int i; //счетчик

float sum=0; //сумма чисел

mem_sh *memptr; //указатель на структуру разделяемой памяти

key_t key; //ключ доступа к семафору

int shmid; //дескриптор разделяемой памяти

int semid; //дескриптор семафора

 

int main(void)

{

printf("\n\t\t.:SERVER:.\n");

key=ftok("sem",'A'); //получаем ключ для сервера

shmid=shmget(key,100,IPC_CREAT|PERM); //получаем деск. разделяемой памяти

memptr=(mem_sh*) shmat (shmid,0,0);//присоединяем память к памяти сервера

semid=semget(key,1,IPC_CREAT|PERM); //получаем деск. семафоров сервера

semop(semid,&mem_trylock[0],1); //пытаемся опустить семафор памяти

//(пытаемся заблокировать доступ к памяти)

if ((fd=fopen("result.txt","w"))==NULL) //создаём файл результатов

{perror("\n\tError (server - fopen)\n");return 0;}

printf("\n\tOpen(Create) result file\n");

for(i=0;i<6;i++) sum=sum+memptr->cord[i]; //читаем содержимое памяти и

printf("\tResult = %f\n",sum); //накапливаем сумму

if ((fprintf(fd,"Sum=%f \n",sum))<=0) //записываем сумму в файл

{perror("\n\tError (server - fprintf)\n");return 0;}

printf("\tResult has writen to file\n");

fclose(fd); //закрываем дескриптор файла результатов

shmdt(memptr); //отсоединяем разделяемую память от сервера

shmctl(shmid,IPC_RMID,0); //удаляем дескриптор памяти

semctl(semid,0,IPC_RMID); //удаляем дескриптор семафоров сервера

return 0;

}

 

Файл client.c

 

#include"shmem.h" //описание структуры семафоров и памяти

FILE *fd; //дескриптор файла данных

int i; //счётчик

float mas[6]; //массив из шести вещественных чисел

mem_sh *memptr; //указатель на область разделяемой памяти

key_t key; //ключ семафора

int shmid; //дескриптор разделяемой памяти

int semid; //дескриптор семафора

 

int main(void)

{

printf("\n\t\t.:CLIENT:.\n");

key=ftok("sem",'A'); //получаем ключ

shmid=shmget(key,100,PERM); //получаем дескриптор разделяемой памяти

memptr=(mem_sh*) shmat (shmid,0,0);//присоединяем память к памяти клиента

semid=semget(key,1,PERM); //получаем деск. набора семафоров для сервера

if ((fd=fopen("data.txt","r+"))==NULL) //открываем файл для чтения

{perror("\n\tError (client - fopen)\n");return 0;}

printf("\n\tOpen data file\n");

while ((fscanf(fd,"%f %f %f %f %f %f ",&mas[0],&mas[1], //читаем числа

&mas[2],&mas[3],&mas[4],&mas[5]))!=EOF) //пока не конец файла

{

printf("\tContent of data file:\n");

printf("\t%f %f %f %f %f %f\n",mas[0],mas[1],mas[2],mas[3],mas[4],mas[5]);

for (i=0;i<6;i++) memptr->cord[i]=mas[i]; //заносим числа в массив

} //структуры которая находится в разделяемой памяти

semop(semid,&mem_unlock[0],1); //разблокируем память для сервера

shmdt(memptr); //отсоединяем разделяемую память от памяти клиента

shmctl(shmid,IPC_RMID,0); //закрываем дескриптор разделяемой памяти

semctl(semid,0,IPC_RMID); //закрываем дескриптор семафора

fclose(fd); //закрываем дескриптор файла данных

return 0;

}

 

Файл shmem.h

 

#include <stdio.h>

#include <sys/types.h>

#include <sys/sem.h>

#include <sys/shm.h>

#include <sys/ipc.h>

 

#define MAXBUF 80 //максимальный размер буфера

#define PERM 0777 //права доступа к памяти

 

typedef struct mem_msg //структура разделяемой памяти

{

float cord[6]; //массив из шести вещественных чисел

}mem_sh; //тип структуры

 

static struct sembuf mem_trylock[1]={0,-1,0}; //блокировка памяти

static struct sembuf mem_unlock[1]={0,1,0}; //разблокировка памяти

 

 



<== предыдущая лекция | следующая лекция ==>
Семафоры | ЛАБОРАТОРНАЯ РАБОТА 9


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.009 сек.