Категории
Самые читаемые
💎Читать книги // БЕСПЛАТНО // 📱Online » Компьютеры и Интернет » Программирование » Системное программирование в среде Windows - Джонсон Харт

Читаем без скачивания Системное программирование в среде Windows - Джонсон Харт

Читать онлайн Системное программирование в среде Windows - Джонсон Харт

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 84 85 86 87 88 89 90 91 92 ... 142
Перейти на страницу:

10.11. На web-сайте находится файл multisem.c, который реализует сложный семафор, имитирующий объекты Windows (они имеют имена и атрибуты безопасности, могут разделяться процессами, и для них предусмотрены две модели ожидания), а также файл тестовой программы TestMultiSem.c. Выполните сборку и тестирование этой программы. Как в ней используется модель переменных условий? Повышается ли производительность в результате использования объекта CRITICAL_SECTION? Что здесь выступает в роли инвариантов и предикатов переменных условий?

10.12. Проиллюстрируйте целесообразность рекомендаций, приведенных в конце настоящей главы, ссылаясь на ошибки, с которыми вам пришлось столкнуться, или ошибки, содержащиеся в версии программы с дефектами, представленной на Web-сайте.

10.13. Ознакомьтесь со статьей Шмидта и Пьярали "Strategies for Implementing POSIX Condition Variables in Win32" ("Стратегии реализации переменных условий POSIX в Win32") (см. раздел "Дополнительная литература"). Примените их методы анализа равноправия, корректности, сериализации и других программных факторов к моделям переменных условий (которые в указанной статье называются "идиомами" ("idioms")), фигурирующим в настоящей главе. Заметьте, что сами переменные условия в настоящей главе не эмулируются; вместо этого эмулируется их использование, тогда как Шмидт и Пьярали эмулируют переменные условий, используемые в произвольном контексте.

10.14. Находящиеся на web-сайте проекты batons и batonsmultipleevents демонстрируют альтернативные варианты решения задачи сериализации выполнения потоков. О предпосылках и предшествующих работах других авторов говорится в комментариях, включенных в код. Во втором решении с каждым потоком связывается уникальное событие, что позволяет отслеживать сигнальные состояния отдельных потоков. Для реализации выбран язык C++, что дало возможность воспользоваться средствами стандартной библиотеки шаблонов C++ (Standard Template Library, STL). Проанализируйте, что имеют общего и чем различаются между собой эти два решения и используйте второе из них в качестве средства ознакомления с библиотекой STL. 

ГЛАВА 11

Взаимодействие между процессами

В главе 6 было показано, как создавать процессы и управлять ими, тогда как главы 7—10 были посвящены описанию методов управления потоками, которые выполняются внутри процессов, и объектов, обеспечивающих их синхронизацию. Вместе с тем, если не считать использования разделяемой памяти, мы до сих пор не рассмотрели ни одного из методов взаимодействия между процессами.

Ниже вы ознакомитесь с последовательным межпроцессным взаимодействием (Interprocess Communication, IPC)[30], в котором используются объекты, подобные файлам. Двумя основными механизмами Windows, реализующими IPC, являются анонимные и именованные каналы, доступ к которым осуществляется с помощью уже известных вам функций ReadFile и WriteFile. Простые анонимные каналы являются символьными и работают в полудуплексном режиме. Эти свойства делают их удобными для перенаправления выходных данных одной программы на вход другой, как это обычно делается в UNIX. В первом примере демонстрируется, как реализовать эту возможность.

По сравнению с анонимными каналами возможности именованных каналов гораздо богаче. Они являются дуплексными, ориентированы на обмен сообщениями и обеспечивают взаимодействие через сеть. Кроме того, один именованный канал может иметь несколько открытых дескрипторов. В сочетании с удобными, ориентированными на выполнение транзакций функциями эти возможности делают именованные каналы пригодными для создания клиент-серверных систем. Это демонстрируется во втором из приведенных в настоящей главе примере, представляющем многопоточный клиент-серверный командный процессор, моделируемый в соответствии с рис. 7.1, который привлекался для обсуждения потоков. Каждый из потоков сервера управляет взаимодействием с отдельным клиентом, и для каждой пары "поток/клиент" используется отдельный дескриптор, то есть отдельный экземпляр именованного канала.

Наконец, почтовые ящики обеспечивают широковещательную рассылку сообщений по схеме "один многим", а их использование для расширения возможностей командного процессора демонстрируется в последнем примере.

Анонимные каналы

