2011. Машбук (1114722), страница 45
Текст из файла (страница 45)
Семафоры IPC предназначены,в первую очередь, для использования в качестве средств организации синхронизации.Общая, или разделяемая, память, которая представляется процессу как указатель наобласть памяти, которая является общей для двух и более процессов. Т.е. внутрипроцесса некоторый указатель можно установить на начало данной области и работать165далее с этой областью, как с массивом. Все изменения, которые сделает данныйпроцесс, будут видны другим процессам. Разделяемая память IPC почти не обладаетникакими средствами синхронизации (т.е.
существует очень слабо развитый механизмвзаимных блокировок, но мы на нем не будем останавливаться).Для организации совместного использования разделяемых ресурсов необходимнекоторый механизм именования ресурсов, используя который взаимодействующиепроцессы смогут работать с данным конкретным ресурсом.
Для этих целей используетсясистема ключей: при создании ресурса с ним ассоциируется ключ — целочисленноезначение. Жесткого ограничения к выбору этих ключей нет. Т.е. при создании ресурса,(например, общей памяти) процесс-создатель ассоциирует с ним конкретный ключ —например, 25. Теперь все процессы, желающие работать с той же общей памятью,должны, во-первых, обладать соответствующими правами, а во-вторых, заявить, что онижелают работать с ресурсом общая память с ключом 25. И они будут с ней работать.
Нотут возможны коллизии из-за случайного совпадения ключей различных ресурсов.Во избежание коллизий система предлагает некоторую унификацию именованияIPC-ресурсов. Для генерации уникальных ключей в системе имеется библиотечнаяфункция ftok().#include <sys/types.h>#include <sys/ipc.h>key_t ftok(char *filename, char proj);Первый параметр данной функции — полное имя существующего файла. Второйпараметр — это уточняющая информация (значение символьной переменной; в частности,этот параметр может использоваться для поддержания разных версий программы).Итак, функция ftok() обращается к указанному файлу, считывает его атрибуты и,используя значение второго аргумента, генерирует уникальный ключ (уникальное целоечисло).
Стоит особо обратить внимание, что первый параметр должен указывать насуществующий файл, и, что не менее важно, при генерации ключа используются атрибутыфайла. Это означает, что если один процесс для генерации ключа ссылается на некоторыйфайл, создает ресурс, потом этот файл уничтожается и создается другой файл с тем жеименем (но, скорее всего, с другими атрибутами), то другой процесс, желающий получитьключ к созданному ресурсу, не сможет этого сделать, т.к. функция ftok() будетгенерировать иное значение.Каждый ресурс IPC имеет атрибут владельца. Владельцем считается тот процесс(его идентификация), который создал данный ресурс, и, соответственно, удалить данныйресурс может только владелец.
Но стоит отметить, что существует механизм передачиправ владения от процесса процессу.С каждым ресурсом, так же как и с файлами, связаны три категории прав (прававладельца, группы и остальных пользователей). Но в каждой категории имеются лишьправа на чтение и запись: право на выполнение нет.Ресурсы IPC могут существовать без процессов, их создавших. Это означает, чтосозданный разделяемый ресурс будет существовать до тех пор, пока его явно не удалятлибо до перезапуска системы.Итак, имеется три группы IPC-ресурсов, с каждой из которой связан свой наборфункций по работе с конкретным типом ресурса. Но функциональная структура работыидентична.
В частности, среди этих наборов можно выделить функции, имеющие суффиксget (а префиксная часть представляет собою аббревиатуру имени ресурса). Средипараметров данных функций присутствует ключ, о котором шла речь выше, а такженекоторые флаги. Соответственно, эти функции в зависимости от флагов позволяютработать либо в режиме создания ресурса, либо в режиме подключения к существующемуIPC-ресурсу, ассоциированному с указываемым ключом.166<ResourceName>get(key, ..., flags);Параметр key – ключ, который мы хотим ассоциировать с разделяемым ресурсом.Параметр флаги (flags) задаёт права доступа к ресурсу и режимы работы сресурсом. Этот параметр может быть комбинацией различных флагов.
Основные из нихприведены ниже.IPC_PRIVATE — данный флаг определяет создание частного IPC-ресурса,доступного только процессу, который его создал, не доступного остальнымпроцессам. Т.е. функция get при наличии данного флага всегда открывает новыйресурс, к которому никто другой не может подключиться. Данный флаг позволяетиспользовать разделяемый ресурс между родственными процессами (посколькудескриптор созданного ресурса передается при наследовании сыновним процессам).IPC_CREAT — если данного флага нет среди параметров функции get, то этоозначает, что процесс хочет подключиться к существующему ресурсу. В этом случае,если такой ресурс существует и права доступа позволяют к нему обратиться, топроцесс получит дескриптор ресурса и продолжит работу.
Иначе функция get вернеткод ошибки -1, а переменная errno будет содержать код ошибки. Если же при вызовефункции get данный флаг установлен, то функция работает на создание илиподключение к существующему ресурсу. В данном случае возможно возникновениеошибки из-за нехватки прав доступа в случае существования ресурса. Но приустановленном флаге встает вопрос, кто является владельцем ресурса, и,соответственно, кто его должен удалять (поскольку каждый процесс либоподключается к существующему ресурсу, либо создает новый). Для разрешенияданной проблемы используется следующий флаг.IPC_EXCL — используя данный флаг в паре с флагом IPC_CREAT, функция getбудет работать только на создание нового ресурса. Если же ресурс будет ужесуществовать, то функция get вернет -1, а переменная errno будет содержать кодсоответствующей ошибки.Ниже приводится список некоторых ошибок, возможных при вызове функции get,возвращаемых в переменной errno:ENOENT — ресурс не существует, и не указан флаг IPC_CREAT;EEXIST — ресурс существует, и установлены флаги IPC_CREAT | IPC_EXCL;EACCESS — не хватает прав доступа на подключение.3.2.1 Очередь сообщений IPCСистема предоставляет возможность создания некоторого функциональнорасширенного аналога канала, причём главное отличие заключается в том, что сообщенияв очереди сообщений IPC типизированы.
Каждое сообщение помимо своейсодержательной части имеет атрибут тип сообщения (неотрицательное целое значение).Тогда очередь сообщений можно рассматривать с двух позиций: во-первых, как сквознуюочередь (когда все сообщения, вне зависимости от типа, рассматриваются как единаяочередь), а, во-вторых, как суперпозицию очередей однотипных сообщений (Рис. 99).
Приэтом способ интерпретации допускает одновременно различные типы интерпретации.Непосредственный выбор интерпретации определяется в момент считывания сообщенияиз очереди.167BAABABAРис. 99. Очередь сообщений IPC.Для организации работы с очередью предусмотрен набор функций. Во-первых, этоуже упомянутая функция создания/доступа к очереди сообщений.#include <sys/types.h>#include <sys/ipc.h>#include <sys/message.h>int msgget(key_t key, int msgflag);У данной функции два параметра: ключ и флаги. В случае успешного выполненияфункция возвращает положительный дескриптор очереди, иначе возвращается -1.Рассмотрим теперь функции отправки и приема сообщений.
Для отправкисообщений служит функция msgsnd().#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgsnd(int msqid, const void *msgp, size_t msgsz,int msgflg);Первый аргумент — идентификатор очереди, полученный в результате вызоваmsgget(). Второй аргумент — указатель на буфер, содержащий реальные данные и типсообщения, подлежащего посылке в очередь, в третьем аргументе указывается размербуфера. В качестве буфера используется структура, содержащая следующие поля:long msgtype — тип сообщения (только положительное длинное целое);char msgtext[] — данные (тело сообщения).В заголовочном файле <sys/msg.h> определена константа MSGMAX,описывающая максимальный размер тела сообщения. При попытке отправить сообщение,у которого число элементов в массиве msgtext превышает это значение, системныйвызов вернет –1.Последний аргумент функции — это флаги.
Среди разнообразных флагов можновыделить те, которые определяют режим блокировки при отправке сообщения. Если флагравен 0, то вызов будет блокироваться, если для отправки недостаточно системныхресурсов. Можно установить флаг IPC_NOWAIT, который позволяет работать безблокировки: тогда, в случае возникновения ошибки при отправке сообщения, вызоввернет -1, а переменная errno будет содержать соответствующий код ошибки.Для получения сообщений используется функция msgrcv().#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>int msgrcv(int msqid, void *msgp, size_t msgsz,long msgtyp, int msgflg);168Первые три аргумента аналогичны аргументам предыдущего вызова: дескрипторочереди, указатель на буфер, куда следует поместить данные, и максимальный размер (вбайтах) тела сообщения, которое можно туда поместить.