Чтение онлайн

ЖАНРЫ

Искусство программирования для Unix
Шрифт:

Общая память может быть представлена различными API-интерфейсами, но в современных Unix-системах реализация обычно зависит от использования функции ттар(2) для отображения файлов в общую память. В стандарте POSIX определяется средство shm_open(3) с API-интерфейсом, поддерживающим использование файлов в качестве общей памяти. Данная функция, главным образом, предоставляет операционной системе возможность не сбрасывать на диск данные псевдофайла.

Так как доступ к общей памяти автоматически не сериализуется в каком-либо порядке, подобном вызовам чтения и записи, программы с общей памятью должны обрабатывать проблемы конфликтов и взаимоблокировок самостоятельно, обычно путем использования семафоров, находящихся в совместно используемом сегменте. В данном случае возникают

проблемы, подобные проблемам мультипроцессной обработки (их обсуждение приведено в конце данной главы), но они являются более управляемыми, так как по^умолчанию программы не используют общую память. Поэтому проблемы становятся более контролируемыми.

В системах, где это доступно и надежно работает, средство учета (scoreboard facility) Web-сервера Apache применяет общую память для обмена данными между главным процессом Apache и пулом распределения нагрузки образов Apache, которыми он управляет. В современных реализациях системы X также применяется общая память для передачи больших образов между клиентом и сервером, когда они находятся в памяти одной машины. В данном случае эта методика применяется для того, чтобы избежать издержек связи с использованием сокетов. Оба варианта применения представляют собой средство повышения производительности, обоснованное скорее опытом и тестами, чем архитектурным выбором.

Вызов ттар(2) поддерживается во всех современных Unix-системах, включая Linux и версии BSD с открытым исходным кодом. Он описан в единой спецификации Unix (Single Unix Specification). Обычно он недоступен в Windows, классической MacOS и других операционных системах.

До того как появилась специализированная функция ттар(2), общим способом сообщения двух процессов было открытие одного и того же файла и последующее удаление данного файла. Файл не удалялся до тех пор, пока не были закрыты все открытые дескрипторы данного файла, но некоторые старые Unix-системы использовали обнуление счетчика ссылок как указание на то, что обновление дисковой копии файла можно прекратить. Недостатком в этом случае было то, что вспомогательным запоминающим устройством была файловая система, а не устройство подкачки. Отключить файловую систему, на которой находился удаляемый файл, было невозможно до тех пор, пока не были закрыты использующие его программы, а подключение новых процессов к существующему сегменту общей памяти, выполненное таким способом, было в лучшем случае сложным.

После появления версии 7 и разделения ветвей BSD и System V эволюция межпроцессного взаимодействия в Unix стала развиваться в двух различных направлениях. Направление BSD привело к появлению сокетов. С другой стороны, ветвь AT&T развивала именованные каналы (как было сказано ранее) и IPC-средство, специально предназначенное для передачи двоичных данных и основанное на двунаправленных очередях сообщений в общей памяти. Это направление называется "System V IPC" или "Indian Hill IPC" (среди профессионалов прежней школы).

Верхний уровень System V IPC, уровень передачи сообщений, почти совершенно вышел из употребления. Нижний уровень, состоящий из общей памяти и семафоров, до сих пор находит широкое применение в условиях, когда необходимо выполнять блокировку с взаимным исключением и некоторое совместное использование глобальных данных между процессами, запущенными на одной машине. Данные средства общей памяти в System V развились в API с общей памятью стандарта POSIX, поддерживаемого в Linux, различных версиях BSD, MacOS X и Windows, но не в классической MacOS.

Используя данные средства общей памяти и семафоров (shmget(2), semget(2) и им подобные), можно избежать издержек копирования данных через сетевой стек. Данная техника интенсивно используется в крупных коммерческих базах данных (включая Oracle, DB2, Sybase р Informix).

7.3. Проблемы и методы, которых следует избегать

