C# · 12月 23, 2021

c# – .net应用程序的生命周期是什么

有一个简单的.net .exe应用程序.一旦执行它的生命周期是什么.我的理解是发生以下情况: > 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加载程序集时的最后一步感兴趣.

>创建了多少堆栈,堆,线程?是否创建了线程并执行可执行文件中的代码?
>分配的初始内存大小是多少?谁分配内存(OS或CLR?)
>它如何知道最初需要多少内存?
>如果exe运行时需要更多内存,谁决定分配这个内存多少以及何时分配?
>关闭exe时会发生什么?CLR在卸载App Domain之前是否运行任何GC? (关闭exe),还是操作系统?

解决方法 好吧,这个过程本身比你写的要复杂一些.一些步骤包括多个人可能想到的 – 例如,步骤1以及PE如何加载(以及mscoree.dll本身加载)包括内部步骤.

但是,我会尽力回答你的问题.请注意你的问题有点大,所以我试着简单回答一下.但是,如果您真的对此感兴趣,我强烈建议您通过C#(Richter)阅读CLR.他在第一章讨论了加载过程,并专门介绍了垃圾收集器.

还有一些关于垃圾收集器基础知识的MSDN文章,你可能会感兴趣.

How many stacks,heaps,threads are created?. Is the thread created and that executes the code within the executable?

简单(空)控制台应用程序将有3个线程:主线程,GC线程和终结器线程.当然,每个线程都有自己的堆栈(每个1MB).

堆的数量取决于您使用的GC类型.如果您正在使用Workstation GC(默认值),则将有1个托管堆(具有2个段,一个用于“普通”对象,一个是大对象堆段).

如果您正在使用Server GC,则系统中可用的每个逻辑核心将有1个堆(每个堆有两个段).

What is the size of the initial memory allocated?,who allocates the memory (OS or CLR?)

初始内存由多个元素组成:每个线程有1MB堆栈,在进程中加载​​的图像大小(当然取决于您的应用程序),并且有“动态”元素. size – 您在应用程序中进行的分配,导致GC增加堆大小,以及您不再使用的对象由GC清理并可能导致GC释放内存.

If more memory is needed when the exe runs,who decides how much and when to allocate this memory?

如果你有一个简单的控制台应用程序,那么在Main中你可以创建一个新类的实例.在这种情况下,“new”关键字(CIL“newobj”指令)将使CLR计算所需的内存量.

如果第0代(存储新创建的对象)中有足够的内存,则不会有额外的内存分配.如果内存不足,GC将启动并调用VirtualAlloc为对象分配内存.在该场景中,新创建对象的引用将保存在堆栈中.

当然,保存引用的位置(堆栈,处理器寄存器)和分配对象(堆栈/堆)的位置可能会有所不同.基本上,这取决于我们是在谈论类或结构的分配,以及分配的上下文(如果它在内部方法中,作为其他类中的字段,结构中的字段等).它也可以根据平台而有所不同.

If more memory is needed when the exe runs,who decides how much and when to allocate this memory?

在您的进程中创建的新对象的所有内存分配都由CLR本身管理(当然,CLR使用Windows API,如VirtualAlloc和VirtualFree,以及管理虚拟内存本身的窗口).

当您使用“new”运算符创建应在托管堆中创建的新对象时,CLR会计算分配所需的大小(锁定ob对象所需的所有字段的大小,并知道它的类型是)并查看托管堆中是否有可用空间(在第0代中,CLR始终保留指向应分配新对象的位置的指针).如果是这样,它就会使用它.否则,如果没有足够的内存,垃圾收集开始,有时(取决于gc进程后的内存状态,以及其他一些东西)CLR将调用VirtualAlloc为进程分配更多内存.

What happens when you close the exe?,does the CLR run any GC right before unloading the App Domain? (closing exe),or does the OS?

CLR在卸载任何app-domain之前运行快速GC.这个快速GC的目的是让最终版本有机会运行.关闭进程时,CLR不需要清理内存,因为操作系统无论如何都会这样做.

希望能帮助到你.