Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows

         

Что нового в четвертом издании


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

чтобы Вы точно знали, что происходит за кулисами этой системы. Намного детальнее я рассказываю и о том, как взаимодействует с системой библиотека С/С++ (С/С++ run-time library) - особенно при создании и уничтожении процессов и потоков. Динамически подключаемым библиотекам я также уделяю больше внимания.

Помимо этих изменений, в книге появилась целая тонна нового содержания Упомяну лишь самое главное.

Новшества Windows 2000. Книгу было бы нельзя считать действительно переработанной, не будь в пей отражены новшества Windows 2000: объект ядра "задание" (job kernel object), функции для создания пула потоков (thread pooling functions), изменения в механизме планирования потоков (thread scheduling), расширения Address Windowing, вспомогательные информационные функции (toolhelp functions), разреженные файлы (sparse files) и многое другое Поддержка 64-разрядной Windows. В книге приводится информация, специфическая для 64-разрядной Windows; все программы-примеры построены с учетом специфики этой версии Windows и протестированы в ней. Практичность программ-примеров. Я заменил многие старые примеры новыми, более полезными в повседневной работе; они иллюстрируют решение не абстрактных, а реальных проблем программирования. Применение С++. По требованию читателей примеры теперь написаны на С++ В итоге они стали компактнее и легче для понимания Повторно используемый код. Я старался писать по возможности универсальный и повторно используемый код. Это позволит Вам брать из него отдельные функции или целые С++-классы без изменений (незначительная модификация может понадобиться лишь в отдельных случаях) Код на С++ гораздо проще для повторного использования. Утилита VMMap. Эта программа-пример из предыдущих изданий серьезно усовершенствована. Ее новая версия дает возможность исследовать адресное пространство любого процесса, выяснять полные имена (вместе с путями) любых файлов данных, спроецированных в адресное пространство процесса, копировать информацию из памяти в буфер обмена и (если Вы пожелаете) просматривать только регионы или блоки памяти внутри регионов. Утилита ProcessInfo. Это новая утилита. Она показывает, какие процессы выполняются в системе и какие DLL используются тем или иным модулем Как только Вы выбираете конкретный процесс, ProcessInfo может запустить утилиту VMMap для просмотра всего адресного пространства этого процесса. ProcessInfo позволяет также узнать, какие модули загружены в системе и какие исполняемые файлы используют определенный модуль. Кроме того, Вы сможете увидеть, у каких модулей были изменены базовые адреса из-за неподходящих значений. Утилита LISWatch. Тоже новая утилита. Она отслеживает общесистемные и специфические для конкретного потока изменения в локальном состоянии ввода. Эта утилита поможет Вам разобраться в проблемах, связанных с перемещением фокуса ввода в пользовательском интерфейсе Информация по оптимизации кода. В этом издании я даю гораздо больше информации о том, как повысить быстродействие кода и сделать его компактнее. В частности, я подробно рассказываю о выравнивании данных (data alignment), привязке к процессорам (processor affinity), кэш-линиях процессо-




pa (CPU cache lines), модификации базовых адресов (rebasing), связывании модулей (module binding), отложенной загрузке DLL (delay-loading DLLs) и др.

Существенно переработанный материал по синхронизации потоков.

Я полностью переписал и перестроил весь материал по синхронизации потоков. Теперь я сначала рассказываю о самых эффективных способах синхронизации, а наименее эффективные обсуждаю в конце Попутно я добавил новую главу, посвященную набору инструментальных средств, которые помогают решать наиболее распространенные проблемы синхронизации потоков

Детальная информация о форматах исполняемых файлов. Форматы файлов EXE- и DLL-модулей рассматриваются намного подробнее Я рассказываю о различных разделах этих модулей и некоторых специфических параметрах компоновщика, которые позволяют делать с модулями весьма интересные вещи. Более подробные сведения о DLL. Главы no DLL тоже полностью переписаны и перестроены Первая из них отвечает на два основных вопроса: "Что такое DLL?" и "Как ее создать?" Остальные главы по DLL посвящены весьма продвинутым и отчасти новым темам - явному связыванию (explicit linking), отложенной загрузке, переадресации вызова функции (function forwarding), перенаправлению DLL (DLL redirection) (новая возможность, появившаяся в Windows 2000), модификации базового адреса модуля (module rebasing) и связыванию. Перехват API-вызовов. Да, это правда За последние годы я получил столько почты с вопросами по перехвату API-вызовов (API hooking), что в конце концов решил включить эту тему в свою книгу, Я представлю Вам несколько C++классов, которые сделают перехват API-вызовов в одном или всех модулях процесса тривиальной задачей. Вы сможете перехватывать даже вызовы LoadLibrary и GetProcAddress от библиотеки С/С++ Более подробные сведения о структурной обработке исключений. Эту часть я тоже переписал и во многом перестроил Вы найдете здесь больше информации о необрабатываемых исключениях и увидите С++-класс - оболочку кода, управляющего виртуальной памятью за счет структурной обработки исключений (stiuctured exception handling) Я также добавил сведения о соответствующих приемах отладки и о том, как обработка исключений в С++ соотносится со структурной обработкой исключений Обработка ошибок. Это новая глава В ней показывается, как правильно перехватывать ошибки при вызове API-функций Здесь же представлены некоторые приемы отладки и ряд других сведений. Windows Installer. Чуть не забыл, программы-примеры (все они содержатся на прилагаемом компакт-диске) используют преимущества нового Windows Installer, встроенного в Windows 2000 Это позволит полностью контролировать состав устанавливаемого программного обеспечения и легко удалять больгае не нужные его части через апплет Add/Remove Programs в Control Panel Если Вы используете Windows 95/98 или Windows NT 40, программа Setup с моего компакт-диска сначала установит Windows Installer. Ho, разумеется, Вы можете и сами скопировать с компакт-диска любые интересующие Вас файлы
с исходным или исполняемым кодом.



операционная система потребительского класса. Она


Windows 98 - операционная система потребительского класса. Она обладает многими возможностями Windows 2000, но некоторые ключевые из них не поддерживает. Так, Windows 98 не отнесешь к числу отказоустойчивых (приложение вполне способно привести к краху системы), она менее защищена, работает только с одним процессором (что ограничивает ее масштабируемость) и поддерживает Unicode лишь частично.

Microsoft намерена ликвидировать ядро Windows 98, поскольку его доработка до уровня ядра Windows 2000 потребовала бы слишком много усилий. Да и кому нужно еще одно ядро Windows 2000? Так что Windows 2000 - это вроде бы надолго, a Windows 98 проживет года два-три, если не меньше.

Но почему вообще существует ядро Wmdows 98? Ответ очень прост; Windows 98 более дружественна к пользователю, чем Windows 2000 Потребители не любят регистрироваться ня своих компьютерах, не хотят заниматься администрированием и т. д. Плюс ко всему в компьютерные игры они играют чаще, чем сотрудники корпораций в рабочее время (впрочем, это спорно). Многие старые игровые программы обращаются к оборудованию напрямую, что может приводить к зависанию компьютера. Windows 2000 - операционная система с отказоустойчивым ядром - такого не по-

зволяет никому. Любая программа, которая пытается напрямую обратиться к оборудованию, немедленно завершается, не успев навредить ни себе, ни другим.

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

Готовя книгу, я старался обращать внимание на отличия реализаций Win32 API в Windows 98 и Windows 2000. Материалы такого рода я обводил рамками и, как показано ниже, помечал соответствующими значками - чтобы привлечь внимание читателей к каким-то деталям, характерным для той или иной платформы.

WINDOWS 98
Здесь рассказывается об особенностях реализации на платформе Windows 98.

WINDOWS 2000
А тут - об особенностях реализации на платформе Windows 2000.

Windows 95 я особо не рассматриваю, но все, что относится к Windows 98, применимо и к ней, так как ядра у них совершенно одинаковые.




это операционная система Microsoft класса


Windows 2000 - это операционная система Microsoft класса "high-end" Список ее возможностей и особенностей займет не одну страницу. Вот лишь некоторые из них (в совершенно произвольном порядке).

Windows 2000 рассчитана на рабочие станции и серверы, а также на применение в центрах обработки данных Отказоустойчива - плохо написанные программы не могут привести к краху системы. Защищена - несанкционированный доступ к ресурсам (например, файлам или принтерам), управляемым этой системой, невозможен. Богатый набор средств и утилит для администрирования системы в масштабах организации. Ядро Windows 2000 написано в основном на С и С++, поэтому система легко портируется (переносится) на процессоры с другими архитектурами. Полностью поддерживает Unicode, что упрощает локализацию и работу с использованием различных языков. Имеет высокоэффективную подсистему управления памятью с чрезвычайно широкими возможностями. Поддерживает структурную обработку исключений (structured exception handling, SEH), облегчая восстановление после ошибок. Позволяет расширять функциональность зa счет динамически подключаемых библиотек (DLL). Поддерживает многопоточность и мультипроцессорную обработку, обеспечивая высокую масштабируемость системы, Файловая система Windows 2000 дает возможность отслеживать, как пользователи манипулируют с данными на своих машинах.


Ядро Windows CE


Windows CE - самое новое ядро Windows от Microsoft Оно рассчитано главным образом на карманные и автомобильные компьютеры, "интеллектуальные" терминалы, тостеры, микроволновые печи и торговые автоматы. Большинство таких устройств должно потреблять минимум электроэнергии, у них очень мало памяти, а дисков чаще всего просто нет. Из-за столь жестких ограничений Microsoft пришлось создать совершенно новое ядро операционной системы, намного менее требовательное к памяти, чем ядро Windows 98 или Windows 2000.
Как ни странно, Windows CE довольно мощная операционная система. Устройства, которыми она управляет, предназначены только для индивидуального использования, поэтому ее ядро не поддерживает администрирование, масштабирование и т. д. Тем не менее практически все концепции Win32 применимы и к данной платформе. Различия обычно проявляются там, где Windows CE накладывает ограничения на те или иные Win32-функции



Сегодняшние Windows-платформы


Сейчас Microsoft поставляет операционные системы Windows с тремя ядрами. Каждое ядро оптимизировано под свои виды вычислительных задач. Microsoft пытается переманить разработчиков программного обеспечения на Windows-платформы, утверждая, что интерфейс прикладного программирования (application programming interface, APT) у каждой из них одинаков. Это означает лишь то, что, научившись писать Windows-приложения для одного ядра, Вы поймете, как сделать то же самое для остальных.

Поскольку я объясняю, как писать Windows-приложения на основе Windows API, то теоретически все, о чем Вы узнаете из моей книги, применимо ко всем трем ядрам. На самом деле они сильно отличаются друг от друга, и поэтому одни и те же функции соответствующих операционных систем реализованы по-разному. Скажем так: базовые концепции одинаковы, но детали могут различаться.
Начнем с того, что представляют собой эти три ядра Windows.



Содержимое компакт-диска и требования к системе


Компакт-диск, прилагаемый к книге, содержит исходный код и исполняемые файлы всех программ-примеров. Эти программы написаны и скомпилированы с использованием Microsoft Visual C++ 6.0. Большая их часть будет работать в Windows 95, Windows 98, Windows NT 4.0 и Windows 2000, но некоторые программы требуют такую функциональность, которая поддерживается только Windows NT 4.0 и Windows 2000. Если Вы захотите самостоятельно скомпилировать какие-то примеры, Вам понадобится Microsoft Visual C++ 6.0.

В корневом каталоге компакт-диска находится общий заголовочный файл (Cmnhdr.h) и около трех десятков каталогов, в которых хранятся соответствующие программыпримеры. В каталогах x86 и Alpha32 содержатся отладочные версии тех же программ - их можно запускать прямо с компакт-диска.

Вставив компакт-диск в привод CD-ROM, Вы увидите окно Welcome. Если оно не появится, перейдите в каталог Setup на компакт-диске и запустите файл PressCDx86.exe или PressCDAlpha32.exe (в зависимости от того, какой процессор в Вашем компьютере).

Техническая поддержка

Microsoft Fress публикует исправления на http://mspress.microsoft.com/support

Если у Вас есть какие-нибудь комментарии, вопросы или идеи, касающиеся моей книги, пожалуйста, направляйте их в Microsoft Press по обычной или электронной почте:

Microsoft Press
Attn: ProgrammingApplicationsforMicrosoft Windows, 4lh cd., editor
One Microsoft Way
Redmond, WA 98052-6399
mspinput@microsoft.com



В этой книге нет ошибок


Этот заголовок отражает лишь то, что я хотел бы сказать. Но все мы знаем: это полное вранье. Мои редакторы и я очень старались без ошибок донести до Вас новую, точную и глубокую информацию в простом для понимания виде. Увы, даже собрав самую фантастическую команду, никто не застрахован от проколов. Найдете какуюнибудь ошибку в этой книге, сообщите мне на http://www.JeffreyRichter.com - буду крайне признателен.



Завтрашние Windows-платформы (64-разрядная Windows 2000)


Будущее уже совсем близко Когда я пишу эти строки, Microsoft напряженно трудится над переносом ядра Windows 2000 на 64-разрядную платформу. Предполагается, что эта истинно 64-разрядная операционная система получит название 64-bit Windows 2000 (64-разрядная Windows 2000). На первых порах она будет работать на процессорах Alpha (архитектура AXP64) от Compaq, а чуть позжс и на новых процессорах Itanium (архитектура IA-64) от Intel.

Процессоры Alpha всегда были 64-разрядными. Так что, если у Вас есть машина с одним из этих процессоров, Вы просто установите 64-разрядную Windows 2000 и получите полноценную 64-разрядную программно-аппаратную платформу. Процес-

соры Intel серии Pentium (и более ранние) имеют 32-разрядную архитектуру (IA-32) Машины с такими процессорами не смогут работать с 64-разрядной Windows 2000. Intel сравнительно недавно закончил разработку новой 64-разрядной архитектуры процессоров и сейчас готовит к выпуску процессор Iranium (его кодовое название было Merced). Поставка машин на базс Itanium ожидается уже в 2000 году.
Меня очень интересует 64-разрядная Windows 2000, и я давно готовлюсь к се появлению. Сейчас на Web-узле Microsoft можно найти много статей о 64-разрядной Windows 2000 и о том, какие изменения она принесет разработчикам программного обеспечения С радостью сообщаю Вам следующее.

Ядро 64-разрядной Windows 2000 получено в результате портирования ядра 32-разрядной версии. А значит, все, что Вы узнали о 32-разрядной Windows 2000, применимо и к 64-разрядной. В сущности, Microsoft так модифицировала исходный код 32-разрядной Windows, что из него можно получить как 32-, так и 64-разрядную систему. Таким образом, у них теперь одна база исходного кода, и любые новшества или исправления будут вноситься в обе системы одновременно. Поскольку эти ядра построены на одном кодс и одинаковых концепциях, Windows API идентичен на обеих платформах. Следовательно, Ваши приложения потребуют лишь минимальной модификации. Если перенос 32-разрядных приложений так легок, то вскоре появится масса инструментальных средств (вроде Microsoft Developer Studio), поддерживающих разработку 64-разрядного программного обеспечения. Конечно, 64-разрядная Windows сможет выполнять и 32-разрядныс приложения. Но, судя по обещаниим, истинно 64-разрядные приложения будут работать в ней гораздо быстрее. Вам не придется учиться заново. Вы обрадуетесь, узнав, что большинство типов данных осталось 32-разрядным. Это относится к целым типам, DWORD, LONG, BOOL и т. д По сути, беспокоиться следует лишь об указателях и некоторых описателях, так как теперь они являются 64-разрядными.

Сведений о том, как подготовить исходный код к выполнению на 64-разрядной платформе, вполне хватает и на Web-узле Microsoft, так что я в эти детали вдаваться не буду. Но, что бы я ни писал в каждой главе, я все время помнил о 64-разрядной Windows и, где это было нужно, включал специфическую для нее информацию. Кроме того, все приведенные в этой книге программы-примеры я компилировал с использованием 64-разрядного компилятора, что позволило мне протестировать их на очень раннсй версии 64-разрядной Windows 2000 для процессоров Alpha. Если Вы будете следовать тем же правилам, что и я, Вам не составит труда создать единую базу исходного кода своих приложений для 32- и 64-разрядной Windows.