Несмотря на то, что BSD-сокеты через TCP/IP стали доминирующим IPC-методом в Unix, до сих пор продолжаются оживленные споры по поводу правильного способа разделения программ средствами мультипрограммирования. Некоторые устаревшие методы еще окончательно не умерли, а из других операционных систем заимствуются некоторые методики с сомнительной эффективностью (часто

в связи с обработкой графики или программированием GUI-интерфейсов). Ниже рассматриваются некоторые небезопасные альтернативы.

7.3.1. Устаревшие IPC-методы в Unix

Операционная система Unix (созданная в 1969 году) предшествовала протоколу TCP/IP (появившемуся в 1980 году) и повсеместному распространению сетей позднее в 90-х годах прошлого века. Неименованные каналы, перенаправление и вызовы с созданием подоболочки были характерны для Unix с ранних дней ее существования, однако история Unix изобилует отжившими API-интерфейсами, связанными с устаревшими IPC-методами и сетевыми моделями, начиная со средства шх , которое появилось в версии 6 (1976) и было отклонено до выхода версии 7 (1979).

В конечном итоге BSD-сокеты победили, когда IPC-механизм объединился с сетью. Однако это случилось только после 15 лет исследований, которые оставили за собой множество пережитков. Знать о них полезно, поскольку в Unix-документации, вероятно, найдутся ссылки на них, которые могут создать ошибочное мнение о том, что данные методы все еще используются. Более подробно эти устаревшие методы описываются в книге "Unix Network Programming" [80].

Действительным оправданием для всех "мертвых" IPC-средств в старых Unix-сис-темах ветви AT&T была политика. Группу поддержки Unix (The Unix Support Group) возглавлял менеджер низкого уровня, тогда как некоторыми проектами, в которых использовалась Unix, руководили вице-президенты. У них были возможности создавать непреодолимые запросы, и они не потерпели бы возражения, что большинство IPC-механизмов являются взаимозаменяемыми.

Дуг Макилрой.

7.3.1.1. System V IPC

Средства System V IPC — средства передачи сообщений, основанные на имеющихся в System V возможностях общей памяти, которые были описаны ранее.

Программы, взаимодействующие с помощью System V IPC, обычно определяют общие протоколы, основанные на обмене короткими (до 8 Кб) двоичными сообщениями. Соответствующие справочные руководства доступны для msgctl(2) и подобных функций. Поскольку данный стиль был почти полностью вытеснен текстовыми протоколами передачи данных между сокетами, примеры этой методики здесь не предоставляются.

Средства System V IPC присутствуют в Linux и других Unix-системах. Однако, поскольку они являются устаревшими, но используются не очень часто. Известно, что Linux-версия до середины 2003 года имела ошибки. Очевидно, никто не заботится об их исправлении.

7.3.1.2. Потоки

Потоки (streams) сетевого взаимодействия были разработаны Деннисом Ритчи для Unix Version 8 (1985). Их новая реализация называется STREAMS (именно так, в документации все буквы прописные). Впервые она стала доетупной в версии 3.0 System V Unix (1986). Средство STREAMS обеспечивало дуплексный интерфейс (функционально не отличавшийся от BSD-сокетов, и подобно сокетам доступ к нему осуществлялся посредством обычных операций read(2) и write(2) после первоначальной установки) между пользовательским процессом и указанным драйвером устройства в ядре. Драйвер устройства мог быть аппаратным, таким как последовательная или сетевая плата, или исключительно программным псевдоустройством, установленным для передачи данных между пользовательскими процессами.

Интересной особенностью потоков и средства STREAMS54 является то, что модули трансляции протокола можно внести в путь обработки ядра, так что данные устройства, используемого пользовательским процессом, проходя через дуплексный канал, фактически фильтруются. Данную возможность можно использовать, например, для реализации протокола построчного редактирования для терминального устройства. Также можно было бы реализовать такие протоколы, как IP или TCP, не встраивая их непосредственно в ядро.

Поделиться с друзьями: