Н.В. Вдовикина, И.В. Машечкин, А.Н. Терехин, В.В. Тюляева - Программирование в ОС UNIX на языке Си (1114655), страница 13
Текст из файла (страница 13)
Ключи являются уникальными во всей UNIXсистеме идентификаторами объектов IPC, и, зная ключ для некоторого объекта, процесс может получить к нему доступ. При этом процессу возвращается дескриптор объекта, который в дальнейшем используется для всех операций с ним. Проведя аналогию с файловойсистемой, можно сказать, что ключ аналогичен имени файла, а получаемый по ключу дескриптор – файловому дескриптору, получаемому во время операции открытия файла.Ключ для каждого объекта IPC задается в момент его созданиятем процессом, который его порождает, а все процессы, желающиеполучить в дальнейшем доступ к этому объекту, должны указыватьтот же самый ключ.Как видно, встает проблема именования разделяемого ресурса:необходим некий механизм получения заведомо уникального ключадля именования ресурса, но вместе с тем нужно, чтобы этот механизм позволял всем процессам, желающим работать с одним ресурсом, получить одно и то же значение ключа.Для решения этой задачи служит функция key_t ftok(char*filename, int proj).
Эта функция генерирует значение ключапо путевому имени некоторого существующего файла и добавочному целому, передаваемым в качестве параметров. Она используетдля создания значения ключа номер индексного дескриптора указанного файла и информацию о файловой системе, в которой он находится. Если файл с указанным именем не существует или недоступен вызывающему процессу, функция возвращает -1.Гарантируется, что при повторном запуске ftok() с теми же параметрамибудет получено то же самое значение ключа 15. Предполагается, чтопри условии, что указанный файл между двумя обращениями к ftok() не удалялся и непересоздавался заново, т.к.
при этом он получит другой номер индексного дескриптора1580передаваемое путевое имя файла известно всем процессам вызывающей программы и имеет в рамках ее некоторый смысл (например, это может быть имя демона-сервера, имя файла данных используемого сервером и т.п.).Смысл же второго аргумента функции ftok() – добавочногоцелого – в том, что он позволяет генерировать разные значения ключа по одному и тому же значению первого параметра – имени файла.Тем самым, используя одно и то же путевое имя, можно получитьнесколько ключей, если нам требуется доступ к нескольким различным ресурсам в рамках одной и той же программы.
Кроме того, этопозволяет программисту поддерживать несколько версий своей программы, которые будут использовать одно и то же имя файла, норазные добавочные параметры для генерации ключа, и тем самымполучат возможность в рамках одной системы работать с разнымиразделяемыми ресурсами.Функция ftok() не является системным вызовом, а предоставляется библиотекой.Общие принципы работы с разделяемыми ресурсамиКак уже говорилось, общим для всех ресурсов является механизм именования. Кроме того, для каждого IPC-ресурса поддерживается идентификатор его владельца и структура, описывающая права доступа к нему.
Подобно файлам, права доступа задаются отдельно для владельца, его группы и всех остальных пользователей; однако, для разделяемых ресурсов поддерживается только две категориидоступа: по чтению и записи. Априори считается, что возможностьизменять свойства ресурса и удалять его имеется только у процесса,эффективный идентификатор пользователя которого совпадает сидентификатором владельца ресурса. Владельцем ресурса назначается пользователь, от имени которого выполнялся процесс, создавший ресурс, однако создатель может передать права владельца другому пользователю.
В заголовочном файле <sys/ipc.h> определентип struct ipc_perm, который описывает права доступа к любомуIPC-ресурсу. Поля в этой структуре содержат информацию о создателе и владельце ресурса и их группах, правах доступа к ресурсу иего ключе.Для создания разделяемого ресурса с заданным ключом, либоподключения к уже существующему ресурсу с таким ключом используются ряд системных вызовов, имеющих общий суффикс get.Общими параметрами для всех этих вызовов являются ключ и флаги.В качестве значения ключа при создании любого IPC-объектаможет быть указано значение IPC_PRIVATE. При этом создается ре81сурс, который будет доступен только породившему его процессу.Такие ресурсы обычно порождаются родительским процессом, который затем сохраняет полученный дескриптор в некоторой переменной и порождает своих потомков.
Так как потомкам доступенуже готовый дескриптор созданного объекта, они могут непосредственно работать с ним, не обращаясь предварительно к «get»методу. Таким образом, созданный ресурс может совместно использоваться родительским и порожденными процессами. Однако, еслиодин из этих процессов повторно вызовет «get»-метод с ключомIPC_PRIVATE, в результате будет получен другой, совершенно новыйразделяемый ресурс, так как при обращении к «get»-методу с ключом IPC_PRIVATE всякий раз создается новый объект нужноготипа16.Если при обращении к «get»-методу указан ключ, отличныйот IPC_PRIVATE, происходит следующее:• Происходит поиск объекта с заданным ключом среди ужесуществующих объектов нужного типа.
Если объект с указанным ключом не найден, и среди флагов указан флагIPC_CREAT, будет создан новый объект. При этом значениепараметра флагов должно содержать побитовое сложениефлага IPC_CREAT и константы, указывающей права доступадля вновь создаваемого объекта.• Если объект с заданным ключом не найден, и среди переданных флагов отсутствует флаг IPC_CREAT, «get»-методвернет –1, а в переменной errno будет установлено значение ENOENT• Если объект с заданным ключом уже существует, «get»метод вернет дескриптор для этого существующего объекта.Если такая ситуация нежелательна (т.е.
означает случайнуюколлизию имен), следует указать в параметре флагов нарядус флагом IPC_CREAT и правами доступа еще и флагIPC_EXCL – в этом случае «get»-метод вернет -1, если объект с таким ключом уже существует (переменная errno будет установлена в значение EEXIST)• при подключении к уже существующему объекту дополнительно проверяются права доступа к нему. В случае, еслипроцесс, запросивший доступ к объекту, не имеет на тогарантируется, что функция ftok() ни при каких значениях своих входных параметров не может сгенерировать ключ, совпадающий с IPC_PRIVATE.1682прав, «get»-метод вернет –1, а в переменной errno будетустановлено значение EACCESSДля каждого типа объектов IPC существует некое ограничениена максимально возможное количество одновременно существующих в системе объектов данного типа.
Если при попытке созданиянового объекта указанное ограничение будет превышено, «get»метод, совершавший попытку создания объекта, вернет -1, а в переменной errno будет указано значение ENOSPC.Даже если ни один процесс не подключен к разделяемому ресурсу, система не удаляет его автоматически. Удаление объектовIPC является обязанностью одного из работающих с ним процессови для этого системой предоставляются соответствующие функциипо управлению объектами System V IPC.Очередь сообщенийОчередь сообщений представляет собой некое хранилище типизированных сообщений, организованное по принципу FIFO.
Любой процесс может помещать новые сообщения в очередь и извлекать из очереди имеющиеся там сообщения. Каждое сообщение имеет тип, представляющий собой некоторое целое число. Благодаряналичию типов сообщений, очередь можно интерпретировать двояко— рассматривать ее либо как сквозную очередь неразличимых потипу сообщений, либо как некоторое объединение подочередей, каждая из которых содержит элементы определенного типа. Извлечение сообщений из очереди происходит согласно принципу FIFO – впорядке их записи, однако процесс-получатель может указать, из какой подочереди он хочет извлечь сообщение, или, иначе говоря, сообщение какого типа он желает получить – в этом случае из очередибудет извлечено самое «старое» сообщение нужного типа (см.
Рис.2).ВААВАВАРис.2 Типизированные очереди сообщенийРассмотрим набор системных вызовов, поддерживающий работу с очередями сообщений.Доступ к очереди сообщенийДля создания новой или для доступа к существующей очередииспользуется системный вызов int msgget (key_t key, int83msgflag). В случае успеха вызов возвращает положительный деск-риптор очереди, который может в дальнейшем использоваться дляопераций с ней, в случае неудачи -1. Первым аргументом вызова является ключ, вторым – флаги, управляющие поведением вызова.Подробнее детали процесса создания/подключения к ресурсу описаны выше.Отправка сообщенияДля отправки сообщения используется функция int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg).Ее первый аргумент — идентификатор очереди, полученный в результате вызова msgget().
Второй аргумент — указатель на буфер,содержащий реальные данные (тело сообщения) и тип сообщения,подлежащего посылке в очередь, в третьем аргументе указываетсядлина тела сообщения в байтах.Буфер интерпретируется как структура, соответствующая следующему шаблону:#include <sys/msg.h>struct msgbuf {long msgtype; // тип сообщенияchar msgtext[1]; //данные (тело сообщения)};В реальности такая структура не означает, что телом сообщения обязательно должен быть лишь один символ (и вообще текст,состоящий из символов).