Конфиденциальные сведения о Windows. Балансировка известных библиотек DLL
Функция
Windows, неофициально называемая «известные библиотеки DLL» (Known DLLs), является списком библиотек DLL (библиотек динамической компоновки), которые обрабатываются особым образом с помощью загрузчика модулей ядра. Если загрузчик в момент загрузки видит программу с динамической связью с известной библиотекой DLL, то эта копия известной библиотеки будет использована немедленно, исключая процедуру поиска, которая обычно выполняется при загрузке модулей.
Можно подумать, что это является функцией безопасности (хотя, по общему признанию, очень слабой), но в действительности безопасность никогда не была назначением этой функции. Функция известных библиотек DLL относится только к производительности.
Механизм работы функции известных библиотек DLL менялся со временем. В некоторых версиях
Windows® ядро использует список известных библиотек DLL в качестве отправной точки, после чего просматривает все библиотеки DLL, с которыми связаны известные библиотеки DLL, затем — библиотеки DLL, с которыми связаны эти библиотеки, и так далее. Этот процесс образует транзитивное замыкание всех зависимостей и обрабатывает их все как известные. В других версиях
Windows такое транзитивное замыкание не строится, вместо этого только явно указанные библиотеки обрабатываются как известные библиотеки DLL. В некоторых версиях
Windows известные библиотеки DLL загружаются ядром предварительно, в момент запуска системы; в других версиях такая предварительная загрузка не производится, и ядро просто использует данный список, чтобы оградить себя от трудностей при поиске путей к библиотекам DLL.
От версии к версии менялось не только представление списка известных библиотек DLL. Содержимое раздела реестра KnownDLLs также подвергалось изменению. Группа производительности
Windows изменяет как список известных DLL, так и правила, по которым этот список преобразуется в набор библиотек DLL, исходя из понимания того, каким образом приложения используют систему
Windows. Как это бывает обычно при проектировании, такие решения являются результатом компромисса. Предварительная загрузка известных библиотек DLL при запуске системы дает возможность приложениям, использующим эти библиотеки, запускаться быстрее, но за это приходится платить. Это требует большего времени запуска системы, возрастает потребление памяти, поскольку указанные библиотеки DLL остаются в памяти вне зависимости от того, используются они или нет. Производительности одних компонентов увеличивается за счет других. Как видно, точное достижение баланса является трудной задачей: этот процесс требует постоянной подстройки, поскольку картина использования постоянно изменяется.
Один из результатов использования известных библиотек DLL, который может показаться не столь очевидным, состоит в том, что известные библиотеки имеют приоритет перед локально переадресуемыми библиотеками DLL. (Мы рассматривали локально переадресуемые библиотеки DLL в январском выпуске этой рубрики за 2007 г.). Если поразмыслить об этом, то можно понять, что такое поведение является ожидаемым. В конце концов, цель указания списка известных библиотек DLL состоит в том, чтобы исключить процедуру поиска путей и тем самым ускорить загрузку библиотек. Если потребуется, чтобы ядро проверило локально зарегистрированные библиотеки DLL, это может привести лишь к замедлению. Можно было бы предположить, что добавление к пути поиска всего одного каталога не имеет большого значения, но если этот каталог оказывается сетевым сервером, расположенным на другой стороне земного шара, добавление всего одного каталога может вызвать огромные потери производительности.
Хотите верьте, хотите нет, но мы изучали программы, работа которых зависит от того, какие библиотеки DLL объявлялись известными. Одна программа содержала файл с именем Version.dll, расположенный в каталоге приложения. В обычных условиях эта закрытая копия файла Version.dll должна была замещать копию файла в системном каталоге, но в ОС
Windows XP библиотека Version.dll была указана как известная. Это привело к тому, что копия библиотеки в каталоге приложения игнорировалась, а использовалась копия библиотеки, находившаяся в системном каталоге.
В системе
Windows Vista® библиотека Version.dll не объявлена как известная библиотека DLL, возможно, потому что сотрудники группы производительности решили, что приложения не использовали ее настолько часто, чтобы оправдать затраты. В результате программа переставала работать в системе
Windows Vista, поскольку приложение фактически надеялось, что ядро проигнорирует библиотеку DLL, которую программа установила в своем каталоге. Программа преднамеренно устанавливала библиотеку DLL в путь поиска, а затем переключалась на
Windows, чтобы игнорировать ее! Конечно, если бы требовалось, чтобы система
Windows игнорировала файл, то намного более эффективным решением было бы просто не устанавливать этот файл в первом месте. В итоге, компания, которая разрабатывала эту программу, сообщила об ошибке, утверждая, что нашла дыру в безопасности.
Рэймонд Чен (Raymond Chen) на своем веб-узле The Old New Thing (Хорошо забытое старое) и в книге с таким же названием (издательство Addison-Wesley, 2007 г.) рассказывает об истории развития
Windows и касается вопросов программирования в среде Win32. Какого размера футболки он сейчас носит, не знает даже он сам.
Компьютер и Windows