|
|
|
|
|
|
|
|
|
Лекция №17
Interprocess Communication
Мы с вами говорили, что далее речь пойдет о разделяемых ресурсах, доступ к которым может осуществляться со стороны произвольных процессов, в общем случае, в произвольном порядке. Эти ресурсы доступны любому процессу, а процессы не обязательно должны быть родственными. При наличии такой схемы возникают две принципиальные проблемы: Именование; Синхронизация;
Проблемы именования связаны с тем, что родственных связей нет и по наследству передать ничего нельзя. Если проблема именования решена, то возникает проблема синхронизации доступа - как организовать обмен с ресурсами, чтобы этот обмен был корректным. Если у нас есть, например, ресурс “оперативная память”, то когда один процесс еще не дописал информацию, а другой процесс уже прочитал весь блок, то возникает некорректная ситуация. Решения этих проблем мы и будем рассматривать.
Проблема именования решается за счет ассоциирования с каждым ресурсом некоторого ключа. В общем случае это целочисленное значение. То есть при создании разделяемого ресурса его автор приписывает ему номер и определяет права доступа к этому ресурсу. После этого любой процесс, который укажет системе, что он хочет общаться с разделяемым ресурсом с ключом N, и обладает необходимыми правами доступа, будет допущен для работы с этим ресурсом. Однако такое решение не является идеальным, так как вполне возможна коллизия номеров - когда совпадают номера разделяемых ресурсов. В этом случае процессы будут путаться, что неизбежно приведет к ошибкам. Поэтому в системе предусмотрено стандартное средство генерации уникальных ключей. Для генерации уникального ключа используется функция ftok
#include #include key_t ftok(char *s, char c);
Суть ее действия - по текстовой строке и символу генерируется уникальное для каждой такой пары значение ключа. После этого сгенерированным ключом можно пользоваться как для создания ресурса, так и для подтверждения использования ресурса. Более того, для исключения коллизий, рекомендуется указывать в качестве параметра "указателя на строку" путь к некоторому своему файлу. Второй аргумент - символьный, который позволяет создавать некоторые варианты ключа, связанного с этим именем, этот аргумент называется проектом (project). При таком подходе можно добиться отсутствия коллизий. Давайте посмотрим конкретные средства работы с разделяемыми ресурсами.
Разделяемая память. Общая схема работы с разделяемыми ресурсами такова - есть некоторый процесс-автор, создающий ресурс с какими-либо параметрами. При создании ресурса разделяемой памяти задаются три параметра - ключ, права доступа и размер области памяти. После создания ресурса к нему могут быть подключены процессы, желающие работать с этой памятью. Соответственно, имеется действие подключения к ресурсу с помощью ключа, который генерируется по тем же правилам, что и ключ для создания ресурса. Понятно, что здесь имеется момент некоторой рассинхронизации, который связан с тем, что потребитель разделяемого ресурса (процесс, который будет работать с ресурсом, но не является его автором) может быть запущен и начать подключаться до запуска автора ресурса. В этой ситуации особого криминала нету, так как имеются функции управления доступом к разделяемому ресурсу, с использованием которых можно установить некоторые опции, определяющие правила работы функций, взаимодействующих с разделяемыми ресурсами. В частности, существует опция, заставляющая процесс дождаться появления ресурса. Это также, может быть, не очень хорошо, например, автор может так и не появиться, но другого выхода нету, это есть некоторые накладные расходы. Вот в общих словах - что есть что. Давайте рассмотрим те функции, которые предоставляются нам для работы с разделяемыми ресурсами.
Первая функция - создание общей памяти. int shmget (key_t key, int size, int shmemflg); key - ключ разделяемой памяти size - размер раздела памяти, который должен быть создан shmemflg - флаги
Данная функция возвращает идентификатор ресурса, который ассоциируется с созданным по данному запросу разделяемым ресурсом. То есть в рамках процесса по аналогии с файловыми дескрипторами каждому разделяемому ресурсу определяется его идентификатор. Надо разделять ключ - это общесистемный атрибут, и идентификатор, используя который мы работаем с конкретным разделяемым ресурсом в рамках процесса. С помощью этой функции можно как создать новый разделяемый ресурс “память” (в этом случае во флагах должен быть указан IPC_CREAT)?, а также можно подключиться к существующему разделяемому ресурсу. Кроме того, в возможных флагах может быть указан флаг IPC_EXECL, он позволяет проверить и подключиться к существующему ресурсу - если ресурс существует, то функция подключает к нему процесс и возвращает код идентификатора, если же ресурс не существует, то функция возвращает -1 и соответствующий код в errno.
Следующая функция - доступ к разделяемой памяти: char *shmat(int shmid, char *shmaddr, int shmflg); shmid - идентификатор разделяемого ресурса
Текущая страница: 1
|
|
|
|
|
|
|
|
|
|