
- •1.1 Основы программирования в операционной системе Windows
- •1.1.1 Вызов функций api
- •1.1.2 Структура программы
- •1.2 Вопросы системного программирования в Windows
- •1.2.1 Страничная и сегментная адресация.
- •1.2.2 Адресное пространство процесса.
- •2.1 Управление процессами
- •2.2 Процессы и потоки в Windows
- •2.3 Создание процессов
- •2.4 Определение исполняемого образа и командной строки
- •2.5 Идентификация процессов
- •3.1 Создание потока. Функция CreateThread
- •3.2. Завершение потока
- •3.3 Другие функции работы с потоками
- •3.4 Структура context
- •3.5 Приоритеты потоков
- •4.1 Объект critical_section
- •4.2 Мьютексы
- •4.3 Семафоры
- •5.1 События
- •7.1 Кучи
- •7.2 Управление памятью кучи
- •Другие функции для работы с кучей
- •Резюме по управлению кучей
- •Отображение адресного пространства процесса в объекты отображения
- •Что такое импорт
- •Явная загрузка dll
- •Явное подключение экспортируемого идентификатора
- •10.1 Управление файлами и каталогами Создание и открытие файлов
- •10.2 Управление каталогами
- •10.3 Другие методы получения атрибутов файлов и каталогов
- •11.1 Блокировка файлов
- •11.2 Реестр
- •12.1 Стандартные устройства и консольный ввод-вывод
- •12.2 Асинхронный ввод-вывод и порты завершения
- •Параметры
- •Цели системы безопасности
- •Параметры
- •Аварийное завершение
- •Использование именованных каналов
- •Параметры
- •Наблюдение за сообщениями в именованном канале
- •Параметры
Использование именованных каналов
Функция CreateNamedPipe создает первый экземпляр именованного канала и возвращает его дескриптор. Также эта функция определяет максимальное количество экземпляров канала и, следовательно, количество клиентов, которых можно обслуживать одновременно.
Обычно процесс создания называется сервером. Процессы-клиенты, возможно, работающие на других системах, открывают этот канал с помощью CreateFile.
Создание именованных каналов
Ниже приведена функция CreateNamedPipe.
HANDLE CreateNamedPipe ( LPCTSTR lpszPipeName,
DWQRD fdwOpenMode, DWORD fdwPipeMode,
DWORD nMaxInstances, DWORD cbOutBuf, DWORD cblnBuf,
DWORD dwTimeOut, LPSECURITY_ATTRIBUTES lpsa)
Параметры
lpszPipeName обозначает имя канала в форме: \\.\pipe\[путь]имя-канала
Точка обозначает локальную машину; иначе говоря, создать канал на удаленной машине нельзя.
fdwOpenMode имеет одно из следующих значений:
PIPE_ACCESS_DUPLEX — эквивалентно комбинации GENERIC_READ и GENERIC_WRITE;
PIPE_ACCESS_INBOUND — направление данных только от клиента к серверу, эквивалентно GENERIC_READ;
PIPE_ACCESS_OUTBOUND — эквивалентно GENERIC_WRITE.
Режим также может быть FILE_FLAG_WRITE_THROUGH (не используется для каналов сообщений) и FILE_FLAG_OVERLAPPED.
fdwPipeMode может принимать три взаимоисключающих пары флагов. Они указывают, является ли запись ориентированной на сообщения или байтовой, осуществляется ли чтение по сообщениям или по блокам и блокируется ли операция чтения.
- PIPE_TYPE_BYTE и PIPE_TYPE_MESSAGE, которые взаимно исключают друг друга, указывают, записываются ли данные в канал как поток байтов или как поток сообщений. Для всех экземпляров канала применяется один и тот же тип.
PIPE_READMODE_BYTE и PIPE_READMODE_MESSAGE указывают, читаются ли данные как поток байтов или как поток сообщений. Для PIPE_READMODE_MESSAGE необходимо PIPE_TYPE_MESSAGE.
PIPE_WAIT и PIPE_NOWAIT определяют, будет ли операция ReadFile блокироваться. Указывайте значение PIPE_WAIT, поскольку для асинхронного ввода-вывода есть способы получше.
nMaxInstances определяет количество экземпляров канала и, следовательно, количество одновременно обслуживаемых клиентов. Если указать значение PIPE_UNLIMITED_ INSTANCES, количество каналов будет определять ОС в зависимости от доступных системных ресурсов.
cbOutBuf и cbInBuf задают размеры в байтах буферов ввода и вывода, используемых для именованных каналов. Если указать нуль, будут использоваться значения по умолчанию.
dwTimeOut — принятый по умолчанию тайм-аут (в миллисекундах) для функции WaitNamedPipe. Эта ситуация, в которой функция создания определяет тайм-аут для другой функции, является уникальной.
Возвращаемое значение в случае ошибки — INVALID_HANDLE_VALUE, так как дескрипторы каналов подобны дескрипторам файлов.
lpsa играет ту же роль, что и в других функциях создания.
При первом вызове CreateNamedPipe фактически создается именованный канал, а не просто экземпляр. При закрытии последнего дескриптора экземпляра сам этот экземпляр удаляется. Удаление последнего экземпляра именованного канала вызывает удаление самого канала.
Подключение клиента к именованному каналу
Клиент может подключиться к именованному каналу с помощью вызова CreateFile с указанием имени канала. Во многих случаях клиент и сервер находятся на одной машине; тогда имя имеет вид: \\.\pipe\[путь]имя_канала
Если бы сервер находился на другой машине, имя выглядело бы так:
\\имя_сервера\pipe\[путь]имя_канала
Если сервер локальный, то применение для имени символа "." вместо указания имени самой машины значительно повышает быстродействие.
Функции состояния именованного канала
GetNamedPipeHandleState возвращает для данного открытого дескриптора сведения о том, находится ли канал в блокируемом или неблокируемом режиме, ориентирован ли он на сообщения или на байты, о количестве экземпляров канала и т.д.
SetNamedPipeHandleState позволяет программе задавать эти атрибуты состояния.
GetNamedPipelnfo определяет, связан ли дескриптор с клиентом или сервером, каков размер буфера и т.д.
Функции подключения именованного канала
После создания экземпляра именованного канала сервер может отслеживать подключение клиента (с помощью функций CreateFile или CallNamedPipe), используя функцию ConnectNamedPipe.
BOOL ConnectNamedPipe ( HANDLE hNamedPipe, LPOVERLAPPED lpo)
Если задать в lpo значение NULL, выполнение ConnectNamedPipe завершится сразу же, как только появится подключение клиента. Обычно функция возвращает TRUE. Значение FALSE может быть, если клиент подключается между вызовами сервером функций CreateNamedPipe и ConnectNamedPipe. В этом случае GetLastError возвращает значение ERROR_PIPE_CONNECTED.
После возвращения из ConnectNamedPipe сервер может читать запросы с помощью ReadFile и записывать ответы, используя WriteFile. В заключение сервер должен вызвать функцию DisconnectNamedPipe, чтобы освободить дескриптор (экземпляр канала) для соединения с другим клиентом.
Последняя функция, WaitNamedPipe, предназначена для синхронизации подключений клиента. Эта функция завершается, если на сервере имеется незавершенное обращение к ConnectNamedPipe. Используя WaitNamedPipe, клиент может убедиться, что сервер готов к подключению, после чего вызвать CreateFile. Кроме того, вызов сервером функции ConnectNamedPipe в этом случае завершится успешно.
Соединение клиента и сервера через именованный канал
Сначала в последовательности сервера осуществляется подключение клиента, с которым сервер связывается до тех пор, пока тот не разорвет соединение, затем сервер закрывает подключение на стороне сервера и соединяется с другим клиентом.
Далее приводится последовательность подключения клиента, в которой клиент закрывается, когда завершает работу, позволяя другому клиенту соединиться через тот же экземпляр именованного канала. Клиент может соединяться с сервером через сеть, если ему известно имя сервера.
Обратите внимание, что между клиентом и сервером происходит состязание. Во-первых, вызов клиентом WaitNamedPipe завершится неудачно, если сервер еще не создал именованный канал. Во-вторых, возможны обстоятельства, в которых клиент может завершить свой вызов CreateFile прежде, чем сервер вызовет ConnectNamedPipe. В этом случае ConnectNamedPipe возвратит FALSE, но связь через именованный канал будет работать, как положено.
Транзакционные функции именованного канала
Клиент выполняет следующее:
• открывает экземпляр канала, создавая долговременное подключение к серверу и потребляя этот экземпляр канала;
попеременно посылает запросы и ожидает ответов;
закрывает подключение.
Обычную последовательность функций WriteFile, ReadFile можно считать отдельной транзакцией клиента, и в Win32 имеется такая функция для каналов сообщений.
BOOL TransactNamedPipe ( HANDLE hNamedPipe, LPVOID lpvWriteBuf,
DWORD cbWriteBuf, LPVOID lpvReadBuf, DWORD cbReadBuf,
LPDWORD lpcbRead, LPOVERLAPPED lpa)
Назначение параметров не нуждается в объяснении, так как эта функция представляет собой сочетание WriteFile и ReadFile для дескриптора именованного канала. Указываются как выходной, так и входной буферы, а * lpcbRead задает длину сообщения.
Функция TransactNamedPipe удобна, но требует постоянного подключения, что ограничивает число клиентов.
CallNamedPipe, вторая функция-полуфабрикат, лишена этого недостатка, так как объединяет в себе всю последовательность: CreateFile, WriteFile, ReadFile, CloseHandle.
Преимущество заключается в более эффективном использовании канала, несмотря на издержки подключения при каждом запросе.
BOOL CallNamedPipe ( LPCPSTR lpszPipeName, LPVOID lpvWriteBuf,
DWORD сbWriteBuf, LPVOID lpvReadBuf, DWORD сbReadBuf,
LPDWORD lpcbRead, DWORD dwTimeOut)
Использование параметров подобно TransactactNamedPipe с тем исключением, что для канала указывается имя, а не дескриптор. Функция CallNamedPipe является синхронной.
Здесь также указывается тайм-аут в миллисекундах — для подключения, но не для транзакции. Для dwTimeOut существует также три специальных значения:
NMPWAIT_NOWAIT;
NMPWAIT_WAIT_FOREVER;
NMPWAIT_USE_DEFAULT_WAIT — в этом случае используется тайм-аут по умолчанию, заданный при вызове CreateNamedPipe.