我想知道当我在.NET中产生一个新的线程时,场景背后究竟发生了什么,如下所示:
Thread t = new Thread(DoWork); //I am not interested in DoWork per se t.Start();
1.在CLR和Windows内核中创build了哪些线程相关的对象?
2.为什么需要这些对象?
3.在x86,x64 Windows上分配多less托pipe/非托pipe内存(堆和堆栈)?
UPDATE
我正在寻找像pipe理线程对象这样的对象 ,这是我认为是,但也许还有一些其他额外的pipe理对象; 内核线程对象 , 用户线程环境块等。
非常感谢!
奇怪的未经处理的exception
在屏幕上自动点击鼠标
Mono在Ubuntu上抛出OutOfMemoryException,而不是OSX或Windows
进程启动作为域pipe理员从用户启动进程与UAC在域networking中激活
我怎样才能使菜单forms留在屏幕上,在所有其他应用程序的顶部?
强制.NET的Windows应用程序。 以英文forms显示数字
下一个Windows Server是否支持.NET 2.0?
使用VisualStyles控件的边框颜色
CefSharp不运行在Windows 7中
如何在Linux环境下运行.net应用程序?
分配的Win32和内核内存
我不太确定.NET部分是如何工作的,但是如果运行时确实决定使用操作系统创建一个真正的线程,它最终会调用kernel32.dll中的Win32 API CreateThread ,可能来自mscorlib.ni.dll
默认情况下,新线程获得堆栈的1MB虚拟地址,根据需要进行提交。 这可以通过maxStackSize参数进行控制。 主线程的堆栈大小来自可执行文件本身的一个参数。
在进程的地址空间中, TEB (线程环境块)将被分配( 另请参阅 )。 顺便提一下,x86上的FS寄存器指向了线程本地存储和结构化异常处理(SEH)之类的东西。 有可能是由Win32分配的其他东西没有记录。
在创建Win32线程时,将联系Win32服务器进程(csRSS.exe)。 您可以看到,csRSS具有对Process Explorer中的所有Win32进程和线程开放的处理以进行某种记帐。
在进程中加载的DLL将被通知新的线程,并可能分配自己的内存来跟踪线程。
内核将从内核非分页池创建一个ETHREAD [ layout ](从KTHREAD派生)对象来跟踪线程的状态。 还会分配一个内核堆栈(x86的缺省值为12k),可以将其分页(除非线程处于内核模式等待状态)。
为什么这么多事情需要为一个线程分配内存
线程是操作系统提供的最小的预先计划的单元,并且有很多上下文连接到它们。 许多不同的组件需要为每个线程提供单独的上下文,因为系统服务需要能够同时处理多个执行不同事情的线程。
一些服务要求你明确地向它们声明新的线程,但大多数服务需要自动处理新的线程。 有时候这意味着在线程启动时分配空间。 当线程调用其他服务时,用于跟踪线程的内存量可以随着这些服务为线程设置自己的上下文而增加。
分配了多少内存
很难说为一个线程分配了多少内存,因为它分布在多个地址空间和堆中。 它在Windows版本,已安装的组件和当前加载到进程中的内容之间会有所不同。
一般认为最大的成本是新线程默认使用的1MB的地址空间,但是即使是这个限制,也可以允许在单个进程中使用数百个而不用空间不足。
如果设计使用的操作系统线程多于系统中的cpu数量,则应该审查。 带有线程池和轻量级线程的工作队列(用户模式使用光纤或其他库的实现进行调度)应该能够处理多线程,而不需要过多的操作系统线程,从而使线程的内存成本变得不重要。
所以这是一个非常复杂的问题,并没有真正的答案“x”。
CLR不需要将单个CLR线程映射到单个OS光纤。 所以…这很难回答。 我认为当前版本的.NET(4.0)尽可能在所有操作系统上尝试使用CLR线程和OS光纤之间的1对1关系。 以前的.NET版本(更像<= 1.1)我不确定在所有的操作系统上都是如此。 调度程序处理大部分这些对象,它们不会成为任何.NET对象图的一部分。 这个调度程序是CLR的一部分,而不是Thread对象的一部分。 如果你深入了解IL,你会看到许多内部调用的实际执行。
我假设的问题是“为什么需要这些对象?” 如果是这样,那是因为操作系统主机必须有光纤来执行该线程的代码。 ThreadPool使用可以大大降低每次创建它们的成本。
对不起…取决于。 很多它也是非托管的,这意味着操作系统主机可以根据负载和系统版本的不同来处理这个问题。
“一个控制线程的逻辑抽象被类库中的System.Threading.Thread对象的实例捕获。 http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf
所以EMCA标准真的没有说这个话题。 但幸运的是,我们有…
“由于CLR线程对象是按光纤进行传输的,任何挂起的信息也是按光纤进行的,Thread.ManagedThreadId返回一个稳定的ID,它与CLR线程一起流动,不依赖于物理OS线程的标识,这意味着使用它意味着没有形式的亲和力,运行在同一个线程上的不同光纤返回不同的ID。“来自Joe Duffy http://www.bluebytesoftware.com/blog/2006/11/10/FibersAndTheCLR.aspx
看这里 ; 托管(即CLR)原语与非托管(即NT内核)原语之间的映射可能会回答您的大部分问题。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。