Материал: Sb97308

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

освободить именованный семафор; задержать на время;

}

}

основная программа()

{

создать (или открыть, если существует) именованный семафор; создать (или открыть, если существует) файл; создать поток из функции потока; ждать нажатия клавиши; установить флаг завершения потока; ждать завершения потока; закрыть файл; закрыть именованный семафор;

удалить именованный семафор;

}

Вопросы для самопроверки

1.Какие программные интерфейсы для именованных семафоров существуют?

2.В чем отличие именованных семафоров от неименованных семафоров?

3.Дайте сравнительную характеристику программных интерфейсов семафоров.

4.Как реализовать определенную очередность записи данных в файл с помощью именованного семафора (например, первый процесс всегда первым начинает запись в файл)?

5.Опишите действия, которые выполняются над именованным семафором при вызове операций sem_wait() и sem_post().

6.Какими операциями с именованным семафором можно проверить занятость ресурса без блокирования процесса?

7.Какими операциями с именованным семафором можно проверить занятость ресурса с определенной периодичностью?

16

5. ВЗАИМОДЕЙСТВИЕ ПРОЦЕССОВ ЧЕРЕЗ РАЗДЕЛЯЕМУЮ ПАМЯТЬ

Цель работы – знакомство с механизмом обмена данными между процессами – разделяемой памятью – и с системными вызовами, обеспечивающими создание разделяемой памяти, отображение ее на локальную память, передачу данных, чтение данных, закрытие и удаление разделяемой памяти.

Общие сведения

Участок разделяемой памяти создается вызовом

int shm_open(const char *name, int oflag, mode_t mode),

где name – имя участка разделяемой памяти; oflag – флаги, определяющие тип создаваемого участка разделяемой памяти; mode – права доступа к участку разделяемой памяти.

Размер участка разделяемой памяти устанавливается вызовом int ftruncate(int fd, off_t length),

где fd – дескриптор разделяемой памяти, полученный как результат вызова функции shm_open(); length – требуемый размер разделяемой памяти.

Отображение разделяемой памяти на локальный адрес создается вызовом

void *mmap(void *addr, size_t length,

int prot, int flags, int fd,

off_t offset),

где addr – начальный адрес отображения; length – размер отображения; prot – параметр, определяющий права чтения/записи отображения; flags – параметр, определяющий правила видимости отображения процессами; fd – дескриптор разделяемой памяти; offset – смещение на участке разделяемой памяти относительно начального адреса.

Удаление отображения разделяемой памяти на локальный адрес производится вызовом

int munmap(void *addr, size_t length),

где addr – локальный адрес отображения; length – размер отображения. Закрытие участка разделяемой памяти производится вызовом

17

int close(int fd),

где fd – дескриптор разделяемой памяти.

Для удаления участка разделяемой памяти используется вызов int shm_unlink(const char *name),

где name – имя участка разделяемой памяти.

Указания к выполнению работы

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

Шаблон программы 1:

объявить флаг завершения потока; объявить идентификатор семафора записи; объявить идентификатор семафора чтения;

объявить идентификатор разделяемой памяти; объявить локальный адрес; функция потока()

{

объявить переменную; пока (флаг завершения потока не установлен)

{

присвоить переменной случайное значение; вывести значение переменной на экран;

скопировать значение переменной в локальный адрес; освободить семафор записи; ждать на семафоре чтения; задержать на время;

}

}

основная программа()

{

объявить идентификатор потока; создать (или открыть, если существует) разделяемую память;

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

18

создать (или открыть, если существует) семафор записи; создать (или открыть, если существует) семафор чтения; создать поток из функции потока; ждать нажатия клавиши; установить флаг завершения потока; ждать завершения потока; закрыть семафор чтения; удалить семафор чтения; закрыть семафор записи; удалить семафор записи;

закрыть отображение разделяемой памяти на локальный адрес; удалить разделяемую память;

}

Шаблон программы 2:

объявить флаг завершения потока; объявить идентификатор семафора записи; объявить идентификатор семафора чтения;

объявить идентификатор разделяемой памяти; объявить локальный адрес; функция потока()

{

объявить переменную; пока (флаг завершения потока не установлен)

{

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

}

}

основная программа()

{

объявить идентификатор потока; создать (или открыть, если существует) разделяемую память;

изменить размер разделяемой памяти на требуемый размер;

19

отобразить разделяемую память на локальный адрес; создать (или открыть, если существует) семафор записи; создать (или открыть, если существует) семафор чтения; создать поток из функции потока; ждать нажатия клавиши; установить флаг завершения потока; ждать завершения потока; закрыть семафор чтения; удалить семафор чтения; закрыть семафор записи; удалить семафор записи;

закрыть отображение разделяемой памяти на локальный адрес; удалить разделяемую память;

}

Вопросы для самопроверки

1.Какие программные интерфейсы существуют для получения участка разделяемой памяти?

2.Какими достоинствами и какими недостатками обладает способ взаимодействия процессов через разделяемую память?

3.На основе какого параметра функции открытия разделяемой памяти один и тот же участок становится доступным из разных процессов?

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

5.С какой целью в предлагаемых шаблонах программ используется пара семафоров – семафор записи и семафор чтения?

6.Сразу при создании участок разделяемой памяти получает нулевую длину. Каким образом впоследствии обеспечивается возможность записи данных в этот участок?

20