Программирование на Visual C++. Архив рассылки - Алекс Jenter
Шрифт:
Интервал:
Закладка:
Введение
Любая операционная система была бы весьма ущербна, если бы замыкала выполняющееся приложение в собственном темном мирке без окон и дверей, без какой-либо возможности сообщить другим программам какую-либо информацию. Если посмотреть внимательно, можно заметить, что далеко не все приложения являются самодостаточными. Очень многим, если не большей части, требуется информация от других приложений, либо они должны эту информацию сообщать. Именно поэтому в операционную систему встраивается множество механизмов, которые обеспечивают т.н. Interproccess Communication (IPC) – то есть межпроцессное взаимодействие.
В историческом плане сначала появилась необходимость в общении процессов, выполняющихся на одном компьютере. В дальнейшем с бурным развитием сетевых технологий все острее стала чувствоваться потребность в средствах для взаимодействия процессов, выполняющихся на разных компьютерах в сети. Особенно трудна такая задача, если это компьютеры на базе разных платформ и/или с разными операционными системами.
Рассмотрим подробнее несколько ключевых примеров, демонстрирующих важность IPC. Вам, возможно это покажется неправдоподобным, но зачатки IPC существовали еще в MS-DOS – и это несмотря на то, что MS-DOS при всем желании трудно назвать многозадачной средой. В самом деле, когда вы в командной строке вводили подобную инструкцию:
C:>DIR|MORE
происходило следующее: выполнялась команда DIR и ее вывод записывался во временный текстовый файл. После этого содержимое файла подавалось на вход команды MORE. В результате вы получали листинг каталогов, который в случае большого количества каталогов не уезжал мгновенно за экран, а мог скроллироваться с помощью клавиши Enter. Конечно же это очень примитивный IPC, но его наличие показывает, что уже тогда такой механизм был востребован и в какой-то мере реализован.
Примеры использования IPC охватывают гораздо большее количество программ и приложений, чем вы скорее всего думаете. Когда вы выходите в интернет, ваш браузер – одна программа (процесс) – взаимодействует с web-сервером – другой программой (процессом). Эти программы выполняются на разных компьютерах; браузер на вашем, сервер – где-то еще. И вас не волнует, какая ОС установлена на сервере и какая там платформа.
Или, например, вы работаете с удаленной базой данных. Ваше клиентское приложение – это один процесс, на сервере базы данных запущен другой процесс. Процесс на сервере выполняет запросы к БД, поступающие от вашего процесса.
ПРИМЕЧАНИЕ
Вообще, для сетевых форм IPC (но не обязательно только для них) очень часто используется концепция "клиент-сервер". Как вы понимаете, "клиент" – это приложение, которому требуются данные, "сервер" – приложение, предоставляющее данные.
А если брать только взаимодействие программ, выполняющихся на одном компьютере, самым банальным примером будет следующий: текст из вашего текcтового редактора передается в электронную таблицу или программу для верстки. Да-да, наш старый знакомый буфер обмена – это тоже один из механизмов IPC!
И еще можно было бы привести очень много примеров.
Средств, обеспечивающих взаимодействие между процессами, создано достаточно много. Огромное их количество реализовано в Windows 9x, еще больше – в Windows NT/2000. Теперь нужно приличное количество времени, чтобы хотя бы познакомиться со всеми! Замечу, что нет, и наверное в принципе не может быть универсального способа обмена данными, который годился бы на все случаи жизни – все равно в некоторых случаях использование другого способа будет предпочтительнее. Но я надеюсь, что после прочтения этой статьи вы сможете достаточно уверенно ориентироваться в мире IPC и обоснованно выбирать тот или иной метод.
Тот факт, что механизмы IPC работают на уровне операционной системы, положительно сказывается на скорости и надежности программ и программных комплексов, построенных с их использованием. Эффективность приложений соответственно возрастает.
Вообще, правильнее было бы называть эти механизмы "Interthread Communication" – межпотоковое взаимодействие. Если вы помните, выполняются именно потоки, они же и обмениваются данными. Однако, смысл для отдельных механизмов взаимодействия появляется только в том случае, если эти потоки принадлежат разным процессам. Ведь потоки, выполняющиеся в рамках одного процесса, вовсе не нуждаются в дополнительных средствах для общения между собой. Так как они разделяют одно адресное пространство, обмен данными могут обеспечить обычные переменные. Таким образом, IPC становится необходим в том случае, если поток одного процесса должен передать данные потоку другого процесса.
Теперь давайте рассмотрим основные виды IPC и случаи, в которых они используются.
Буфер обмена (clipboard)
Это одна из самых примитивных и хорошо известных форм IPC. Он появился еще в самых ранних версиях Windows. Основная его задача – обеспечивать обмен данными между программами по желанию и под контролем пользователя. Впрочем, вы наверняка сами неплохо знаете, как используется буфер обмена… ;-) Не рекомендуется использовать его для внутренних нужд приложения, и не стоит помещать туда то, что не предназначено для прямого просмотра пользователем.
Сообщение WM_COPYDATA
Стандартное сообщение для передачи участка памяти другому процессу. Работает однонаправленно, принимающий процесс должен расценивать полученные данные как read only. Посылать это сообщение необходимо только с помощью SendMessage, которая (напомню) в отличие от PostMessage ждет завершения операции. Таким образом, посылающий поток "подвисает" на время передачи данных. Вы сами должны решить, насколько это приемлемо для вас. Это не имеет значения для небольших кусков данных, но для больших объемов данных или для real-time приложений этот способ вряд ли подходит.
Разделяемая память (shared memory)
Этот способ взаимодействия реализуется не совсем напрямую, а через технологию File Mapping – отображения файлов на оперативную память. Вкраце, этот механизм позволяет осуществлять доступ к файлу таким образом, как будто это обыкновенный массив, хранящийся в памяти (не загружая файл в память явно). "Побочным эффектом" этой технологии является возможность работать с таким отображенным файлом сразу нескольким процессам. Таким образом, можно создать объект file mapping, но не ассоциировать его с каким-то конкретным файлом. Получаемая область памяти как раз и будет общей между процессами. Работая с этой памятью, потоки обязательно должны согласовывать свои действия с помощью объектов синхронизации.
Библиотеки динамической компоновки (DLL)
Библиотеки динамической компоновки также имеют способность обеспечивать обмен данными между процессами. Когда в рамках DLL объявляется переменная, ее можно сделать разделяемой (shared). Все процессы, обращающиеся к библиотеке, для таких переменных будут использовать одно и то же место в физической памяти. (Здесь также важно не забыть о синхронизации.)
Протокол динамического обмена данными (Dynamic Data Exchange, DDE)
Этот протокол выполняет все основные функции для обмена данными между приложениями. Он очень широко использовался до тех пор, пока для этих целей не стали применять OLE (впоследствии ActiveX). На данный момент DDE используется достаточно редко, в основном для обратной совместимости.
Больше всего этот протокол подходит для задач, не требующих продолжительного взаимодействия с пользователем. Пользователю в некоторых случаях нужно только установить соединение между программами, а обмен данными происходит без его участия. Замечу, что все это в равной степени относится и к технологии OLE/ActiveX.
OLE/ActiveX
Это действительно универсальная технология, и одно из многих ее применений – межпроцессный обмен данными. Хотя cтоит думаю отметить, что OLE как раз для этой цели и создавалась (на смену DDE), и только потом была расширена настолько, что пришлось поменять название ;-). Специально для обмена данными существует интерфейс IDataObject. А для обмена данными по сети используется DCOM, которую под некоторым углом можно рассматривать как объединение ActiveX и RPC.
Каналы (pipes)
Каналы – это очень мощная технология обмена данными. Наверное, именно поэтому в полной мере они поддерживаются только в Windows NT/2000. В общем случае канал можно представить в виде трубы, соединяющей два процесса. Что попадает в трубу на одном конце, мгновенно появляется на другом. Чаще всего каналы используются для передачи непрерывного потока данных.
Каналы делятся на анонимные (anonymous pipes) и именованные (named pipes).
Анонимные каналы используются достаточно редко, они просто передают поток вывода одного процесса на поток ввода другого.
Именованные каналы передают произвольные данные и могут работать через сеть. (Именованные каналы поддерживаются только в WinNT/2000.)