Операционная система UNIX - Робачевский Андрей Михайлович
Шрифт:
Интервал:
Закладка:
exit(0);
}
Клиент:#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "mesg.h"
main {
/* Структура нашего сообщения (может отличаться от
структуры msgbuf */
Message message;
key_t key;
int msgid, length;
/* Тип посылаемого сообщения, может использоваться для
мультиплексирования */
message.mtype = 1L;
/* Получим ключ */
if ((key = ftok("server", 'A')) < 0) {
printf("Невозможно получить ключn");
exit(1);
}
/* Получим доступ к очереди сообщений, очередь уже
должна быть создана сервером */
if ((msgid = msgget(key, 0)) < 0) {
printf("Невозможно получить доступ к очередиn");
exit(1);
}
/* Поместим строку в сообщение */
if ((length = sprintf(message.buff,
"Здравствуй, Мир!n")) < 0) {
printf("Ошибка копирования в буферn");
exit(1);
} /* Передадим сообщение */
if (msgsnd(msgid, (void*)&message, length, 0) != 0) {
printf("Ошибка записи сообщения в очередьn");
exit(1);
}
/* Удалим очередь сообщений */
if (msgctl(msgid, IPC_RMID, 0) < 0) {
printf("Ошибка удаления очередиn");
exit(1);
}
exit(0);
}
Семафоры
Для синхронизации процессов, а точнее, для синхронизации доступа нескольких процессов к разделяемым ресурсам, используются семафоры. Являясь одной из форм IPC, семафоры не предназначены для обмена большими объемами данных, как в случае FIFO или очередей сообщений. Вместо этого, они выполняют функцию, полностью соответствующую своему названию — разрешать или запрещать процессу использование того или иного разделяемого ресурса.
Применение семафоров поясним на простом примере. Допустим, имеется некий разделяемый ресурс (например, файл). Необходимо блокировать доступ к ресурсу для других процессов, когда некий процесс производит операцию над ресурсом (например, записывает в файл). Для этого свяжем с данным ресурсом некую целочисленную величину — счетчик, доступный для всех процессов. Примем, что значение 1 счетчика означает доступность ресурса, 0 — его недоступность. Тогда перед началом работы с ресурсом процесс должен проверить значение счетчика. Если оно равно 0 — ресурс занят и операция недопустима — процессу остается ждать. Если значение счетчика равно 1 — можно работать с ресурсом. Для этого, прежде всего, необходимо заблокировать ресурс, т. е. изменить значение счетчика на 0. После выполнения операции для освобождения ресурса значение счетчика необходимо изменить на 1. В приведенном примере счетчик играет роль семафора.
Для нормальной работы необходимо обеспечить выполнение следующих условий:
1. Значение семафора должно быть доступно различным процессам. Поэтому семафор находится не в адресном пространстве процесса, а в адресном пространстве ядра.
2. Операция проверки и изменения значения семафора должна быть реализована в виде одной атомарной по отношению к другим процессам (т. е. непрерываемой другими процессами) операции. В противном случае возможна ситуация, когда после проверки значения семафора выполнение процесса будет прервано другим процессом, который в свою очередь проверит семафор и изменит его значение. Единственным способом гарантировать атомарность критических участков операций является выполнение этих операций в режиме ядра (см. режимы выполнения процесса).
Таким образом семафоры являются системным ресурсом, действия над которым производятся через интерфейс системных вызовов.
Семафоры в System V обладают следующими характеристиками:
□ Семафор представляет собой не один счетчик, а группу, состоящую из нескольких счетчиков, объединенных общими признаками (например, дескриптором объекта, правами доступа и т.д.).
□ Каждое из этих чисел может принимать любое неотрицательное значение в пределах, определенных системой (а не только значения 0 и 1).
Для каждой группы семафоров (в дальнейшем мы будем называть группу просто семафором) ядро поддерживает структуру данных semid_ds, включающую следующие поля:
struct ipc_perm sem_perm Описание прав доступа struct sem *sem_base Указатель на первый элемент массива семафоров ushort sem_nsems Число семафоров в группе time_t sem_otime Время последней операции time_t sem_ctime Время последнего измененияЗначение конкретного семафора из набора хранится во внутренней структуре sem:
ushort semval Значение семафора pid_t sempid Идентификатор процесса, выполнившего последнюю операцию над семафором ushort semncnt Число процессов, ожидающих увеличения значения семафора ushort semzcnt Число процессов, ожидающих обнуления семафора