Искусство программирования для Unix
Шрифт:
7.2. Классификация IPC-методов в Unix
Как и в однопроцессных структурах программ, простейшая организация является наилучшей. В оставшейся части данной главы представлены IPC-методики приблизительно в порядке возрастания сложности их программирования. Прежде чем использовать более сложные методики; следует с помощью прототипов и эталонных тестов получить доказательства того, что простые методики не подходят. Такой подход часто приводит к поразительным результатам.
7.2.1. Передача задач специализированным программам
В простейшей форме взаимодействия программ, которая возможна благодаря малозатратному созданию дочерних процессов, одна программа вызывает другую для решения специализированной задачи. Поскольку вызванная
66
Распространенная ошибка в программировании с созданием подоболочек заключается в том, что программист забывает блокировать сигналы в родительском процессе при работающем подпроцессе. Без такой предосторожности прерывание подпроцесса может иметь нежелательные побочные эффекты для родительского процесса.
Классическим случаем вызова с созданием подоболочки в Unix является вызов редактора из программы чтения почты или новостей. Разработчик, придерживающийся традиций Unix, не встраивает специально созданный редактор в программу, которая требует обычного текстового ввода. Вместо этого программист предоставляет пользователю возможность указать предпочтительный редактор, который будет вызываться при необходимости.
Специализированная программа обычно сообщается с родительским процессом через файловую систему, считывая или модифицируя файл (или файлы) с определенным расположением. Так работают вызываемые редакторами и почтовыми агентами программы.
В распространенном варианте данной модели специализированная программа может получать данные на свой стандартный ввод и вызываться с помощью функции C-библиотеки
Ключевым моментом во всех описанных случаях является то, что специализированные программы во время работы не обмениваются данными с родительскими. Они имеют связанный протокол только в том случае, когда какая-либо программа (главная или подчиненная), принимающая ввод от другой, должна быть способна осуществлять синтаксический анализ ввода.
7.2.1.1. Учебный пример: пользовательский почтовый агент mutt
Пользовательский почтовый агент mutt является современным представителем наиболее важной традиции проектирования программ для обработки электронной почты в Unix. Данная программа имеет простой экранный интерфейс с одноклавишными командами для просмотра и чтения почты.
Если mutt используется для создания почтовых сообщений (либо если данная программа вызвана с адресом в качестве аргумента командной строки или с помощью
67
По сути, это излишнее упрощение. Дополнительная информация представлена при обсуждении переменных
Данное соглашение в Unix соблюдается почти во всех программах создания почтовых сообщений и сообщений в группах новостей. И вследствие этого программистам, реализующим такие программы, не требуется писать сотни неизбежно различающихся редакторов, а пользователям не требуется изучать сотни различных интерфейсов. Вместо этого пользователи могут использовать с такими программами предпочтительные редакторы.
Важным вариантом такой стратегии является вызов с созданием подоболочки небольшой программы-посредника, передающей специальное задание уже запущенному экземпляру большой программы, такой как редактор или Web-браузер. Поэтому разработчики, на X-дисплеях которых обычно уже имеется запущенный экземпляр редактора emacs, могут установить переменную
7.2.2. Каналы, перенаправление и фильтры
После Кена Томпсона и Денниса Ритчи одной из наиболее важных фигур в истории создания Unix был, вероятно, Дуг Макилрой. Созданная им конструкция канала (pipe) в той или иной форме влияла на конструкцию операционной системы Unix, поддерживая зарождающуюся в ней философию "хорошего решения одной задачи" и способствуя большинству более поздних форм IPC в Unix (в частности, абстракции сокетов, применяемой для поддержки сетей).
Работа каналов определяется соглашением, согласно которому каждая программа изначально имеет доступные ей (по крайней мере) два потока данных ввода-вывода: стандартный ввод и стандартный вывод (числовые дескрипторы файлов 0 и 1 соответственно). Многие программы могут быть написаны в виде фильтров (filters), которые последовательно считывают данные со стандартного ввода и записывают только в стандартный вывод.
Обычно такие потоки подключены к пользовательской клавиатуре и дисплею соответственно. Однако оболочки в операционной системе Unix обеспечивают универсальную поддержку операций перенаправления (redirection), которые подключают стандартный ввод и стандартный вывод к файлам. Поэтому команда
отправляет вывод команды ls(1) в файл с именем "foo". С другой стороны, команда
вынуждает утилиту для подсчета слов wc(1) принять на свой стандартный ввод данные из файла "foo" и отправить сведения о количестве символов/слов/строк на стандартный вывод.
Канал подключает стандартный вывод одной программы к стандартному вводу другой. Цепочка программ, соединенных таким способом, называется конвейером (pipeline). Команда