2015-11-26 3 views
6

Наличие простого .net-приложения .exe. Каков жизненный цикл после его выполнения. Я понимаю, что происходит следующее:Каков жизненный цикл приложения .net

> 1. OS loads exe assemblies into memory 
> 2. OS checks if it is in fact .net assembly 
> 3. mscoree.dll loads, and loads CLR 
> 4. CLR takes over and loads external dlls, GC stuff, memory management etc. 
> 5. CLR creates app domain where exe assemblies are loaded 
> 6. exe is started 

Учитывая вышеизложенное правильно (пожалуйста, не стесняйтесь подробно), я заинтересован в последней стадии, когда CLR нагрузок узлов.

  1. Сколько штабелей, куч, нитей создано ?. Создан ли поток и выполняется код внутри исполняемого файла?
  2. Каков размер выделенной исходной памяти ?, который выделяет память (ОС или CLR?)
  3. Как узнать, сколько памяти изначально требуется?
  4. Если требуется больше памяти при запуске exe, кто решает, сколько и когда выделить эту память?
  5. Что происходит, когда вы закрываете exe ?, CLR запускает любой GC прямо перед разгрузкой домена приложения? (закрытие exe), или же ОС?
+5

Просто купите книгу «CLR через C#» или прочитайте серию блога «CLR Inside Out». Это слишком широко, чтобы правильно ответить, и я уверен, что на каждый из ваших вопросов был дан ответ. – CodeCaster

ответ

1

Ну, сам процесс немного сложнее, чем вы писали. Некоторые из этапов включают в себя несколько больше, чем можно подумать - например, шаг 1 и то, как PE загружается (и сама загрузка mscoree.dll), включает внутренние шаги внутри.

Но, я постараюсь ответить на ваши вопросы. Просто обратите внимание, что ваши вопросы очень большие, поэтому я попытался кратко ответить на них. Но, если вы действительно заинтересованы в том, что я настоятельно рекомендую вам прочитать CLR через C# (от Рихтера). Он обсуждает процесс загрузки в первой главе и посвятил раздел сборщику мусора.

Есть также некоторые хорошие статьи MSDN об основах сборщика мусора, которые могут оказаться интересными.

Сколько штабелей, куч, нитей создано ?. Создан ли поток и выполняется код внутри исполняемого файла?

Простым (пустым) консольным приложением будет 3 потока: основная нить, резьба GC и резьба финализаторов. конечно, каждый поток имеет собственный стек (по 1 МБ).

Количество кучей зависит от типа GC, который вы используете. Если вы используете GC рабочей станции (по умолчанию), будет 1 управляемая куча (с двумя сегментами, одна для «нормальных» объектов и одна - большой кусок кучи объекта).

Если вы работаете с GC сервера, для каждого логического ядра, доступного в системе, будет 1 куча (каждая из кучек с двумя сегментами).

Каков размер исходной выделенной памяти ?, который выделяет память (OS или CLR?)

Исходная память состоит из более чем одного элемента: есть стек 1МБ для каждого потока , есть размер изображений, загруженных в процесс (который зависит от вашего приложения, конечно), и есть «динамический» элемент размера - распределения, которые вы создаете в своем приложении, которые заставляют GC увеличьте размер кучи и объекты, которые вы больше не используете, очищенные GC и могут привести к тому, что GC освободит память.

Если требуется больше памяти при работе exe, кто решает, сколько и когда выделить эту память?

Если у вас есть простое консольное приложение, внутри Main вы создаете экземпляр нового класса. В этом случае команда «нового» ключевого слова (CIL «newobj») заставит CLR вычислить требуемый объем памяти.

Если в генерации 0 достаточно памяти (где только что создан новый объект), дополнительного распределения памяти не будет. Если памяти недостаточно, GC запустится и вызовет VirtualAlloc для выделения памяти для объекта. Ссылка на новый созданный объект в этом сценарии будет сохранена в стеке.

