Джонсон М. Харт Системное программирование в среде Windows Третье издание Введение Потенциальная аудитория Изменения в третьем издании Как организована эта книга Сопоставление с UNIX и библиотекой С Примеры Web-сайты, посвященные этой книге Благодарности От издательства ГЛАВА 1 Знакомство с Win32 и Win64 Основные возможности операционных систем Эволюция Windows Версии Windows Устаревшие предыдущие версии Windows Windows NT 5.x Другие интерфейсы программирования для Windows Поддержка процессоров Воздействие Windows на ситуацию на рынке Windows, стандарты и открытые системы Библиотеки совместимости Принципы, лежащие в основе Windows Подготовка к работе с Win64 О целесообразности привлечения функций стандартной библиотеки C для обработки файлов Что требуется для работы с данной книгой Пример: простое последовательное копирование файла Копирование файлов с использованием стандартной библиотеки С Копирование файлов с использованием Windows Копирование файлов с использованием вспомогательной функции Windows Резюме В следующих главах Дополнительная литература Упражнения ГЛАВА 2 Использование файловой системы и функций символьного ввода/вывода Windows Файловые системы Windows Правила именования файлов Операции открытия, чтения, записи и закрытияфайлов Создание и открытие файла Закрытие файла Чтение файла Запись в файл Вступление: стандартные символы и символы Unicode Альтернативные функции для работы с обобщенными строками Обобщенная функция Main Определения функций Стратегии использования символов Unicode Стандартные устройства и консольный ввод/вывод Пример: вывод на консоль сообщений и подсказок для пользователя Пример: обработка ошибок Пример: копирование нескольких файлов на стандартное устройство вывода Пример: преобразование символов из ASCII в Unicode Производительность программы Управление файлами и каталогами Управление файлами Управление каталогами Пример: печать текущего каталога Резюме В следующих главах Дополнительная литература Упражнения ГЛАВА 3 Усовершенствованные средства для работы с файлами и каталогами и знакомство с реестром 64-битовая файловая система Указатели файлов 64-битовая арифметика Указание позиции файла с помощью структуры OVERLAPPED Определение размера файла Установка размера файла, инициализация файла и разреженные файлы Пример: обновление записей, находящихся в произвольном месте файла Атрибуты файлов и управление каталогами Полные имена файлов Другие методы определения атрибутов файлов и каталогов Именование временных файлов Точки монтирования Пример: вывод списка атрибутов файла Пример: установка меток времени файла Стратегии обработки файлов Блокирование файлов Следствия принятой логики блокирования файлов Реестр Ключи реестра Управление системным реестром Управление подразделами реестра Управление значениями Пример: вывод списка разделов и содержимого реестра Резюме В следующих главах Дополнительная литература Упражнения ГЛАВА 4 Обработка исключений Исключения и обработчики исключений Блоки try и except Выражения фильтров и их значения Коды исключений Резюме: последовательность обработки исключений Исключения, возникающие при выполнении операций над числами с плавающей точкой Ошибки и исключения Исключения, генерируемые приложением Пример: обработка ошибок как исключений Обработчики завершения Выход из try-блока Аварийное завершение Выполнение обработчика завершения и выход из него Сочетание блоков finally и except Глобальное и локальное разворачивание стека Обработчики завершения: завершение процессов и потоков SEH и обработка исключений в C++ Пример: использование обработчиков завершения для повышения качества программ Пример: использование функции фильтра Обработчики управляющих сигналов консоли Пример: обработчик управляющих сигналов консоли Векторная обработка исключений Резюме В следующих главах Упражнения ГЛАВА 5 Управление памятью, отображение файлов и библиотеки DLL Архитектура системы управления памятью в Win32 и Win64 Обзор методов управления памятью Куча Управление памятью кучи Другие функции кучи Резюме: управление кучами Пример: сортировка файлов с использованием бинарного дерева поиска Отображение файлов Объекты отображения файлов Отображение файла на адресное пространство процесса Ограничения метода отображения файлов Резюме: отображение файлов Пример: последовательная обработка файлов с использованием метода отображения Пример: сортировка отображенных файлов Базовые указатели Пример: использование базовых указателей Динамически компонуемые библиотеки Статические и динамические библиотеки Неявное связывание Явное связывание Пример: явное связывание функци и преобразования файлов Создание библиотек DLL на основе функции Asc2Un Точки входа библиотеки DLL Управление версиями DLL Резюме В следующих главах Дополнительная литература Упражнения ГЛАВА 6 Управление процессами Процессы и потоки Windows Создание процесса Указание исполняемого модуля и командной строки Наследуемые дескрипторы Счетчики дескрипторов процессов Идентификаторы процессов Дублирование дескрипторов Завершение и прекращение выполнения процесса Ожидание завершения процесса Блоки и строки окружения Защита процесса Пример: параллельный поиск указанного текстового шаблона Процессы в многопроцессорной среде Временные характеристики процесса Пример: временные характеристики процессов Использование команды timep Генерация управляющих событий консоли Пример: простое управление задачами Создание фоновых задач Получение номера задачи Вывод списка фоновых задач Поиск задачи в файле списка задач Объекты задач Резюме В следующих главах Упражнения ГЛАВА 7 Потоки и планирование выполнения Обзор потоков Перспективы и проблемы Основные сведения о потоках Управление потоками Идентификация потоков Дополнительные функции управления потоками Приостановка и возобновление выполнения потока Ожидание завершения потока Удаленные потоки Использование библиотеки С впотоках Библиотеки с многопоточной поддержкой Пример: многопоточный поиск контекста Потоки и производительность Модель "хозяин/рабочий" и другие модели многопоточных приложений Пример: применение принципа "разделяй и властвуй" для решения задачи сортировки слиянием в SMP-системах Производительность Локальные области хранения потоков Приоритеты процессов и потоков и планирование выполнения Предостережение относительно использования приоритетов потоков и процессов Состояния потоков Возможные ловушки и распространенные ошибки Ожидание в течение конечного интервала времени Облегченные потоки Резюме В следующих главах Дополнительная литература Упражнения ГЛАВА 8 Синхронизация потоков Необходимость в синхронизации потоков Критические участки кода Функции взаимоблокировки Локальная и глобальная память Резюме: безопасный многопоточный код Объекты синхронизации потоков Объекты критических участковкода Настройка спин-счетчика Использование объектов CRITICAL_SECTION для защиты разделяемыхпеременных Пример: простая система "производитель/потребитель" Комментарии к примеру простой системы "производитель/потребитель" Мьютексы Покинутые мьютексы Мьютексы, критические участки кода и взаимоблокировки Сравнительный обзор: мьютексы и объекты CRITICAL_SECTION Синхронизация куч Семафоры Использование семафоров Ограниченность семафоров События Обзор: четыре модели использования событий Пример: система "производитель/потребитель" Обзор: объекты синхронизации Windows Ожидание сообщений и объектов Дополнительные рекомендации относительно использования мьютексов и объектов CRITICAL_SECTION Другие функции взаимоблокировки Учет факторов производительности при организации управленияпамятью Резюме В следующих главах Дополнительная литература Упражнения ГЛАВА 9 Влияние синхронизации на производительность и рекомендации по ее повышению Влияние синхронизации на производительность Достоинства и недостатки объектов CRITICAL_SECTION Модельная программа для исследования факторов производительности Настройка производительности SMP-систем с помощью спин-счетчиков Установка значений спин-счетчиков Дросселирование семафора для уменьшения состязательности между потоками Родство процессоров Маски родства системы, процесса и потока Определение количества процессоров в системе Гиперпотоки и счетчик процессоров Порты завершения ввода/вывода Рекомендации по повышению производительности и возможные риски Резюме В следующих главах Дополнительная литература Упражнения ГЛАВА 10 Усовершенствованные методы синхронизации потоков Модель переменных условий и свойства безопасности Совместное использование событий и мьютексов Модель переменных условий Использование функции SignalObjectAndWait Пример: объект порогового барьера Комментарии по поводу реализации объекта порогового барьера Объект очереди Комментарии по поводу функций управления очередью с точки зрения производительности Пример: использование очередей в многоступенчатом конвейере Комментарии по поводу многоступенчатого конвейера Асинхронные вызовы процедур Очередизация асинхронных вызовов процедур АРС и упущенные сигналы Состояния дежурного ожидания Безопасная отмена выполнения потоков Создание переносимых приложений с использованием потоков Pthreads Стеки потоков и допустимые количества потоков Рекомендации по проектированию, отладке и тестированию программ Как избежать создания некорректного программного кода За рамками Windows API Резюме В следующих главах Дополнительная литература Упражнения ГЛАВА 11 Взаимодействие между процессами Анонимные каналы Пример: перенаправление ввода/вывода с использованием анонимного канала Именованные каналы Использование именованных каналов Создание именованных каналов Подключение клиентов именованных каналов Функции состояния именованных каналов Функции подключения именованных каналов Подключение клиентов и серверов именованных каналов Функции транзакций именованных каналов Определение наличия сообщений в именованных каналах Пример: клиент-серверный процессор командной строки Комментарии по поводу клиент-серверного процессора командной строки Почтовые ящики Использование почтовых ящиков Создание и открытие почтового ящика Создание, подключение и именование каналов и почтовых ящиков Пример: сервер, обнаруживаемый клиентами Комментарии по поводу многопоточных моделей Резюме В следующих главах Упражнения ГЛАВА 12 Сетевое программирование с помощью сокетов Windows Сокеты Windows Инициализация Winsock Создание сокета Серверные функции сокета Связывание сокета Перевод связанного сокета в состояние прослушивания Прием клиентских запросов соединения Отключение и закрытие сокетов Пример: подготовка и получение клиентских запросов соединения Клиентские функции сокета Установление клиентского соединения с сервером Пример: подключение клиента к серверу Отправка и получение данных Сравнение именованных каналов и сокетов Сравнение серверов именованных каналов и сокетов Сравнение клиентов именованных каналов и сокетов Пример: функция приема сообщений в случае сокета Пример: клиент на основе сокета Пример: усовершенствованный сервер на основе сокетов Замечания по поводу безопасности Внутрипроцессные серверы Ориентированные на строки сообщения, точкив хода DLL и TLS Решение проблемы долговременных состояний в многопоточной среде Пример: безопасная многопоточная DLL для обмена сообщениями через сокет Комментарии по поводу DLL и безопасной многопоточной среды Пример: альтернативная стратегия создания безопасных библиотек DLL с много поточной поддержкой Дейтаграммы Использование дейтаграмм для удаленного вызова процедур Сравнение Berkeley Sockets и Windows Sockets Перекрывающийся ввод/вывод с использованием Windows Sockets Windows Sockets 2 Резюме В следующих главах Дополнительная литература Упражнения ГЛАВА 13 Windows Services Написание программ, реализующихслужбы Windows Services: обзор Функция main() Функции ServiceMain() Регистрация управляющей программы службы Настройка состояния службы Структура SERVICE_STATUS Специфический для службы код Обработчик управляющих команд службы Пример: "интерфейсная оболочка" службы Управление службами Windows Открытие SCM Создание и удаление службы Запуск службы Управление службой Опрос состояния службы Резюме: функционирование и управление службой Пример:команднаяоболочкауправленияслужбами Совместное использование объектов ядра приложениями и службами Регистрация событий Замечания по отладке службы Резюме В следующих главах Дополнительная литература Упражнения ГЛАВА 14 Асинхронный ввод/вывод и порты завершения Обзор методов асинхронного ввода/вывода Windows Перекрывающийся ввод/вывод Перекрывающиеся сокеты Следствия применения перекрывающегося ввода/вывода Структуры OVERLAPPED Состояния перекрывающегося ввода/вывода Отмена выполнения операций перекрывающегося ввода/вывода Пример: использование дескриптора файла в качестве объекта синхронизации Пример: преобразование файлов с использованием перекрывающегося ввода/вывода и множественной буферизации Расширенный ввод/вывод с использованием процедуры завершения Функции ReadFileEx, WriteFileEx и процедурызавершения Функции дежурного ожидания Выполнение процедуры завершения и возврат из функции дежурного ожидания Пример: преобразование файла с использованием расширенного ввода/вывода Асинхронный ввод/вывод сиспользованием нескольких потоков Таймеры ожидания Пример: использование таймера ожидания Комментарии к примеру с таймером ожидания Порты завершения ввода/вывода Управление портами завершения ввода/вывода Ожидание порта завершения ввода/вывода Отправка уведомления порту завершения ввода/вывода Альтернативы портам завершенияввода/вывода Пример: сервер, использующий порты завершения ввода/вывода Резюме В следующих главах Упражнения ГЛАВА 15 Безопасность объектов Windows Атрибуты безопасности Общий обзор средств безопасности: дескриптор безопасности Списки контроля доступа Использование объектов безопасности Windows Права объектов и доступ к объектам Инициализация дескриптора безопасности Управляющие флаги дескриптора безопасности Идентификаторы безопасности Работа с ACL Пример: использование разрешений на доступ в стиле UNIX к файлам NTFS Пример: инициализация атрибутов защиты Комментарии к программе 15.3 Чтение и изменение дескрипторов безопасности Пример: чтение разрешений на доступ к файлу Пример: изменение разрешений на доступ к файлу Защита объектов ядра и коммуникаций Защита именованных каналов Защита объектов ядра и приватных объектов Значения маски АСЕ Пример: защита процесса и его потоков Обзор дополнительных возможностей защиты объектов Удаление элементов АСЕ Абсолютные и самоопределяющиеся относительные дескрипторы безопасности Системные списки ACL Информация, хранящаяся в маркерах доступа Управление идентификаторами SID Протокол защищенных сокетов Резюме В следующей главе Дополнительная литература Упражнения ГЛАВА 16 Программирование в среде Win64 Нынешнее состояние Win64 Поддержка процессоров Поддержка Windows Поддержка сторонних компаний Обзор 64-разрядной архитектуры Необходимость в 64-битовой адресации Опыт UNIX Опыт перехода от 16-разрядных версий Windows к 32-разрядным Надолго ли хватит 64 бит? Модель программирования Win64 Цели Типы данных Типы данных фиксированной точности Типы данных, соответствующие точности указателей Пример: использование указательных типов данных Различия между Windows и UNIX Перенос имеющегося программного кода Изменения, связанные с использованием API Изменения, связанные с устранением неявных допущений относительно предполагаемых размеров элементов данных Пример: перенос программы sortMM (программа 5.5) Использование предупреждающих сообщений компилятора Код до подготовки к переносу Предупреждающие сообщения компилятора Предупреждающие сообщения и необходимые изменения, касающиеся других программ Резюме Дополнительная литература Упражнения ПРИЛОЖЕНИЕ А Использование примеров программ Структура каталогов Учебные пособия (слайды) Каталог Utility Каталог Include Распределение программ по главам Листинги включаемых файлов Дополнительные служебные программы ПРИЛОЖЕНИЕ Б Сопоставление функций Windows, UNIX и библиотеки С ПРИЛОЖЕНИЕ В Результаты измерения производительности Тестовые конфигурации Приложения Хост-системы Измерение производительности Копирование файлов Преобразование символов из кодировки ASCII в Unicode Поиск заданных комбинаций символов Сортировка файлов Множество потоков, соревнующихся между собой за обладание единственным ресурсом Выполнение тестов Библиография
Введение В этой книге описывается разработка приложений с использованием интерфейса прикладного программирования (Application Programming Interface, API) операционных систем Windows компании Microsoft, причем основное внимание уделяется базовым системным службам, включая управление файловой системой, процессами и потоками, межпроцессное взаимодействие, сетевое программирование и синхронизацию. Пользовательские интерфейсы, внутренние функции Windows и драйверы ввода/вывода в данной книге не рассматриваются, хотя сами по себе эти темы не менее важны и представляют не меньший интерес. Для примеров преимущественно выбирались реалистичные сценарии, и поэтому многие из них вполне могут служить в качестве основы для построения реальных приложений.
Win32/Win64 API, или обобщенно Windows API, поддерживаются семейством 32– и 64-разрядных операционных систем компании Microsoft, в которое в настоящее время входят Windows XP, Windows 2000 и Windows Server 2003. К числу ранних представителей этого семейства относятся операционные системы Windows NT, Windows Me, Windows 98 и Windows 95; в настоящее время эти системы считаются устаревшими, однако многие из приведенных в книге примеров программ способны выполняться и под их управлением. Вопросы перехода от платформы Win32 к развивающейся платформе Win64 обсуждаются по мере необходимости. Win64, поддерживаемый в качестве 64-разрядного интерфейса в некоторых версиях Windows Server 2003 и Windows XP, почти идентичен Win32.
Не вызывает сомнений, что Windows API является важнейшим фактором, который оказывает влияние на весь процесс разработки приложений, и во многих случаях вытесняет поддерживаемый операционными системами UNIX и Linux POSIX API, поскольку считается более предпочтительным или, по крайней мере, предоставляющим те же возможности для приложений, ориентированных на настольные и серверные системы. Поэтому многие опытные программисты заинтересованы в скорейшем изучении Windows API, и данная книга призвана содействовать этому.
Прежде всего, необходимо рассказать вам о том, что представляет собой Windows API, и показать, как им пользоваться в реальных ситуациях, причем этот рассказ должен быть как можно более кратким и не перегруженным излишними деталями. Поэтому данная книга предназначена не для использования в качестве справочного руководства, а для ознакомления с основными свойствами наиболее важных функций и демонстрации возможностей их применения в ситуациях практического программирования. Вооружившись этими знаниями, читатель сможет воспользоваться обширной справочной документацией, предоставляемой компанией Microsoft, для самостоятельного углубленного изучения отдельных вопросов, расширенных возможностей и менее приметных функций в соответствии с возникшими потребностями или заинтересованностью. Лично мне при таком подходе изучение Windows API далось легко, а разработка Windows-программ доставила огромное удовольствие, хотя и без неприятных минут также не обошлось. Мои порывы энтузиазма легко просматриваются в некоторых местах книги, что, собственно, и неудивительно. Впрочем, это вовсе не свидетельствует о том, что я безоговорочно соглашусь с превосходством Windows API над API других операционных систем (ОС), но относительно того, что у него есть масса положительных качеств, вряд ли кто-либо станет возражать.
Авторы многих книг, посвященных Windows, значительное внимание уделяют объяснению того, что представляют собой процессы, виртуальная память, межпроцессное взаимодействие, вытесняющий планировщик, но при этом не показывают, как все это используется в реальных ситуациях. Программистам, имеющим опыт работы с системами UNIX, Linux, IBM MVS, Open VMS и некоторыми другими ОС эти понятия уже знакомы, и они заинтересованы лишь в том, чтобы как можно быстрее перейти к изучению того, как эти возможности реализованы в Windows. К тому же, в большинстве книг по Windows важное место отводится методам программирования на основе пользовательского интерфейса. С целью концентрации внимания лишь на самых главных базовых возможностях, предоставляемых системой, в данной книге тема пользовательского интерфейса не затрагивается, и мы ограничиваемся обсуждением лишь простого консольного символьного ввода/вывода.
В соответствии с принятой в данной книге точке зрения Windows — это всего лишь API операционной системы, предоставляющий набор вполне понятных средств. Потребность в ускоренном изучении Windows испытывают многие программисты, независимо от уровня их опыта, и без знания Windows немыслимо обсуждение таких, например, тем, как модель компонентного объекта (Component Object Model, СОМ), разработанная компанией Microsoft. В некоторых отношениях системы Windows превосходят остальные системы, в других — отстают от них или находятся примерно на том же уровне. Задача данной книги состоит в том, чтобы продемонстрировать, как эффективнее всего использовать эти возможности в реальных ситуациях для разработки полезных, высококачественных и высокопроизводительных приложений.