Из курса ОС известно, что для выполнения таких задач, как совместное использование данных, построение интегрированных многофункциональных приложений и т.д., различным процессам (а также различным потокам) необходимо взаимодействовать между собой. Поскольку процессы изначально задумывались как обособленные сущности, для обеспечения корректного взаимодействия процессов требуются специальные средства и действия операционной системы.
Известно также, что в основе межпроцессного (Inter Process Communications,
Кроме того, организация связи между процессами всегда предполагает установления таких ее характеристик, как:
Кроме перечисленных у каждой связи есть еще ряд особенностей.
Традиционно считается, что основными способами межпроцессного обмена являются каналы и
(рис 7.1) Основные способы межпроцессного обменаВ случае разделяемой памяти два или более процессов совместно используют сегмент памяти. Общение происходит с помощью обычных операций копирования или перемещения данных в памяти (средствами обычных языков программирования).
Каналы предполагают созданные средствами операционной системы линии связи. Двумя основными моделями передачи данных по каналу являются поток ввода-вывода и сообщения. При передаче в рамках
Ограниченный объем курса не позволяет рассмотреть другие механизмы межпроцессного обмена, реализованные в ОС Windows, например, сокеты,
Межпроцессный обмен базируется на разделяемых ресурсах, к которым имеет доступ некоторое множество процессов. При этом возникают задачи создания, именования и защиты таких ресурсов. Обычно один из процессов создает ресурс, наделяет его атрибутами защиты и именем, по которому данный ресурс может быть доступен остальным процессам (даже в случае завершения работы процесса-создателя).
В качестве примера рассмотрим общение через
(рис 7.2) Адресные пространства процессов, взаимодействующих через сегмент разделяемой памятиВ ОС Windows сегмент разделяемой памяти создается с помощью Win32-функции ). В случае успешного выполнения данной функции создается ресурс - фрагмент памяти, доступный по имени (параметр lpname ), который базируется на соответствующем объекте ядра - "объекте-файле, отображаемом в память" с присущими любому объекту OpenFileMapping, указав имя ресурса в качестве одного из параметров.
(рис 7.3) Создание сегмента разделяемой памяти базируется на разделяемом ресурсе, которому соответствует объект ядраСпособы создания и характеристики файлов, отображаемых в память, будут рассмотрены в Части III курса "Система управления памятью", а в рамках данной темы ограничимся сведениями об обмене информации по каналам связи. При этом не надо забывать, что при любом способе общения в рамках одной вычислительной системы всегда будет использоваться элемент общей памяти. Другое дело, что в случае каналов эта память может быть выделена не в адресном пространстве процесса, а в адресном пространстве ядра системы, как это показано на рис 7.4.
(рис 7.4) Обмен через каналы связи осуществляется через буфер в адресном пространстве ядра системыОсновной принцип работы канала состоит в буферизации вывода одного процесса и обеспечении возможности чтения содержимого программного канала другим процессом. При этом часто интерфейс программного канала совпадает с интерфейсом обычного файла и реализуется обычными файловыми операциями read и write. Для обмена могут использоваться потоковая модель и модель обмена сообщениями.
Механизм генерации канала предполагает получение процессом-создателем (процессом-сервером) двух описателей (handles) для пользования этим каналом. Один из описателей применяется для чтения из канала, другой - для записи в канал.
Один из вариантов использования канала - это его использование процессом для взаимодействия с самим собой. Рассмотрим следующее изображение системы, состоящей из процесса и ядра, после создания канала (рис 7.5):
(рис 7.5) Общение процесса с самим собой через канал связиИз этого рисунка легко увидеть, что даже если процесс посылает данные самому себе, они проходят через ядро. Следовательно, для организации таких каналов, а также их именования, в ядре должны быть реализованы элементы файловой системы.
Очевидно, что обмен процесса с самим собой через канал большого смысла не имеет, поэтому обычно через канал взаимодействуют два (или более) процессов. Процесс, создающий канал, принято называть сервером, а другой процесс - клиентом. Для общения с каналом клиент и сервер должны иметь описатели (дескрипторы, handles) для чтения и записи. Процесс-сервер получает описатель при создании канала. Процесс-клиент может получить описатели в результате наследования, в том случае, когда клиент является потомком сервера. Это типично для общения через так называемые анонимные каналы. Другой способ получения - открытие по имени уже существующего
(рис 7.6) Общение процессов через канал связиЕсли нужно организовать однонаправленную связь и принято решение о направлении передачи данных, то можно "закрыть" неиспользуемый конец канала. В примере на рис 7.7 клиент посылает через канал информацию серверу.
(рис 7.7) Передача информации от клиента серверу через канал связиАнонимные каналы в Windows - это полудуплексное средство потоковой передачи байтов между родственными процессами. Они функционируют в пределах локальной вычислительной системы и хорошо подходят для перенаправления выходного потока одной программы на вход другой. Анонимные каналы реализованы при помощи именованных каналов с уникальными именами.
Анонимные каналы создаются процессом сервером при помощи функции CreatePipe:
BOOL CreatePipe( PHANDLE hReadPipe, // описатель для чтения PHANDLE hWritePipe, // описатель для записи LPSECURITY_ATTRIBUTES lpPipeAttributes, // атрибуты безопасности DWORD nSize // размер канала );
Функция CreatePipe возвращает два описателя (дескриптора) для чтения и записи в канал. После создания канала необходимо передать клиентскому процессу эти дескрипторы (или один из них), что обычно делается с помощью механизма наследования.
Для наследования описателя нужно, чтобы CreateProcess с флагом наследования TRUE. Предварительно нужно создать наследуемые описатели. Это можно, например, сделать путем явной спецификации параметра bInheritHandle структуры SECURITY_ATTRIBUTES при создании канала.
Другим способом является создание наследуемого дубликата имеющегося описателя при помощи функции DuplicateHandle и последующая передача его создаваемому процессу через командную строку или каким-либо иным образом.
Получив нужный описатель, клиентский процесс, так же как и сервер, может далее взаимодействовать с каналом при помощи функций и WriteFile. По окончании работы с каналом оба процесса должны закрыть описатели при помощи функции CloseHandle.
#include <windows.h>
#include <stdio.h>
int main()
{
HANDLE hRead, hWrite;
char BufIn[100], *BufOut = "0123456789";
int BufSize = 100;
int BytesOut = 10, BytesIn = 5, i;
if(!CreatePipe(hRead, hWrite, NULL, BufSize))
printf("Create pipe failed.\n");
WriteFile(hWrite, BufOut, BytesOut, BytesOut, NULL);
printf("Write into pipe %d bytes : ", BytesOut);
for(i=0; i<BytesOut;i++) printf("%c",BufOut[i]);
printf("\n");
ReadFile(hRead, BufIn, BytesIn, BytesIn, NULL);
printf("Read from pipe %d bytes : ", BytesIn);
for(i=0; i<5;i++) printf("%c",BufIn[i]);
return 0;
}
В приведенной программе создается анонимный канал, в него записывается строка цифр, затем часть этой строки читается и выводится на экран.
В качестве самостоятельного упражнения рекомендуется организовать через анонимный канал
Именованные каналы являются объектами ядра ОС Windows, позволяющими организовать межпроцессный обмен не только в изолированной вычислительной системе, но и в локальной сети. Они обеспечивают
Каналы должны иметь уникальные в рамках сети имена в соответствии с правилами именования ресурсов в сетях Windows (Universal Naming \\ServerName\pipe\PipeName. Для общения внутри одного компьютера имя записывается в форме \\.\pipe\PipeName, где "." обозначает локальную машину. Слово "pipe" в составе имени фиксировано, а PipeName - имя, задаваемое пользователем. Эти имена, подобно именам открытых файлов, не являются именами объектов. Они относятся к пространству имен под управлением драйверов файловых систем именованных каналов ( \Winnt\System32\Drivers\Npfs.sys ), привязанному к специальному объекту устройству \Device\NamedPipe, на которое есть ссылка в каталоге глобальных имен объектов \??\Pipe (эти последние имена "видит" утилита WinObj).
Имена созданных именованных каналов можно перечислить с помощью свободно распространяемой утилиты pipelist с сайта http://www.sysinternals.com. Поскольку имена каналов интегрированы в общую структуру имен объектов, приложения могут открывать именованные каналы с помощью функции CreateFile и взаимодействовать с ними через функции и WriteFile.
Сервер создает CreateNamedPipe (см. MSDN).
Помимо имени канала в форме, описанной выше, в число параметров функции входят: флаг, указывающий модель передачи данных; параметр, определяющий синхронный или асинхронный режим работы канала, а также указывающий, должен ли канал быть односторонним или двухсторонним. Кроме того, имеется необязательный дескриптор защиты, запрещающий несанкционированный доступ к именованному каналу, и параметр, определяющий максимальное число одновременных соединений по данному каналу.
Повторно вызывая CreateNamedPipe, можно создавать дополнительные экземпляры этого же канала.
После вызова CreateNamedPipe сервер выполняет вызов ConnectNamedPipe и ждет отклика от клиентов, которые соединяются с каналом при помощи функции CreateFile или CallNamedPipe, указывая при вызове имя созданного сервером канала. Легальный клиент получает описатель, представляющий клиентскую сторону ConnectNamedPipe на этом завершается.
После того как соединение по именованному каналу установлено, клиент и сервер могут использовать его для чтения и записи данных через Win32-функции и WriteFile.
В качестве упражнения рекомендуется осуществить прогон программы общения клиента и сервера через
Сервер
#include <stdio.h>
#include <windows.h>
void main()
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO SI;
char * ClientName = "client.exe";
HANDLE hPipe;
LPTSTR PipeName = TEXT("\\\\.\\pipe\\MyPipe");
char Buff[255];
DWORD iNumBytesToRead = 255, i;
ZeroMemory(SI, sizeof(STARTUPINFO));
SI.cb = sizeof(STARTUPINFO);
ZeroMemory(piProcInfo, sizeof(piProcInfo));
hPipe = CreateNamedPipe(
PipeName, // имя канала
PIPE_ACCESS_DUPLEX, // чтение и запись из канала
PIPE_TYPE_MESSAGE | // передача сообщений по каналу
PIPE_READMODE_MESSAGE | // режим чтения сообщений
PIPE_WAIT, // синхронная передача сообщений
PIPE_UNLIMITED_INSTANCES, // число экземпляров канала
4096, // размер выходного буфера
4096, // размер входного буфера
NMPWAIT_USE_DEFAULT_WAIT, // тайм-аут клиента
NULL); // защита по умолчанию
if (hPipe == INVALID_HANDLE_VALUE)
{
printf("CreatePipe failed: error code %d\n", (int)GetLastError());
return;
}
if((CreateProcess(NULL, ClientName, NULL, NULL, FALSE, 0, NULL, NULL, SI, piProcInfo))==0)
{
printf("create client process: error code %d\n", (int)GetLastError());
return;
}
if((ConnectNamedPipe(hPipe, NULL))==0)
{
printf("client could not connect\n");
return;
}
ReadFile(hPipe, Buff, iNumBytesToRead, iNumBytesToRead, NULL);
for(i=0; i<iNumBytesToRead; i++) printf("%c",Buff[i]);
}
Клиент
#include <stdio.h>
#include <windows.h>
void main()
{
HANDLE hPipe;
LPTSTR PipeName = TEXT("\\\\.\\pipe\\MyPipe");
DWORD NumBytesToWrite;
char Buff[] = "Message from Client";
hPipe = CreateFile(
PipeName, // имя канала
GENERIC_READ | // чтение и запись в канал
GENERIC_WRITE,
0, // нет разделяемых операций
NULL, // защита по умолчанию
OPEN_EXISTING, // открытие существующего канала
0, // атрибуты по умолчанию
NULL); // нет дополнительных атрибутов
WriteFile(hPipe, Buff, strlen(Buff), NumBytesToWrite, NULL);
}
В данном примере сервер создает канал, затем запускает процесс-клиент и ждет соединения. Далее он читает сообщение, посланное клиентом.
Помимо перечисленных выше система представляет еще ряд полезных функций для работы с именованными каналами. Для копирования данных из PeekNamedPipe. Функция TransactNamedPipe применяется для объединения операций чтения и записи в канал в одну операцию, которая называется транзакцией. Имеются информационные функции для определения состояния канала, например, GetNamedPipeHandleState или GetNamedPipeInfo. Полный перечень находится в MSDN.
Организация совместной деятельности и общения процессов является важной и актуальной задачей. К основным способам межпроцессного обмена традиционно относят каналы и
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.