Linux API – Введение в межпроцессное взаимодействие
Статья из серии "Программирование для Linux", журнал Linux Format
,
журнал Linux Format
Наличие в Unix-системах простых и эффективных средств взаимодействия между процессами оказало программирование в Unix не менее важное влияние, чем представление объектов системы в виде файлов. Благодаря межпроцессному взаимодействию (Inter-Process Communication, IPC) разработчик (и пользователь) может разбить решение сложной задачи на несколько простых операций, каждая из которых доверяется отдельной небольшой программе. Последовательная обработка одной задачи несколькими простыми программами очень похожа на конвейерное производство (среди многих значений английского pipeline есть и «конвейер», но в этой статье мы для перевода слова pipe будем пользоваться принятым в отечественной литературе термином «канал» []. Альтернативой конвейерному подходу являются большие монолитные пакеты, построенные по принципу «все в одном». Использование набора простых утилит для решения одной сложной задачи требует несколько большей квалификации со стороны пользователя, но взамен предоставляет гибкость, не достижимую при использовании монолитных «монстров». Наборы утилит, использующих открытые протоколы IPC, легко наращивать и модифицировать. Разбиение сложных задач на сравнительно небольшие подзадачи также позволяет снизить количество ошибок, допускаемых программистами (см. ). Помимо всего этого у IPC есть еще одно важное преимущество. Программы, использующие IPC, могут «общаться» друг с другом практически также эффективно, как и с пользователем, в результате чего появляется возможность автоматизировать выполнение сложных задач. Могущество скриптовых языков Unix и Linux во многом основано на возможностях IPC.
Закон Брукса
Фредерик Брукс, автор книги «Мифический человеко-месяц», высказал предположение (известное как «закон Брукса»), что количество ошибок в проекте должно быть пропорционально квадрату числа участников проекта, тогда как объем полезной работы при увеличении числа участников проекта растет линейно. Закон Брукса означал, что на определенном этапе развития проекта любая попытка привлечь к разработке новых программистов приводит лавинообразному росту числа ошибок (а значит все больше и больше работы требуется на их выявление и исправление). Если бы закон Брукса выполнялся, то для всех проектов существовал бы верхний порог сложности, при попытке превысить который КПД разработки начинал бы стремительно падать. Что же касается открытой модели разработки ПО, то она, с точки зрения закона Брукса, была бы невозможна в принципе. Для того, чтобы понять, в чем Ф. Брукс ошибался, следует рассмотреть исходные посылки его рассуждений. Закон Брукса основан двух предположениях (а) ошибки чаще возникают на стыке элементов проекта, выполняемых разными разработчиками (соответственно, чем больше таких «швов», тем больше ошибок); (б) модель взаимодействия разработчиков представляет собой полный граф (то есть, каждый разработчик взаимодействует со всеми остальными участниками проекта), число ребер которого пропорционально квадрату числа вершин. Ни то, ни другое утверждение, вообще говоря, неверно. В частности, при программировании «канальных» утилит всем участникам проекта нет надобности непосредственно контактировать между собой. Каждая группа разработчиков должна следовать только фиксированному протоколу обмена данными между программами, так что в этом случае число ошибок подчиняется линейной, а не квадратичной, зависимости.
В этой статье мы ограничимся рассмотрением IPC с помощью каналов различных типов. Предполагается, что читатели статьи являются опытными пользователями Linux, и, во всяком случае, знают, как создаются каналы из нескольких программ с помощью командной строки. С точки зрения программиста работа, программ в канале, организованном с помощью символа “|”, выглядит очень просто. Данные со стандартного потока вывода одной программы перенаправляются на стандартный поток ввода другой программы, чей стандартный поток вывода может быть также перенаправлен. Но как быть в том случае, если необходимо использовать канал внутри самой программы?