Скачиваний:
56
Добавлен:
08.01.2014
Размер:
2.6 Mб
Скачать

Глава 8. Дополнительные методы межпроцессного взаимодействия

8.1. Введение

Используя средства из глав 6 и 7, можно осуществить основные взаимодействия между процессами. В этой главе рассматриваются усовершенствованные средства межпроцессного взаимодействия, которые позволят использовать более сложные методы программирования.

Первая и наиболее простая тема данной главы – блокировка записей (record locking), которая фактически является не формой прямого межпроцессного взаимодействия, а скорее – методом координирования работы процессов. Блокировка позволяет процессу временно резервировать часть файла для исключительного использования при решении некоторых сложных задач управления базами данных. Здесь стоит сделать предупреждение: спецификация XSI определяет блокировку записей как рекомендательную (advisory), означающую, что она не препятствует непосредственному выполнению операций файлового ввода/вывода, а вся ответственность за проверку установленных блокировок полностью ложится на процесс.1

Другие механизмы межпроцессного взаимодействия, обсуждаемые в этой главе, являются более редкими. В общем случае эти средства описываются как средства IPC (IPC facilities, где сокращение IPC означает inter-process communication – межпроцессное взаимодействие) и включены в одноименный модуль. Этот общий термин подчеркивает общность их применения и структуры, хотя существуют три определенных типа таких средств:

  • очереди сообщений (message passing). Они позволяют процессу посылать и принимать сообщения, под которыми понимается произвольная последовательность байтов или символов;

  • семафоры (semaphores). По сравнению с очередями сообщений семафоры представляют собой низкоуровневый метод синхронизации процессов, малопригодный для передачи больших объемов данных. Их теория берет начало из работ Дейкстры (Е.W. Dijkstra, 1968);

  • разделяемая память (shared memory). Это средство межпроцессного взаимодействия позволяет двум и более процессам совместно использовать данные, содержащиеся в определенных сегментах памяти. Естественно, обычно данные процесса являются недоступными для других процессов. Этот механизм обычно является самым быстрым механизмом межпроцессного взаимодействия.2

8.2. Блокировка записей

8.2.1. Мотивация

На первом этапе стоит рассмотреть простой пример демонстрации того, почему блокировка записей необходима в некоторых ситуациях.

Примером будет служить известная корпорация ACME Airlines, использующая ОС UNIX в своей системе заказа билетов. Она имеет два офиса, А и В, в каждом из которых установлен терминал, подключенный к компьютеру авиакомпании. Служащие компании используют для доступа к базе данных, реализованной в виде обычного файла UNIX, программу acmebook. Эта программа позволяет пользователю выполнять чтение и обновление базы данных. В частности, служащий может уменьшить на единицу число свободных мест при заказе билета на определенный авиарейс.

Предположим теперь, что осталось всего одно свободное место на рейс АСМ501 в Лондон, и миссис Джонс входит в офис А; в то же самое время мистер Смит входит в офис В, и они оба заказывают место на рейс АСМ501. При этом возможна такая последовательность событий:

  1. Служащий офиса А запускает программу acmebook. Назовем стартовавший процесс РА.

  2. Сразу же после этого служащий в офисе В также запускает программу acmebook. Назовем этот процесс РВ.

  3. Процесс РА считывает соответствующую часть базы данных при помощи системного вызова fdread и определяет, что осталось всего одно свободное место.

  4. Процесс РВ выполняет чтение из базы данных сразу же после процесса РА и также определяет, что осталось одно свободное место на рейс АСМ501.

  5. Процесс РА обнуляет счетчик свободных мест для рейса при помощи системного вызова fdwrite, изменяя соответствующую часть базы данных. Служащий в офисе А вручает билет миссис Джонс.

  6. Сразу же вслед за этим процесс РВ также выполняет запись в базу данных, также записывая нулевое значение в счетчик свободных мест. Но на этот раз значение счетчика ошибочно – на самом деле оно должно было бы быть равно -1, то есть хотя процесс РА уже обновил базу данных, процесс РВ не знает об этом и спешит выполнить заказ, как если бы место было свободно. Вследствие этого мистер Смит также получит билет, и на самолет будет продано больше билетов, чем число свободных мест в нем.

Эта проблема возникает из-за того, что несколько процессов могут одновременно обращаться к файлу UNIX. Комплексная операция с данными файла, состоящая из нескольких вызовов fdseek, fdread и fdwrite, может быть выполнена двумя или более процессами одновременно, и это, как показывает наш простой пример, будет иметь непредвиденные последствия.

Одно из решений состоит в том, чтобы разрешить процессу выполнить блокировку (lock) части файла, с которой он работает. Блокировка, которая нисколько не изменяет содержимое файла, показывает другим процессам, что данные, о которых идет речь, уже используются. Это предотвращает вмешательство другого процесса во время последовательности дискретных физических операций, образующих одну комплексную операцию, или транзакцию. Этот механизм часто называют блокировкой записи (record locking), где запись означает просто произвольную часть файла. Для обеспечения корректности сама операция блокировки должна быть атомарной, чтобы она не могла пересечься с параллельной попыткой блокировки в другом процессе.

Для обеспечения нормальной работы блокировка должна выполняться централизованно. Возможно, лучше всего это возложить на ядро, хотя пользовательский процесс, выступающий в качестве агента базы данных, также может служить для этой цели. Блокировка записей на уровне ядра может выполняться при помощи уже известного нам вызова fcntl.

Обратите внимание, что возможен также альтернативный способ блокировки записей – при помощи процедуры lockf. Этот подход все еще встречается во многих системах – за дополнительными сведениями следует обратиться к справочному руководству системы.

Соседние файлы в папке Полищук, Семериков. Системное программирование в UNIX средствами Free Pascal