Анонимные каналы (anonymous channels) Windows обеспечивают однонаправленное (полудуплексное) посимвольное межпроцессное взаимодействие. Каждый канал имеет два дескриптора: дескриптор чтения (read handle) и дескриптор записи (write handle). Функция, с помощью которой создаются анонимные каналы, имеет следующий прототип:

BOOL CreatePipe(PHANDLE phRead, PHANDLE phWrite, LPSECURITY_ATTRIBUTES lpsa, DWORD cbPipe)

Дескрипторы каналов часто бывают наследуемыми; причины этого станут понятными из приведенного ниже примера. Значение параметра cbPipe, указывающее размер канала в байтах, носит рекомендательный характер, причем значению 0 соответствует размер канала по умолчанию.

Чтобы канал можно было использовать для IPC, должен существовать еще один процесс, и для этого процесса требуется один из дескрипторов канала. Предположим, например, что родительскому процессу, вызвавшему функцию CreatePipe, необходимо вывести данные, которые нужны дочернему процессу. Тогда возникает вопрос о том, как передать дочернему процессу дескриптор чтения (phRead). Родительский процесс осуществляет это, устанавливая дескриптор стандартного ввода в структуре STARTUPINFO для дочерней процедуры равным *phRead.

Чтение с использованием дескриптора чтения канала блокируется, если канал пуст. В противном случае в процессе чтения будет воспринято столько байтов, сколько имеется в канале, вплоть до количества, указанного при вызове функции ReadFile. Операция записи в заполненный канал, которая выполняется с использованием буфера в памяти, также будет блокирована.

Наконец, анонимные каналы обеспечивают только однонаправленное взаимодействие. Для двухстороннего взаимодействия необходимы два канала. 

Пример: перенаправление ввода/вывода с использованием анонимного канала

В программе 11.1 представлен родительский процесс, который создает два процесса из командной строки и соединяет их каналом. Родительский процесс устанавливает канал и осуществляет перенаправление стандартного ввода/вывода. Обратите внимание на то, каким образом задается свойство наследования дескрипторов анонимного канала и как организуется перенаправление стандартного ввода/вывода на два дочерних процесса; эти методики описаны в главе 6.

Местоположение оператора WriteFile в блоке Program2 на рис. 11.1 справа предполагает, что программа считывает большой объем данных, обрабатывает их, и лишь после этого записывает результаты. Эту запись можно было бы осуществлять и внутри цикла, выводя результаты после каждого считывания.

Рис. 11.1. Межпроцессное взаимодействие с использованием анонимного канала

Дескрипторы каналов и потоков должны закрываться при первой же возможности. На рис. 11.1 закрытие дескрипторов не отражено, однако это делается в программе 11.1. Родительский процесс должен закрыть дескриптор устройства стандартного вывода сразу же после создания первого дочернего процесса, чтобы второй процесс мог распознать метку конца файла, когда завершится выполнение первого процесса. В случае существования открытого дескриптора первого процесса второй процесс не смог бы завершиться, поскольку система не обозначила бы конец файла.

В программе 11.1 используется непривычный синтаксис: две команды, разделенные символом =, обозначающим канал. Использование для этой цели символа вертикальной черты (|) привело бы к возникновению конфликта с системным командным процессором. Рисунок 11.1 является схематическим представлением выполнения следующей команды:

$ pipe Program1 аргументы = Program2 аргументы

При использовании средств командного процессора UNIX или Windows соответствующая команда имела бы следующий вид:

$ Program1 аргументы | Program2 аргументы

Программа 11.1. pipe: межпроцессное взаимодействие с использованием анонимных каналов 

#include "EvryThng.h"

int _tmain(int argc, LPTSTR argv[])

/* Соединение двух команд с помощью канала в командной строке: pipe команда1 = команда2 */

{

 DWORD i = 0;

 HANDLE hReadPipe, hWritePipe;

 TCHAR Command1[MAX_PATH];

 SECURITY_ATTRIBUTES PipeSA = /* Для наследуемых дескрипторов. */

  {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};

 PROCESS_INFORMATION ProcInfo1, ProcInfo2;

 STARTUPINFO StartInfoCh1, StartInfoCh2;

 LPTSTR targv = SkipArg(GetCommandLine());

 GetStartupInfo(&StartInfoCh1);

 GetStartupInfo(&StartInfoCh2);

 /* Найти символ "=", разделяющий две команды. */

 while (*targv != '=' && *targv != '') {

  Command1[i] = *targv;

1 ... 84 85 86 87 88 89 90 91 92 ... 142
Перейти на страницу:
На этой странице вы можете бесплатно скачать Системное программирование в среде Windows - Джонсон Харт торрент бесплатно.
Комментарии