Системное программирование в среде Windows
Шрифт:
Дополнительная литература
Источником большей части информации и советов по программированию, приведенных в конце настоящей главы, послужила книга [6]. Из нее же было взято в переработанном виде и решение на базе объекта барьера, использованное в программах 10.1 и 10.2.
В статье Дугласа Шмидта (Douglas Schmidt) и Ирфана Пьярали (Irfan Pyarali) "Strategies for Implementing POSIX Condition Variables in Win32" ("Стратегии реализации переменных условий POSIX в Win32") (доступна по адресу http:// www.es.wustl.edu/~schmidt/win32-cv-1.html), обсуждается ограниченность событий Win32 (Windows) и эмуляция переменных условий, а также дан глубокий анализ и оценка нескольких подходов. Вместе с тем, этот материал был написан еще до появления функции SignalObjectAndWait,
Упражнения
10.1. Переработайте программу 10.1, исключив из нее функцию SignalObjectAndWait; для тестирования полученного результата воспользуйтесь Windows 9х.
10.2. Модифицируйте программу evenpc (программа 8.2), использовав модель переменных условий и обеспечив возможность существования нескольких потребителей. События какого типа потребуются в данном случае?
10.3. Измените логику работы программы 10.2 таким образом, чтобы объект события переходил в сигнальное состояние только один раз.
10.4. Замените мьютекс в объекте очереди, который используется в программе 10.2, объектом CS. Какое влияние это изменение оказывает на производительность и пропускную способность программы? Решение находится на Web-сайте книги, а соответствующие экспериментальные данные приведены в приложении В.
10.5. Для индикации состояний очереди, в которых она не пуста или не заполнена, в программе 10.4 применяется широковещательная модель CV. Будет ли в данном случае работать сигнальная модель CV? Не является ли она даже более предпочтительной в некоторых отношениях? Соответствующие экспериментальные данные приведены в приложении В.
10.6. Поэкспериментируйте с размерами очереди и величиной коэффициента блокирования "передатчик/приемник" в программе 10.5 для выяснения того, какое влияние оказывают эти факторы на загрузку ЦП, а также производительность и пропускную способность программы.
10.7. Видоизмените программы 10.3–10.5, обеспечив их соответствие принятым в Windows соглашениям о правилах образования имен, которых мы придерживаемся на протяжении всей книги.
10.8. Для программистов на C++. Приведенный в программах 10.3 и 10.4 код можно использовать для создания в C++ класса синхронизированной очереди; создайте этот класс и протестируйте его, модифицировав соответствующим образом программу 10.5. Какие из функций должны быть общедоступными, а какие — закрытыми?
10.9. Исследуйте, как изменятся показатели производительности программы 10.5 после замены мьютексов объектами CRITICAL_SECTIONS.
10.10. Улучшите программу 10.5, исключив необходимость прекращения выполнения потоков передатчика и приемника. Потоки должны самостоятельно завершать свое выполнение.
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") (см. раздел "Дополнительная литература"). Примените их методы анализа равноправия,
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. В первом примере демонстрируется, как реализовать эту возможность.
30
Как показано в главе 10, в упражнении с семафором (упражнение 10.11), системные службы Windows предоставляют возможность организации взаимодействия между процессами также посредством отображаемых файлов. Дополнительные механизмы IPC включают файлы, сокеты, удаленные вызовы процедур, СОМ и отправку сообщений через почтовые ящики. Сокеты рассматриваются в главе 12.
По сравнению с анонимными каналами возможности именованных каналов гораздо богаче. Они являются дуплексными, ориентированы на обмен сообщениями и обеспечивают взаимодействие через сеть. Кроме того, один именованный канал может иметь несколько открытых дескрипторов. В сочетании с удобными, ориентированными на выполнение транзакций функциями эти возможности делают именованные каналы пригодными для создания клиент-серверных систем. Это демонстрируется во втором из приведенных в настоящей главе примере, представляющем многопоточный клиент-серверный командный процессор, моделируемый в соответствии с рис. 7.1, который привлекался для обсуждения потоков. Каждый из потоков сервера управляет взаимодействием с отдельным клиентом, и для каждой пары "поток/клиент" используется отдельный дескриптор, то есть отдельный экземпляр именованного канала.
Наконец, почтовые ящики обеспечивают широковещательную рассылку сообщений по схеме "один многим", а их использование для расширения возможностей командного процессора демонстрируется в последнем примере.
Анонимные каналы
Анонимные каналы (anonymous channels) Windows обеспечивают однонаправленное (полудуплексное) посимвольное межпроцессное взаимодействие. Каждый канал имеет два дескриптора: дескриптор чтения (read handle) и дескриптор записи (write handle). Функция, с помощью которой создаются анонимные каналы, имеет следующий прототип: