Программирование на Visual C++. Архив рассылки - Алекс Jenter
Шрифт:
Интервал:
Закладка:
ПРИМЕЧАНИЕ
На самом деле, .publickeytoken описывает не контрольную сумму файла, а является хэшем (контрольной суммой) публичного ключа автора, создавшего сборку, на которую ссылается ключ .assembly extern.
Давайте "копнём" поглубжеКак же сборка устроена изнутри? Что у нее "под капотом"? Оказывается, не так все и страшно, как вам могло показаться. Сборка помещается внутри файла в формате PE (Portable Executable), то есть внутри DLL или EXE. Здесь все зависит от того, будет ли сборка самостоятельной программой или "библиотекой". Любая сборка импортирует функции из библиотеки mscoree.dll, которая является частью среды исполнения. Исполняемые файлы (EXE) импортируют из этой библиотеки функцию _CorExeMain, которую они вызывают для своего запуска. А происходит это так: как и в любом exe-файле, в нашем присутствует точка входа - это маленькая функция (6 байт), которая призвана передавать управление функции _CorExeMain из библиотеки mscoree.dll. Когда данная функция получает управление, она находит в exe-файле свою точку входа и начинает выполнение с нее. Вы можете проверить все сказанное мною сами при помощи утилиты dumpbin, запустив ее с параметрам /imports. Правда, у файла, скомпилированного на Managed C++, вы можете увидеть много других импортов. Не пугайтесь, это нормально, так как MC++ одновременно поддерживает как управляемые, так и неуправляемые данные (managed/unmanaged data). А значит, может делать самостоятельные системные вызовы в обход CLR.
Динамически загружаемые библиотеки импортируют функцию _CorDllMain, которую они вызывают из DllMain, "точки входа" DLL. Сама же функция точки входа ничего, кроме вызова _CorDllMain, не делает. С exe-сборками дело обстоит аналогичным образом, только вместо _CorDllMain, импортируется функция _CorExeMain.
Вот как выглядят точки входа в dll– в exe-сборки.
Dll сборка Exe сборка start proc near start proc near jmp ds:CorDllMain jmp ds:CorExeMain start endp start endpВ будущих версиях Windows Microsoft планирует изменить процесс загрузки, при котором реальная точка входа будет находиться не таким странноватым способом. Вы спросите: а почему нельзя было сделать сразу, нормально? Это на самом деле не такой простой вопрос, как кажется. Ведь новые исполняемые файлы, по сути дела, со старыми ничего общего не имеют, а надо сделать так, чтобы они могли запускаться существующими версиями Windows без изменения загрузчика файлов. Microsoft пошла по давно известному пути "оборачивание нового в старое", то есть сам exe-файл является оберткой, для реального исполняемого файла CLR. Благодаря этому подходу файлы могут запускаться на уже существующих версиях Windows без изменения их самих.
Сборка может состоять из следующих частей: манифест – метаданные, описывающие сборку, описание типов, код в виде промежуточного языка (IL) и набор ресурсов. Не все из них должны обязательно присутствовать в каждой сборке, кроме, разумеется, манифеста. Сборка также может быть разбита на несколько файлов. Для большей наглядности я нарисовал, как это все происходит.
Рис. 2
Как вы можете видеть, за пределами сборки можно помещать не только другие специальные файлы, которые тоже являются сборками, а любые другие файлы, какие вам захочется, к примеру, картинки. Это дает несколько преимуществ. Во-первых, вы можете обновлять отдельные файлы сборки, не прибегая к компиляции, во-вторых, как я уже говорил ранее, не имеет никакого значения, где размещены эти файлы. Внешние файлы подгружаются только по мере надобности, что позволяет оптимизировать сетевой трафик, если часть приложения находиться в сети. Тут даже можно немного схитрить: сделать основной сборку которая не несет в себе ничего, кроме зависимостей. Тогда вы сможете поставить вашу программу в малюсеньком файле, который, по мере надобности, скачает все, что ему нужно, из сети.
Управлениями версиями и изоляция Немного лирикиПо умолчанию COM-компоненты общедоступны. Я имею в виду, что для них присутствуют записи в реестре, с которым любой может делать все, что захочет, а также то, что большинство приложений хранит свои библиотеки в системных директориях, хотя Microsoft и не советует этого делать. То есть ни о какой изолированности приложений говорить не приходилось. Потенциально, любое приложение может быть приведено в неработоспособное состояние при обстоятельствах, никак от него не зависящих.
Концепция сборок предоставляет полную изолированность приложений (ну, почти полную). Сборки делятся на два типа:
• приватные (private) – те которые используются только самим приложением.
• совместные (shared) – те которые используются всеми.
Приватные сборки поставляются с самим приложением, используются только им и храниться в его папке. Microsoft рекомендует использовать совместные сборки только при крайней необходимости. Да, вы, конечно, можете сказать, что это нецелесообразно – с каждым приложение поставлять одни и те же сборки, можно ведь сделать сборку совместной, сэкономив тем самым немного места. Но на самом деле теперь, когда цена за мегабайт дискового пространства неуклонно уменьшается, а объем дисков неуклонно увеличивается, проблемы объема, занимаемого вашим приложением, не должны вас беспокоить. Собственно, здесь нужно выбирать между устойчивостью и небольшим увеличением эффективности в виде сохранения дискового пространства. Я лично думаю, что надо остановиться на первом. Хотя эта проблема может показаться для вас незначительной, на самом деле все очень серьёзно. Вдумайтесь: над решением этой проблемы компания Microsoft работает с выхода первых версий Windows и по сей день. И только сейчас в .NET были предложены четко стандартизированные и хорошо продуманные средства для решения этой проблемы. Хотя, как знать? Все еще может обернуться провалом, как это бывало и раньше.
Приватные сборкиПриватные сборки видны только самому приложению и никому более, то есть приложение изолируется от внешнего воздействия как других программ, так и самой операционной системы. Соответственно, приватные сборки лишены многих проблем, связанных с совместными сборками. К примеру, такой, как уникальность имен: так как сборка приватна, нет необходимости заботится об уникальности имен во всем глобальном пространстве имен. Концепция приватных сборок сильно упрощает развёртывание (инсталляцию) ваших приложений, так как больше не придется делать записей в реестре, подобных тем, которые вы делали ранее для регистрации ваших COM-компонентов. Теперь вы будете просто копировать ваши сборки в директорию вашего приложения или в подчиненные директории. Общая среда исполнения (CLR) при запуске вашего приложения прочитает его манифест и определит, какие сборки необходимы. Затем будет произведён процесс зондирования (probing) (звучит прямо как зомбирование :) директории вашего приложения на предмет нужной сборки, сборка соответственно определяется по имени файла, определенного в манифесте.
ПРИМЕЧАНИЕ
Для справки: процесс зондирования (или зомбирования – это как кому больше нравится) – это просто рекурсивный поиск в директории вашего приложения (то есть при поиске сборки просматриваются все поддиректории).
Среда исполнения может подходить к зондированию достаточно интеллектуально: к примеру, могут быть выбраны локализованные для данного региона сборки, если, конечно, они поставляются автором приложения. Как выбираются именно нужные сборки, я расскажу позднее.
Как я говорил ранее, в манифесте сборки указывается строгая информация о версии. Но для приватных сборок точное соответствие версий не навязывается средой исполнения, так как считается, что разработчик имеет полный контроль над своим приложением и, соответственно, может сам управлять версиями, если это ему нужно.
Совместные сборкиСреда исполнения .NET поддерживает также совместные сборки. Это сборки, которые могут быть использованы сразу несколькими приложениями и которые, соответственно, "видны" всем. Правда, к таким сборкам предъявляются более строгие правила, к приватным сборкам. Например, необходима уникальность имен сборки: имена внутри сборки не должны конфликтовать с уже существующими в глобальном пространстве имен, предоставляемом средой исполнения по умолчанию, хотя система и предоставляет сервисы защиты имен (protection of the name). Специально для реализации этого сервиса была разработана технология Shared Names (совместные имена), описываемая далее.
Действия системы управления версиями при поиске необходимых сборок, могут быть изменены при помощи политики версий, которую сможет изменять администратор или приложения. Данная политика позволит принудительно изменить версию сборки, запрашиваемой приложением, а также поведение среды разработки при поиске и загрузке сборок. То есть приложение можно заставить использовать сборку другой версии, даже если оно на это не рассчитано. Данная политика настраивается при помощи файла конфигурации, который помещается в каталог приложения и имеет то же имя, что и у приложения, только с расширением .config. Подробно формат этих файлов я сейчас описывать не буду.