|
Программирование >> Структура ядра и системные вызовы
конечным точкам канала с целью чтения и записи данных может подклю чаться множество процессов, но механизма, который обеспечивал бы избирательную связь между читающим и записывающим процессами, нет. Пусть, к примеру, процессы А и В подсоединены к конечной точке канала для записи, а процессы С и D - к конечной точке для чтения. Если и А, и В записывают данные в канал в расчете на то, что данные процесса А будет читать процесс С, а данные процесса В - процесс D, то С и D не смогут избирательно читать данные, предназначенные конкретно каждому из них. Другая проблема состоит в том, что для успещной передачи сообщения к обоим концам канала должны быть подсоединены процессы, иначе данные теряются. Таким образом, каналы и находящиеся в них данные являютсй нерезидентными объектами, и если процессы вьшолняются не одновременно, надежный обмен данными не обеспечивается. Сообщения, кроме того, позволяют осуществлять доступ к центральной очереди сообщений сразу множеству процессов. При этом каждый процесс, который помещает сообщение в очередь, должен указать для своего сообщения целочисленный тип. Процесс-получатель сможет выбрать это сообщение, указав тот же тип. Кроме того, сообщения не удаляются из очереди, даже если к ней не обращается ни один процесс. Сообщения удаляются из очереди только тогда, когда процессы обращаются к ним явно. Следовательно, механизм использования сообщений позволяет осуществить более гибкое многопроцессное взаимодействие. Если в UNIX-системе существует множество очередей сообщений, каждая из них может использоваться для организации межпроцессного взаимодействия сразу несколькими приложениями. 10.3.1. Поддержка сообщений ядром UNIX Реализация очередей сообщений в UNIX System V.3 и V.4 аналогична реализации UNIX-файлов. В частности, в адресном пространстве ядра имеется таблица очередей сообщений, в которой отслеживаются все очереди сообщений, создаваемые в системе. В каждой записи таблицы сообщений можно найти следующие данные, относящиеся к одной из очередей: Имя, представляющее собой целочисленный идентификационный ключ, присвоенный очереди процессом, который ее создал. Другие процессы могут, указывая этот ключ, открывать очередь и получать дескриптор , для доступа к ней. ;%if UID и GID создателя очереди. Процесс, эффективный UID которого {Совпадает с UID создателя очереди сообщений, имеет право удалять . очередь и изменять параметры управления ею. * UID и GID назначенного владельца. Эти идентификаторы обычно сов-;,. падают с идентификаторами создателя очереди, но создатель может изменять эти идентификаторы для переназначения владельца очереди и ая принадлежности к фуппе. Права доступа к очереди для чтения-записи по категориям владелец , ( группа и прочие . Процесс, имеющий право на чтение сообщений из очереди, может получать сообщения и запрашивать UID и GID назначенного владельца этой очереди. Процесс, имеющий право на запись в очередь, может передавать в нее сообщения. Время и идентификатор процесса, который последним передал сообщение в очередь. Время и идентификатор процесса, который последним прочитал сообщение из очереди. Указатель на связный список сообщений, находящихся в очереди. В каждой записи списка хранится одно сообщение и присвоенный ему тип. На рис. 10.1 изображена структура данных ядра, используемая для манипулирования очередью сообщений. Очередь сообщений Запись сообщения Таблица сообщений Рис. 10.1. Структура данных ядра, используемая для манипулирования очередью сообщений Когда процесс передает сообщение в очередь, ядро создает для него новую запись и помещает ее в конец связного списка записей, соответствующих сообщениям указанной очереди. В каждой такой записи указывается тип сообщения, число байтов данных, содержащихся в сообщении, и указатель на другую область данных ядра, где фактически находятся данные сообщения. Ядро копирует данные, содержащиеся в сообщении, из адресного пространства процесса-отправителя в эту область данных ядра, чтобы процесс-отправитель мог завершиться, а сообщение осталось доступным для чтения другими процессами. Когда процесс выбирает сообщение из очереди, ядро копирует относящиеся к нему данные из записи сообщения в адресное пространство этого процесса, а затем удаляет запись. Процесс может выбрать сообщение из очереди следующими способами: Выбрать самое старое сообщение, независимо от его типа. ; Выбрать сообщение, идентификатор которого совпадает с идентифика- тором, указанным процессом. Если в очереди есть несколько сообщений заданного типа, из них выбирается самое старое. Выбрать сообщение, числовое значение типа которого - наименьшее из меньших или равных значению типа, указанного процессом. Если этому критерию удовлетворяют несколько сообщений, из них выбирается самое старое. Если процесс попытается прочитать сообщение из очереди, в которой ни одно сообщение не удовлетворяет критерию поиска, ядро по умолчанию переведет его в состояние ожидания (пока в очередь не поступит сообщение, которое этот процесс сможет прочитать). Если же процесс укажет в системном вызове приема сообщения неблокирующий флаг, то этот вызов не заблокирует процесс, а вьщаст код неудачного завершения. На процедуру манипулирования сообщениями система устанавливает ряд ограничений, которые определяются в заголовке <sys/msg.h>. Системное ограничение Значение MSGMNI MSGMAX MSGMNB MSGTQL Максимальное число очередей сообщений, которые могут существовать в системе в любой данный момент времени Максимальное число байтов данных в сообщении Максимальное число байтов во всех сообщениях одной очереди Максимальное число сообщений во всех очередях Влияние этих системных ограничений на процессы таково: если текущее число очередей сообщений, существующих в системе, равно MSGMNI, то любая попытка создания процессом новой очереди сообщений будет неудачной до тех пор, пока какой-либо процесс не удалит одну из существующих очередей; если процесс попытается передать сообщение размером более MSGMAX, этот системный вызов выполнен не будет; если попытка процесса передать в очередь сообщение вызовет превышение лимита MSGMNB или MSGTQL, этот процесс будет заблокирован до тех пор, пока из очереди не будет получено одно или более сообщений и не появится возможность вставить сообщение в очередь без нарушения обоих этих ограничений. 10.3.2. API ОС UNIX, предназначенные для обмена сообщениями в заголовке <sys/ipc.h> объявляется тип данных struct ipc perm, который используется для хранения UID создателя, UID владельца, идентификаторов их групп, имени (ключа) очереди и прав на чтение и запись для той или иной очереди сообщений. В UNIX System V этот тип данных используется также Ьри организации IPC на основе семафоров и разделяемой памяти. Запись таблицы сообщений имеет тип данных struct msqid cls, определяемый в заголовке <sys/message.h>. Ниже перечислены информационные поля этой структуры и данные, которые в них хранятся. Поле Данные msg perm Данные, хранящиеся в записи типа struct ipcjerm msg f irst Указатель на первое (самое старое) сообщение в очереди msg last Указатель на последнее (самое новое) сообщение в очереди msg cbyte Общее число байтов во всех сообщениях, находящихся в очереди ~ на данный момент msg qnum Общее число сообщений, находящихся в очереди на данный ~ момент msq qbyte Максимальное число байтов во всех сообщениях, которые могут находиться в очереди. Обычно это MSGMNB, но создатель или назначенный владелец очереди может установить и более низкое значение msg lspid Идентификатор процесса, который последним передал в очередь сообщение msg lrpid Идентификатор процесса, который последним прочитал из очереди сообщение msg stime Время, когда в очередь было передано самое последнее сообщение msg rtime Время, когда из очереди было прочитано самое последнее сообщение msg ctime Время последнего изменения управляющих параметров очереди ~ сообщений (прав доступа, идентификатора владельца и идентификатора группы владельца) Структура struct msg, определенная в заголовке <sys/msg.h>,- это тип данных для записи сообщения. Ниже перечислены информационные поля этой структуры и данные, которые в них приводятся. Поле Данные f sg type Целочисленный тип, присвоенный сообщению msg ts Количество байтов в тексте сообщения msg spot Указатель на текст сообщения, который хранится в другой области данных ядра msg next Указатель на следующую запись сообщения или NULL, если это последняя запись в очереди сообщений На рис. 10.2 показано, как вышеупомянутые структуры используются в таблице сообщений и записях сообщений. msgjast struct msqid ds Область памяти ядра struct msg msg first
msg spot struct msg msg spot Таблица сообщений Рис. 10.2. Типы данных для очереди сообщений и записей сообщений Для манипулирования сообщениями используются четыре API: API сообщений Назначение msgget msgsnd msg rev msgcti Открытие для доступа и создание (при необходимости) очереди сообщений Передача сообщения в очередь Прием сообщения из очереди Манипулирование управляющими параметрами очереди сообщений ттхт отмечалось вьше, сообщения обрабатываются так же, как файлы UNIX, поэтому между API сообщений и API файлов можно провести следующую аналогию. API сообщений API файлов msgget open msgsnd т write msg rev read sgtt stat, unlink, chmod, chown Для этих API сообщений необходимы следующие файлы заголовков: ♦include <sys/types.h> ♦include <sys/ipc.h> ♦include <sys/msg.h> 10.3.3. функция msgget прототип функции msgget выглядит следующим образом: #include <sys/types.h> #include <sys/ipc.h> #include <sys/message.h> int msgget {key t key, int flag ); Эта функция открывает очередь сообщений, идентификатор которой совпадает со значением аргумента key, и возвращает положительный целочисленный дескриптор. Его можно использовать в других API сообщений для передачи и приема сообщений, а также для запроса и/или установки управляющих параметров очереди. Если значение аргумента key - положительное целое, этот API пробует открыгь очередь сообщений, идентификатор которой совпадает с данным значением. Если же значением key является макрос IPC PRrVATE, API создает новую очередь сообщений, которая будет использоваться исключительно вызывающим процессом. Если аргумент flag имеет нулевое значение и нет очереди сообщений, идентификатор которой совпадал бы с заданным значением key, то API прерывается; в противном случае возвращается дескриптор этой очереди. Если процессу необходимо создать новую очередь (когда нет ни одной очереди), то значение аргумента/7ag должно содержать макрос IPC CREAT, а также права на чтение сообщений из новой очереди и запись в нее (для владельца, группы и прочих). Например, следующий системный вызов создает очередь сообщений с ключевым идентификатором 15 и правами доступа 0644 (чтение-запись для владельца, только чтение для членов группы и прочих пользователей), если такая очередь не существует. Этот вызов возвращает целочисленный дескриптор для последующих обращений к данной очереди: int msgfdesc = msgget ( 15, IPC CREAT064 4 ); Если желательно иметь гарантию создания новой очереди сообщений, можно указать одновременно с флагом IPC CREAT флаг IPC EXCL, и этот API будет успешно выполнен только в том случае, если он создаст новую очередь с заданным значением key. В случае неудачи такой API возвращает -1. Вот некоторые возможные причины неудачи: Значение errno Причина ошибки ENOSPC ENOENT Достигнут установленный системой лимит MSGMNI Аргумент flag не содержит флаг IPC CREAT, а очереди с указанным значением key нет
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |