Читаем Операционная система UNIX полностью

 0, 1, 0   /* увеличить значение семафора на 1 */

};

Процесс запирает ресурс вызовом:

semop(semid, &sop_lock[0], 1);

а освобождает:

semop(semid, &sop_unlock[0], 1);

Во втором случае операции получились проще (по крайней мере их код стал компактнее), однако этот подход имеет потенциальную опасность: при создании семафора, его значения устанавливаются равными 0, и во втором случае он сразу же запирает ресурс. Для преодоления данной ситуации процесс, первым создавший семафор, должен вызвать операцию sop_unlock, однако в этом случае процесс инициализации семафора перестанет быть атомарным и может быть прерван другим процессом, который, в свою очередь, изменит значение семафора. В итоге, значение семафора станет равным 2, что повредит нормальной работе с разделяемым ресурсом.

Можно предложить следующее решение данной проблемы:

/* Создаем семафор, если он уже существует semget

   возвращает ошибку, поскольку указан флаг IPC_EXCL */

if ((semid = semget(key, nsems, perms | IPC_CREAT | IPC_EXCL)) < 0) {

 if (errno = EEXIST) {

  /* Действительно, ошибка вызвана существованием объекта */

  if ((semid = semget(key, nsems, perms)) < 0)

   return(-1); /* Возможно, не хватает системных ресурсов */

 } else

 return(-1); /* Возможно, не хватает системных ресурсов * /

}

/* Если семафор создан нами, проинициализируем его */

else

 semop(semid, &sop_unlock[0], 1);

<p>Разделяемая память</p>

Интенсивный обмен данными между процессами с использованием рассмотренных механизмов межпроцессного взаимодействия (каналы, FIFO, очереди сообщений) может вызвать падение производительности системы. Это, в первую очередь, связано с тем, что данные, передаваемые с помощью этих объектов, копируются из буфера передающего процесса в буфер ядра и затем в буфер принимающего процесса. Механизм разделяемой памяти позволяет избавиться от накладных расходов передачи данных через ядро, предоставляя двум или более процессам возможность непосредственного получения доступа к одной области памяти для обмена данными.

Безусловно, процессы должны предварительно "договориться" о правилах использования разделяемой памяти. Например, пока один из процессов производит запись данных в разделяемую память, другие процессы должны воздержаться от работы с ней. К счастью, задача кооперативного использования разделяемой памяти, заключающаяся в синхронизации выполнения процессов, легко решается с помощью семафоров.

Примерный сценарий работы с разделяемой памятью выглядит следующим образом:

1. Сервер получает доступ к разделяемой памяти, используя семафор.

2. Сервер производит запись данных в разделяемую память.

3. После завершения записи сервер освобождает разделяемую память с помощью семафора.

4. Клиент получает доступ к разделяемой памяти, запирая ресурс с помощью семафора.

5. Клиент производит чтение данных из разделяемой памяти и освобождает ее, используя семафор.

Для каждой области разделяемой памяти, ядро поддерживает структуру данных shmid_ds, основными полями которой являются:

struct ipc_perm shm_permПрава доступа, владельца и создателя области (см. описание ipc_perm выше)
int shm_segszРазмер выделяемой памяти
ushort shm_nattchЧисло процессов, использующих разделяемую память
time_t shm_atimeВремя последнего присоединения к разделяемой памяти
time_t shm_dtimeВремя последнего отключения от разделяемой памяти
time_t shm_ctimeВремя последнего изменения

Для создания или для доступа к уже существующей разделяемой памяти используется системный вызов shmget(2):

#include

#include

#include

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

Перейти на страницу:

Похожие книги

Архитектура операционной системы UNIX (ЛП)
Архитектура операционной системы UNIX (ЛП)

Настоящая книга посвящена описанию внутренних алгоритмов и структур, составляющих основу операционной системы (т. н. «ядро»), и объяснению их взаимосвязи с программным интерфейсом. Таким образом, она будет полезна для работающих в различных операционных средах. При работе с книгой было бы гораздо полезнее обращаться непосредственно к исходному тексту системных программ, но книгу можно читать и независимо от него.  Во-вторых, эта книга может служить в качестве справочного руководства для системных программистов, из которого последние могли бы лучше уяснить себе механизм работы ядра операционной системы и сравнить между собой алгоритмы, используемые в UNIX, и алгоритмы, используемые в других операционных системах. Наконец, программисты, работающие в среде UNIX, могут углубить свое понимание механизма взаимодействия программ с операционной системой и посредством этого прийти к написанию более эффективных и совершенных программ.

Морис Дж Бах , Морис Дж. Бах

ОС и Сети, интернет / ОС и Сети / Книги по IT