Конечно, если ссылка сохранена (стек, куча, регистр процессора) и где выделены объекты (стеки/куча), могут различаться. В принципе, это зависит, если мы говорим о распределении класса или структуры, и каков контекст распределения (если он внутри метода, как поле в другом классе, поле в структуре и т. Д.). Он также может варьироваться в зависимости от платформы.

Если требуется больше памяти при работе exe, кто решает, сколько и когда выделить эту память?

Все выделение памяти для новых объектов, созданных в процессе управляется самой CLR (конечно, использование CLR Windows API, такие как VirtualAlloc и VirtualFree и окна управления самой виртуальной памяти).

Когда вы используете «новый» оператор для создания нового объекта, который должен быть создан в управляемой куче, CLR вычисляет размер, необходимый для выделения (размер всех полей + немного накладных расходов, необходимых для блокировки объектов ob и знаете, какой тип это) и посмотреть, есть ли свободное место в управляемой куче (в генерации 0 CLR всегда сохраняет указатель на то, где должны быть выделены новые объекты). Если это так, он использует его. в противном случае, если памяти недостаточно, начинается сбор мусора, а иногда (зависит от состояния памяти после процесса gc и некоторых других вещей). VirtualAlloc будет вызываться CLR, чтобы выделить больше памяти для процесса.

Что происходит, когда вы закрываете exe ?, CLR запускает любой GC прямо перед разгрузкой домена приложения? (закрытие exe), или же ОС?

CLR запускает быстрый GC перед выгрузкой любого домена приложения. Цель этого быстрого GC - дать финалистам шанс на запуск. При закрытии процесса CLR не нуждается в очистке памяти, потому что ОС все равно это делает.

Надеюсь, это поможет.

+0

# 3. Предположим, у вас есть новый словарь () в коде, отвечает ли основной поток (CLR) на это ?, увеличивает размер кучи? каков первоначальный размер кучи - перед чтением новой линии Dict? – ShaneKm

+0

отредактировал мой ответ, надеюсь, что он ответит ему немного больше ... –

+0

* Если вы работаете с GC сервера, будет 1 куча для каждого логического потока, доступного в системе * Предполагаю, вы имели в виду кучу для каждого логического ядра. –

8

Сколько штабелей, кучей, нитей создано?

В процессе, в котором работает приложение, может быть много потоков. Тем не менее, один из них будет основным потоком исполнения.

При создании потока выделяется 1 МБ стека.

, который выделяет память (OS или CLR?)

Как указано here

сборщик мусора общеязыковой среды выполнения управляет распределением и выделение памяти для приложения

Это значимая разница между управляемыми и не управляемые программы. Если вы запрограммировали либо на C, либо на C++, вы определенно знаете, что эта ответственность принадлежит разработчику, а не сборщику мусора. Это великая сила. Но с великой силой приходит большая ответственность. Вы несете ответственность за поиск (создание) необходимого объема памяти. Затем вы выделяете там свой объект и, когда вам это больше не нужно, вы должны освободить эту память. Любая ошибка, которая может быть выполнена в вышеупомянутом процессе, приводит к утечке памяти и даже к сбою вашей программы. Не говоря уже о трудностях устранения неполадок, подобных этому.

С другой стороны, в мире управляемых программ (C#, Java, JavaScript и т. Д.) Эта ответственность относится к части среды выполнения, которая называется сборщиком мусора. Сборщик мусора выделяет память и решает, когда наступит подходящее время для взлома и удаления мусора. Это от собственного - это отличное удобство, что значительно облегчает жизнь разработчика. Однако это компромисс. Управляемая программа не может повлиять на производительность хорошо структурированной не управляемой программы.

Что происходит, когда вы закрываете exe ?, CLR запускает любой GC справа перед выгрузкой домена приложения? (закрытие exe), или же ОС?

Когда вы закрываете исполняемый файл, одна из вещей, которые будут выполняться перед разгрузкой домена приложения, представляет собой сборку мусора в порядке использования любых используемых ресурсов. Затем область приложения будет выгружена. После этого CLR будет отделен от пространства памяти процесса и, наконец, процесс будет убит.

Смежные вопросы