multithreading - 线程内存布局

标签 multithreading memory layout process

我了解进程内存布局的外观(代码、数据、堆、堆栈)。

但是,我不明白具有多个线程的程序的内存布局到底是什么样的。

毕竟,该进程有一个堆栈,所以我会假设所有线程都以某种方式共享同一个堆栈..
但这似乎不对,因为每个线程都有自己的堆栈,并且线程并不能保证按照它们被调用的顺序执行,因此将它们一一放入进程堆栈对我来说没有多大意义。

我在网上看到这张图:

Threads memory layout

这里似乎每个线程都有自己的堆栈,这是有道理的,也有自己的内核堆栈。

这是否意味着我有(使用图片)3个“过程”? (假设一个进程地址空间是 4GB,那么 3 个线程将是 12GB?我认为不是..)

我想了解每个线程的堆栈在内存中的位置。

我知道所有线程共享数据和代码段,所以我假设堆将包含线程的堆栈,或者它们将位于内核空间中。

我真的很想知道会发生什么。。

许多赞赏。

最佳答案

首先,让我们明确区分这两个定义。进程实际上是一个隔离容器,可以容纳系统资源(如套接字、互斥锁等),并且可以在其中执行环境线程。该进程没有堆栈并且不接收 CPU 时间(不可调度)。相反,线程是操作系统内核执行的调度单元。线程定期接收 quant 的 CPU 时间以取得进展,并有一个堆栈来存储时间数据(局部变量和返回地址)。

第一点注意:虚拟地址空间是进程抽象的核心部分。每个进程都有自己的虚拟地址空间,每个虚拟地址空间只属于一个进程。
第二个注意事项:进程中运行的所有线程共享该进程的所有资源。因此,同一进程的所有线程共享相同的地址空间。每个线程都能够访问另一个线程可以访问的每个内存字节。一个线程甚至可以访问另一个线程堆栈上的局部变量。

在旧的 UNIX 中,只有一个抽象——一个进程。但是从现代的观点来看,我们可以说 UNIX 坚持了 1 对 1 模型(每个进程都有一个且只有一个线程)。由于这种 1 对 1 模型,UNIX 能够在内存中修复堆栈位置。目前采用的 1 对 N 模型(单个进程多个线程)假设没有这样的固定堆栈位​​置。相反,操作系统内核负责在请求创建线程时为堆栈定位空间,并在线程终止时释放该空间。此外,如果内核在查找空闲的进程虚拟地址空间 block 时失败,甚至可以拒绝线程创建请求。

维持不间断线程执行的假象。内核跟踪每个线程的指令和堆栈指针。当内核在 CPU 上加载线程(给线程执行 CPU 时间)时,它会加载特殊的 CPU 寄存器,其中包含内核为该特定线程维护的指令和堆栈指针。当内核从 CPU 卸载线程时,它会将这些指针存储在内核内存中。这样一来,内核就会产生一种错觉,即每个线程都有自己独立的堆栈,因为线程本身不需要处理这个堆栈指针操作。事实上,我们可以说每个线程都有自己的地址空间部分,逻辑上分配给他,但进程中的每个人都可以物理访问,但每个线程都有自己的私有(private)堆栈指针。

关于multithreading - 线程内存布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34164854/

相关文章:

c++ - Windows 操作系统中的线程安全和原子读取

c - memset 设置值不正确

c++ - 缓存未命中是否与我们是否使用堆内存相关?

perl - 我可以让 Windows 中的 Perl ithreads 并发运行吗?

c - 如何在 C/C++ 中写入不同线程的堆栈?

c# - PaintEvent内存泄漏

ios - 在约束属性中找不到为 UIView 创建的约束

html - 如何在背景图片下显示文字?

html - 为移动设备设计网页界面

c# - 如何使用 TPL 在 C# 中编码(marshal)对特定线程的调用