Реймонд Эрик Стивен
Шрифт:
Следовательно, в обсуждении данных проблем основное внимание уделено видам логики протоколов, каждый из которых программист свободно использует для каждого вида межпроцессного взаимодействия.
7.1. Отделение контроля сложности от настройки производительности
Прежде всего, необходимо избавиться от некоторых ложных целей. В данной главе обсуждение не касается использования одновременных операций для повышения производительности. Рассмотрение этой идеи до того как будет сформулирована ясная структура, которая сводит к минимуму глобальную сложность, является преждевременной оптимизацией, т.е. корнем всех зол (дальнейшее обсуждение приведено в главе 12).
Близкой ложной целью являются параллельные процессы (threads) (т.е. множество одновременно выполняемых процессов, совместно использующих одно адресное пространство памяти). Использование параллельных процессов — средство повышения производительности. Для того чтобы не уходить далеко от основной линии обсуждения, данная методика более подробно рассматривается в конце данной главы. Здесь достаточно сделать обобщение: параллельные процессы не уменьшают глобальную сложность, а скорее увеличивают ее, и поэтому следует избегать их использования, кроме случаев крайней необходимости.
С другой стороны, соблюдение правила модульности не является ложной целью, поскольку модульность позволяет упростить программы и, следовательно, работу программиста. Все причины для разделения процессов являются продолжением причин для разделения модулей, которое рассматривалось в главе 4.
Другой важной причиной разбиения программ на взаимодействующие процессы является повышение безопасности. В операционной системе Unix программы, которые запускаются обычными пользователями, но должны иметь доступ к важным с точки зрения безопасности системным ресурсам, получают такой доступ с помощью функции setuid [64] . Исполняемые файлы представляют собой наименьший элемент кода, который может содержать setuid-бит. Следовательно, каждая строка кода в исполняемом setuid-файле должна быть "благонадежной". (Вместе с тем хорошо написанные setuid-программы, сначала предпринимают все необходимые привилегированные действия, а на последующих этапах своей работы понижают свои привилегии до уровня пользователя.)
64
setuid-программа выполняется не с привилегиями вызвавшего ее пользователя, а с привилегиями владельца исполняемого файла. Эту особенность можно использовать для предоставления ограниченного, программно-управляемого доступа к таким элементам, как файлы паролей, непосредственное изменение которых должно быть разрешено только администраторам.
Обычно привилегии setuid-программы требуются для выполнения ею одной или нескольких операций. Часто имеется возможность разбить такую программу на взаимодействующие процессы: мелкий, не требующий использования функции setuid, и более крупный, который в ней не нуждается. Если такое разделение возможно, то "благонадежным" должен быть только код в меньшей программе. В значительной степени благодаря подобному разделению и делегированию функций, операционная система Unix обладает большими достижениями в обеспечении безопасности [65] , чем ее конкуренты.
65
То есть, лучшие достижения, выраженные в количестве прорывов безопасности относительно общего времени работы в Internet.
7.2. Классификация IPC-методов в Unix
Как и в однопроцессных структурах программ, простейшая организация является наилучшей. В оставшейся части данной главы представлены IPC-методики приблизительно в порядке возрастания сложности их программирования. Прежде чем использовать более сложные методики; следует с помощью прототипов и эталонных тестов получить доказательства того, что простые методики не подходят. Такой подход часто приводит к поразительным результатам.
7.2.1. Передача задач специализированным программам
В простейшей форме взаимодействия программ, которая возможна благодаря малозатратному созданию дочерних процессов, одна программа вызывает другую для решения специализированной задачи. Поскольку вызванная программа часто задается как команда оболочки Unix через вызов system(3), данная операция часто называется вызовом программы с созданием подоболочки (shelling out). Вызываемая программа наследует управление клавиатурой и пользовательским дисплеем и выполняется до завершения. Когда она прекращает свою работу, вызывающая программа возобновляет управление клавиатурой и дисплеем и продолжает выполнение [66] . Поскольку вызывающая программа не обменивается данными с вызванной программой во время работы последней, конструкция протокола не является проблемой при таком виде взаимодействия, кроме очевидного случая, при котором вызывающая программа может для изменения поведения вызванной программы передать ей аргументы командной строки.
66
Распространенная ошибка в программировании с созданием подоболочек заключается в том, что программист забывает блокировать сигналы в родительском процессе при работающем подпроцессе. Без такой предосторожности прерывание подпроцесса может иметь нежелательные побочные эффекты для родительского процесса.
Классическим случаем вызова с созданием подоболочки в Unix является вызов редактора из программы чтения почты или новостей. Разработчик, придерживающийся традиций Unix, не встраивает специально созданный редактор в программу, которая требует обычного текстового ввода. Вместо этого программист предоставляет пользователю возможность указать предпочтительный редактор, который будет вызываться при необходимости.
Специализированная программа обычно сообщается с родительским процессом через файловую систему, считывая или модифицируя файл (или файлы) с определенным расположением. Так работают вызываемые редакторами и почтовыми агентами программы.
В распространенном варианте данной модели специализированная программа может получать данные на свой стандартный ввод и вызываться с помощью функции C-библиотеки