Работа с базами данных - это будничный труд большинства программистов. Язык Perl помогает им в этом, предоставляя удобные средства доступа ко всем распространенным СУБД, настольным базам данных и многим экзотическим источникам данных.
Лекция 16. Взаимодействие процессов
В этой лекции обсуждаются вопросы выполнения программ в многозадачной среде: пользовательские программы запускают на выполнение внешние программы, программы могут порождать параллельно выполняемые процессы, в рамках выполняемой программы может быть запущено несколько потоков управления. Все эти модели программирования поддерживаются языком Perl и будут рассмотрены в этой лекции.
Цель лекции: познакомиться со средствами языка Perl, связанными с межпроцессным взаимодействием, и научиться применять их при разработке собственных программ на языке Perl, выбирая наиболее подходящую из моделей параллельного программирования.
Современные операционные системы в том или ином виде поддерживают многозадачность (multitasking) даже на однопроцессорных компьютерах, не говоря уже о многопроцессорных системах. Операционная система (ОС) производит запуск системных и пользовательских программ в виде независимых процессов (process), выделяя для каждого из них отдельный участок оперативной памяти и другие ресурсы. Каждый процесс нумеруется своим уникальным числовым идентификатором процесса (Рrocess Identifier, PID). Специальные модули ядра операционной системы организуют переключение процессора на обслуживание выполняющихся программ, оптимизируя распределение между ними процессорного времени. При этом работающие процессы могут инициировать выполнение других процессов, порождать зависимые подпроцессы (subprocess) в отдельной области памяти или запускать подпроцессы в области памяти основного процесса. Примерами программ, основанных на использовании подпроцессов, могут служить различные серверные программы: почтовые и web-серверы, серверы приложений и баз данных.
Во время выполнения процессы могут взаимодействовать между собой различными способами. Они могут иметь доступ к разделяемой области памяти, организовывать программные каналы (pipe), посылать друг другу сигналы (signal), обмениваться данными через сокеты, совместно использовать файлы и применять другие средства межпроцессного взаимодействия (Inter-Process Communication, IPC). При этом часто один процесс ожидает окончания выполнения каких-либо действий в другом процессе: про такую ситуацию говорят, что процессы выполняются синхронно (synchronous), то есть согласованно. В других случаях требуется, чтобы процессы выполнялись асинхронно (asynchronous), то есть одновременно и независимо друг от друга. В определенный момент процесс может перейти от асинхронного выполнения к синхронному, то есть перейти в ожидание для синхронизации с другим процессом.
Реализация этих механизмов сильно зависит от конкретной операционной системы, поэтому некоторые стандартные средства языка Perl, связанные с управлением процессами, ориентированы на работу в определенном операционном окружении. Кроме того, имеются специализированные Perl-модули для работы с процессами в операционных системах, соответствующих стандарту POSIX, или в ОС MS Windows. Конечно, в этой лекции нам удастся обсудить только основные средства языка Perl, касающиеся обширной темы межпроцессного взаимодействия. Приводимые примеры намеренно сделаны максимально простыми, чтобы продемонстрировать основные подходы к управлению процессами, избегая особенностей, которыми изобилует многозадачное программирование.
В Perl имеется операция выполнения программы, которая обозначается обратными апострофами (backticks) или синонимом - конструкцией qx(), упоминавшейся в лекции 7. Она предназначена для получения результатов выполнения внешней программы. Эта операция пытается выполнить любую внешнюю программу, ожидает окончания ее работы и возвращает то, что программа выводит в свой поток стандартного вывода. Например, так в операционных системах Linux или MS Windows можно выполнить команду dir, выводящую список файлов в текущем каталоге:
my $file_list = `dir`; # в скалярном контексте
my @file_list = qx(dir); # в списочном контексте
В зависимости от того, в каком контексте - скалярном или списочном - употребляется операция выполнения программы, результат работы внешней программы рассматривается как одна строка или как список строк.