Все о моделировании в Компас-3D LT
   Главная Статьи Файлы Форум Ссылки Категории новостей
April 28 2024 06:33:45   
Навигация
Главная
Статьи
Файлы
FAQ
Форум
Ссылки
Категории новостей
Обратная связь
Фото галерея
Поиск
Разное
Карта Сайта
Популярные статьи
Что необходимо ... 65535
4.12.1 Професси... 32814
Учимся удалять!... 31916
Примеры, синони... 23301
Просмотр готовы... 22528
Декартовы коорд... 22058
FAST (методика ... 21346
содержание - се... 20567
Просмотр готовы... 19170
Работа с инстру... 14631
Сейчас на сайте
Гостей: 1
На сайте нет зарегистрированных пользователей

Пользователей: 9,955
новичок: Logyattella
Друзья сайта
Ramblers Top100
Рейтинг@Mail.ru

Реклама
Выполняем курсовые и лабораторные по разным языкам программирования
Подробнее - курсовые и лабораторные на заказ по Delphi
Turbo Pascal, Assembler, C, C++, C#, Visual Basic, Java, GPSS, Prolog
11.2.1 Сообщения

Когда пользователь вызывает функцию msgget для того, чтобы создать новый дескриптор, ядро просматривает массив очередей сообщений в поисках существующей очереди с указанным идентификатором. Если такой очереди нет, ядро выделяет новую очередь, инициализирует ее и возвращает идентификатор пользователю. В противном случае ядро проверяет наличие необходимых прав доступа и завершает выполнение функции.
Для посылки сообщения процесс использует системную функцию msgsnd:
msgsnd(msgqid, msg, count, flag);
где msgqid — дескриптор очереди сообщений, обычно возвращаемый функцией msgget, msg — указатель на структуру, состоящую из типа в виде назначаемого пользователем целого числа и массива символов, count — размер информационного массива, flag — действие, предпринимаемое ядром в случае переполнения внутреннего буферного пространства.
алгоритм msgsnd /* послать сообщение */
входная информация:
(1) дескриптор очереди сообщений
(2) адрес структуры сообщения
(3) размер сообщения
(4) флаги
выходная информация: количество посланных байт
{
проверить правильность указания дескриптора и наличие соответствующих прав доступа;
do while (для хранения сообщения не будет выделено место) {
if (флаги не разрешают ждать) return;
sleep (до тех пор, пока место не освободится);
}
получить заголовок сообщения;
считать текст сообщения из пространства задачи в пространство ядра;
настроить структуры данных: выстроить очередь заголовков сообщений, установить в заголовке указатель на текст сообщения, заполнить поля, содержащие счетчики, время последнего выполнения операций и идентификатор процесса;
вывести из состояния приостанова все процессы, ожидающие разрешения считать сообщение из очереди;
}
Рисунок 11.4. Алгоритм посылки сообщения
Ядро проверяет (Рисунок 11.4), имеется ли у посылающего сообщение процесса разрешения на запись по указанному дескриптору, не выходит ли размер сообщения за установленную системой границу, не содержится ли в очереди слишком большой объем информации, а также является ли тип сообщения положительным целым числом. Если все условия соблюдены, ядро выделяет сообщению место, используя карту сообщений (см. раздел 9.1), и копирует в это место данные из пространства пользователя. К сообщению присоединяется заголовок, после чего оно помещается в конец связного списка заголовков сообщений. В заголовке сообщения записывается тип и размер сообщения, устанавливается указатель на текст сообщения и производится корректировка содержимого различных полей заголовка очереди, содержащих статистическую информацию (количество сообщений в очереди и их суммарный объем в байтах, время последнего выполнения операций и идентификатор процесса, пославшего сообщение). Затем ядро выводит из состояния приостанова все процессы, ожидающие пополнения очереди сообщений. Если размер очереди в байтах превышает границу допустимости, процесс приостанавливается до тех пор, пока другие сообщения не уйдут из очереди. Однако, если процессу было дано указание не ждать (флаг IPC_NOWAIT), он немедленно возвращает управление с уведомлением об ошибке. На Рисунке 11.5 показана очередь сообщений, состоящая из заголовков сообщений, организованных в связные списки, с указателями на область текста.
Рисунок 11.5. Структуры данных, используемые в организации сообщений
Рассмотрим программу, представленную на Рисунке 11.6. Процесс вызывает функцию msgget для того, чтобы получить дескриптор для записи с идентификатором MSGKEY. Длина сообщения принимается равной 256 байт, хотя используется только первое поле целого типа, в область текста сообщения копируется идентификатор процесса, типу сообщения присваивается значение 1, после чего вызывается функция msgsnd для посылки сообщения. Мы вернемся к этому примеру позже.
Процесс получает сообщения, вызывая функцию msgrcv по следующему формату:
count = msgrcv(id, msg, maxcount, type, flag);
где id — дескриптор сообщения, msg — адрес пользовательской структуры, которая будет содержать полученное сообщение, maxcount — размер структуры msg, type — тип считываемого сообщения, flag — действие, предпринимаемое ядром в том случае, если в очереди сообщений нет. В переменной count пользователю возвращается число прочитанных байт сообщения.
Ядро проверяет (Рисунок 11.7), имеет ли пользователь необходимые права доступа к очереди сообщений. Если тип считываемого сообщения имеет нулевое значение, ядро ищет первое по счету сообщение в связном списке. Если его размер меньше или равен размеру, указанному пользователем, ядро копирует текст сообщения в пользовательскую структуру и соответствующим образом настраивает свои внутренние структуры: уменьшает счетчик сообщений в очереди и суммарный объем информации в байтах, запоминает время получения сообщения и идентификатор процесса-получателя, перестраивает связный список и освобождает место в системном пространстве, где хранился текст сообщения. Если какие-либо процессы, ожидавшие получения сообщения, находились в состоянии приостанова из-за отсутствия свободного места в списке, ядро выводит их из этого состояния. Если размер сообщения превышает значение maxcount, указанное пользователем, ядро посылает системной функции уведомление об ошибке и оставляет сообщение в очереди. Если, тем не менее, процесс игнорирует ограничения на размер (в поле flag установлен бит MSG_NOERROR), ядро обрезает сообщение, возвращает запрошенное количество байт и удаляет сообщение из списка целиком.
#include ‹sys/types.h›
#include ‹sys/ipc.h›
#include ‹sys/msg.h›
#define MSGKEY 75
struct msgform {
long mtype;
char mtext[256];
};
main() {
struct msgform msg;
int msgid, pid, *pint;
msgid = msgget(MSGKEY, 0777);
pid = getpid();
pint = (int *) msg.mtext;
*pint = pid; /* копирование идентификатора процесса в область текста сообщения */
msg.mtype = 1;
msgsnd(msgid, &msg, sizeof(int), 0);
msgrcv(msgid, &msg, 256, pid, 0);
/* идентификатор процесса используется в качестве типа сообщения */
printf("клиент: получил от процесса с pid %d\n", *pint);
}
Рисунок 11.6. Пользовательский процесс
алгоритм msgrcv /* получение сообщения */
входная информация:
(1) дескриптор сообщения
(2) адрес массива, в который заносится сообщение
(3) размер массива
(4) тип сообщения в запросе
(5) флаги
выходная информация: количество байт в полученном сообщении
{
проверить права доступа;
loop:
проверить правильность дескриптора сообщения;
/* найти сообщение, нужное пользователю */
if (тип сообщения в запросе == 0)
рассмотреть первое сообщение в очереди;
else
if (тип сообщения в запросе › 0)
рассмотреть первое сообщение в очереди, имеющее данный тип;
else /* тип сообщения в запросе ‹ 0 */
рассмотреть первое из сообщений в очереди с наименьшим значением типа при условии, что его тип не превышает абсолютное значение типа, указанного в запросе;
if (сообщение найдено) {
переустановить размер сообщения или вернуть ошибку, если размер, указанный пользователем слишком мал; скопировать тип сообщения и его текст из пространства ядра в пространство задачи;
разорвать связь сообщения с очередью;
return;
}
/* сообщений нет */
if (флаги не разрешают приостанавливать работу)
return ошибку;
sleep (пока сообщение не появится в очереди);
перейти на loop;
}
Рисунок 11.7. Алгоритм получения сообщения
Процесс может получать сообщения определенного типа, если присвоит параметру type соответствующее значение. Если это положительное целое число, функция возвращает первое значение данного типа, если отрицательное, ядро определяет минимальное значение типа сообщений в очереди, и если оно не превышает абсолютное значение параметра type, возвращает процессу первое сообщение этого типа. Например, если очередь состоит из трех сообщений, имеющих тип 3, 1 и 2, соответственно, а пользователь запрашивает сообщение с типом -2, ядро возвращает ему сообщение типа 1. Во всех случаях, если условиям запроса не удовлетворяет ни одно из сообщений в очереди, ядро переводит процесс в состояние приостанова, разумеется если только в параметре flag не установлен бит IPC_NOWAIT (иначе процесс немедленно выходит из функции).
Рассмотрим программы, представленные на Рисунках 11.6 и 11.8. Программа на Рисунке 11.8 осуществляет общее обслуживание запросов пользовательских процессов (клиентов). Запросы, например, могут касаться информации, хранящейся в базе данных; обслуживающий процесс (сервер) выступает необходимым посредником при обращении к базе данных, такой порядок облегчает поддержание целостности данных и организацию их защиты от несанкционированного доступа. Обслуживающий процесс создает сообщение путем установки флага IPC _CREAT при выполнении функции msgget и получает все сообщения типа 1 — запросы от процессов-клиентов. Он читает текст сообщения, находит идентификатор процесса-клиента и приравнивает возвращаемое значение типа сообщения значению этого идентификатора. В данном примере обслуживающий процесс возвращает в тексте сообщения процессу-клиенту его идентификатор, и клиент получает сообщения с типом, равным идентификатору клиента. Таким образом, обслуживающий процесс получает сообщения только от клиентов, а клиент — только от обслуживающего процесса. Работа процессов реализуется в виде многоканального взаимодействия, строящегося на основе одной очереди сообщений.
#include ‹sys/types.h›
#include ‹sys/ipc.h›
#include ‹sys/msg.h›
#define MSGKEY 75
struct msgform {
long mtype;
char mtext[256];
} msg;
int msgid;
main() {
int i, pid, *pint;
extern cleanup();
for (i = 0; i ‹ 20; i++) signal(i, cleanup);
msgid = msgget(MSGKEY, 0777, IPC_CREAT);
for (;;) {
msgrcv(msgid, &msg, 256, 1, 0);
pint = (int *) msg.mtext;
pid = *pint;
printf("сервер: получил от процесса с pid %d\n", pid);
msg.mtype = pid;
*pint = getpid();
msgsnd(msgid, &msg, sizeof(int), 0);
}
}
cleanup() {
msgctl(msgid, IPC_RMID, 0);
exit();
}
Рисунок 11.8. Обслуживающий процесс (сервер)
Сообщения имеют форму "тип — текст", где текст представляет собой поток байтов. Указание типа дает процессам возможность выбирать сообщения только определенного рода, что в файловой системе не так легко сделать. Таким образом, процессы могут выбирать из очереди сообщения определенного типа в порядке их поступления, причем эта очередность гарантируется ядром. Несмотря на то, что обмен сообщениями может быть реализован на пользовательском уровне средствами файловой системы, представленный вашему вниманию механизм обеспечивает более эффективную организацию передачи данных между процессами.
С помощью системной функции msgctl процесс может запросить информацию о статусе дескриптора сообщения, установить этот статус или удалить дескриптор сообщения из системы. Синтаксис вызова функции:
msgctl(id, cmd, mstatbuf)
где id — дескриптор сообщения, cmd — тип команды, mstatbuf — адрес пользовательской структуры, в которой будут храниться управляющие параметры или результаты обработки запроса. Более подробно об аргументах функции пойдет речь в Приложении.
Вернемся к примеру, представленному на Рисунке 11.8. Обслуживающий процесс принимает сигналы и с помощью функции cleanup удаляет очередь сообщений из системы. Если же им не было поймано ни одного сигнала или был получен сигнал SIGKILL, очередь сообщений остается в системе, даже если на нее не ссылается ни один из процессов. Дальнейшие попытки исключительно создания новой очереди сообщений с данным ключом (идентификатором) не будут иметь успех до тех пор, пока старая очередь не будет удалена из системы.
Комментарии
Нет комментариев.
Добавить комментарий
Пожалуйста залогиньтесь для добавления комментария.
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Случайные статьи
7.2.3 Посылка сигн...
Глава 1. Ноутбук ...
12.3.3.3 Драйверы
По законам джунглей
Глава 11. BOTTOM L...
7.2.1. Обязательс...
5.5 УКАЗАНИЕ МЕСТА...
Синтаксис 2
Индукция Джона Ст...
Уникальный идентиф...
Анализ результатов...
Правила
5. Продукции типа...
СИСТЕМНЫЕ ОПЕРАЦИИ...
9.1.3 Загрузка (по...
О чем мы узнали ?
8.4. Управление пр...
7.2.4. Измерения ...
Общая информация о...
Глава 29. Автомоб...
9.6. Межгрупповая ...
Независимость данных
9.2.3.2 Обработка ...
1.5 Классификация...
Конструкционные сп...
Иерархические сети
5.16 UNLINК
Режим GPS
Разделение отношен...
Настройки телефона...
Антенна
8.2. Планирование...
Настройки Графичес...
Программы, не подд...
Программное обеспе...
Время восхода/захо...
Качество
2.4.7.4 Построение...
Шинная топология
5.14.2 Демонтирова...
Мини-чат
Вам необходимо залогиниться.

Нет присланных сообщений.
Copyright © 2009