Процесс управляемого выполнения
Процесс управляемого исполнения включает следующие шаги, которые подробно разбираются позднее в этом разделе:
Выбор компилятора.
Чтобы воспользоваться преимуществами среды CLR, необходимо использовать один или несколько языковых компиляторов, обращающихся к среде выполнения.
Компиляция кода в MSIL.
При компиляции исходный код преобразуется в MSIL и создаются необходимые метаданные.
Компиляция инструкций MSIL в машинный код.
Во время выполнения JIT-компилятор преобразует инструкции MSIL в машинный код. Во время этой компиляции выполняется проверка кода и метаданных MSIL с целью установить, можно ли для них определить, является ли код типобезопасным.
Выполнение кода.
Среда CLR предоставляет инфраструктуру, обеспечивающую выполнение кода, и ряд служб, которые можно использовать при выполнении.
Выбор компилятора
Чтобы воспользоваться преимуществами, предоставляемыми средой CLR, необходимо применить один или несколько языковых компиляторов, ориентированных на среду выполнения, например компилятор Visual Basic, C#, Visual C++, F# или один из многочисленных компиляторов от независимых разработчиков, например компилятор Eiffel, Perl или COBOL.
Поскольку среда выполнения является многоязычной, она поддерживает широкий набор разнообразных типов данных и языковых средств. Доступные средства среды выполнения определяются используемым языковым компилятором, и разработчики создают код с использованием этих средств. Используемый в коде синтаксис определяется компилятором, а не средой выполнения. Если компонент должен быть полностью доступен для компонентов, написанных на других языках, то экспортируемые этим компонентом типы должны предоставлять исключительно языковые функции, включенные в состав Спецификация CLS (CLS). Атрибут CLSCompliantAttribute позволяет гарантировать, что код является CLS-совместимым. Дополнительные сведения см. в разделе Написание CLS-совместимого кода.
К началу
Компиляция в MSIL
При компиляции в управляемый код компилятор преобразует исходный код в промежуточный язык Microsoft (MSIL), представляющий собой независимый от процессора набор инструкций, который можно эффективно преобразовать в машинный код. Язык MSIL включает инструкции для загрузки, сохранения, инициализации и вызова методов для объектов, а также инструкции для арифметических и логических операций, потоков управления, прямого доступа к памяти, обработки исключений и других операций. Перед выполнением код MSIL необходимо преобразовать в код для конкретного процессора, обычно с помощью JIT-компилятора. Поскольку среда CLR предоставляет для каждой поддерживаемой компьютерной архитектуры один или несколько JIT-компиляторов, один набор инструкций MSIL можно компилировать и выполнять в любой поддерживаемой архитектуре.
Когда компилятор создает код MSIL, одновременно создаются метаданные. Метаданные содержат описание типов в коде, включая определение каждого типа, сигнатуры каждого члена типа, члены, на которые есть ссылки в коде, а также другие сведения, используемые средой выполнения во время выполнения. MSIL и метаданные содержатся в переносимом исполняемом (PE) файле, который основывается на форматах Microsoft PE и COFF, ранее использовавшихся для исполняемого контента, но при этом расширяет их возможности. Этот формат файлов, позволяющий размещать код MSIL или машинный код, а также метаданные, позволяет операционной системе распознавать образы среды CLR. Наличие в файле метаданных наряду с MSIL позволяет коду описывать себя. Это устраняет потребность в библиотеках типов и языке IDL. Среда выполнения находит и извлекает метаданные из файла по мере необходимости при выполнении.
К началу
Компиляция MSIL в машинный код
Перед запуском MSIL его необходимо скомпилировать в машинный код в среде CLR для архитектуры конечного компьютера. Платформа .NET Framework предоставляет два способа такого преобразования:
JIT-компилятор платформы .NET Framework;
.NET Framework Ngen.exe (генератор образов в машинном коде).
Компиляция с помощью JIT-компилятора
При JIT-компиляции язык MSIL преобразуется в машинный код во время выполнения приложения по требованию, когда загружается и выполняется содержимое сборки. Поскольку среда CLR предоставляет JIT-компилятор для каждой поддерживаемой архитектуры процессора, разработчики могут создавать набор сборок MSIL, которые могут компилироваться с помощью JIT-компилятора и выполняться на разных компьютерах с разной архитектурой. Если управляемый код вызывает специфический для платформы машинный API или библиотеку классов, то он будет выполняться только в соответствующей операционной системе.
При JIT-компиляции учитывается возможность того, что определенный код может никогда не вызываться во время выполнения. Чтобы не тратить время и память на преобразование всего содержащегося в PE-файле MSIL в машинный код, при компиляции MSIL преобразуется в машинный код по мере необходимости во время выполнения. Полученный таким образом машинный код сохраняется в памяти, что позволяет использовать его при дальнейших вызовах в контексте этого процесса. Загрузчик создает и присоединяет заглушки к каждому методу в типе, когда тип загружается и инициализируется. При первом вызове метода заглушка передает управление JIT-компилятору, который преобразует MSIL для этого метода в машинный код и заменяет заглушку на созданный машинный код. Поэтому последующие вызовы метода, скомпилированного с помощью JIT-компилятора, ведут непосредственно к машинному коду.
Создание кода во время установки с помощью NGen.exe
Тот факт, что JIT-компилятор преобразует MSIL-код сборки в машинный код при вызове отдельных методов, определенных в этой сборке, отрицательно сказывается на производительности во время выполнения. В большинстве случаев снижение производительности приемлемо. Что более важно, код, созданный JIT-компилятором, будет привязан к процессу, вызвавшему компиляцию. Его нельзя сделать общим для нескольких процессов. Чтобы созданный код можно было использовать в нескольких вызовах приложения или в нескольких процессах, которые совместно используют набор сборок, среда CLR предоставляет режим предварительной компиляции. В таком режиме компиляции для преобразования сборок MSIL в машинный код в стиле JIT-компилятора используется программа Ngen.exe (генератор образов в машинном коде). Однако, работа Ngen.exe отличается от JIT-компилятора в трех аспектах.
Ngen.exe выполняет преобразование из MSIL-кода в машинный код перед выполнением приложения, а не во время его выполнения.
При этом сборка компилируется целиком, а не по одному методу за раз.
Она сохраняет созданный код в кэше образа машинного кода в виде файла на диске.
Проверка кода
В процессе компиляции в машинный код MSIL-код должен пройти проверку, если только администратор не установил политику безопасности, разрешающую пропустить проверку кода. MSIL-код и метаданные проверяются на типобезопасность. Это подразумевает, что код должен обращаться только к тем адресам памяти, к которым ему разрешен доступ. Типобезопасность помогает изолировать объекты друг от друга и способствует их защите от непредумышленного или злонамеренного повреждения. Она также гарантирует надежное применение условий безопасности для кода.
Среда выполнения основывается на истинности следующих утверждений для поддающегося проверке типобезопасного кода:
ссылка на тип строго совместима с адресуемым типом;
для объекта вызываются только правильно определенные операции;
удостоверения являются подлинными.
В процессе проверки кода MSIL делается попытка подтвердить, что код может получать доступ к расположениям в памяти и вызывать методы только через правильно определенные типы. Например, код не должен разрешать доступ к полям объекта так, чтобы можно было выходить за границы расположения в памяти. Кроме того, проверка определяет, правильно ли был создан код MSIL, поскольку неверный код MSIL может приводить к нарушению правил строгой типизации. В процессе проверки передается правильно определенный типобезопасный код. Однако иногда типобезопасный код может не пройти проверку из-за ограничений процесса проверки, а некоторые языки по своей структуре не позволяют создавать поддающийся проверке типобезопасный код. Если в соответствии с политикой безопасности использование типобезопасного кода является обязательным и код не проходит проверку, то при выполнении кода создается исключение.
К началу
Выполнение кода
Среда CLR предоставляет инфраструктуру, обеспечивающую управляемое выполнение кода, и ряд служб, которые можно использовать при выполнении. Перед выполнением метода его необходимо скомпилировать в код для конкретного процессора. Каждый метод, для которого создан MSIL-код, компилируется с помощью JIT-компилятора при первом вызове и затем запускается. При следующем вызове метода будет выполняться существующий JIT-скомпилированный код. Процесс JIT-компиляции и последующего выполнения кода повторяется до завершения выполнения.
Во время выполнения для управляемого кода доступны такие службы, как сборка мусора, обеспечение безопасности, взаимодействие с неуправляемым кодом, поддержка отладки на нескольких языках, а также поддержка расширенного развертывания и управления версиями.
В Microsoft Windows XP и Windows Vista загрузчик операционной системы выполняет поиск управляемых модулей путем анализа бита в заголовке COFF. Установленный бит обозначает управляемый модуль. При обнаружении управляемых модулей загружается библиотека Mscoree.dll, а подпрограммы _CorValidateImage и _CorImageUnloading уведомляют загрузчик о загрузке и выгрузке образов управляемых модулей. Подпрограмма _CorValidateImage выполняет следующие действия:
Проверяет, является ли код допустимым управляемым кодом.
Заменяет точку входа в образе на точку входа в среде выполнения.
В 64-разрядных системах Windows _CorValidateImage изменяет образ, находящийся в памяти, путем преобразования его из формата PE32 в формат PE32+.
К началу
См. также
Ссылки
Основные понятия
Метаданные и компоненты с самоописанием
Развертывание .NET Framework и приложений