【问题标题】:Thread(s) Memory Layout线程内存布局
【发布时间】:2016-03-13 21:39:23
【问题描述】:

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

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

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

我在网上看到这张图:

Threads memory layout

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

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

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

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

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

非常感谢。

【问题讨论】:

  • 一个线程的栈通常在 1MB 左右。只要您不创建数千个进程,使其适合一个进程的地址空间就没有问题。请注意,右图具有误导性,用户堆栈是用户地址空间的一部分。它的分配方式是您永远不必担心的操作系统实现细节。

标签: multithreading memory layout process


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 2013-08-11
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-26
    • 2013-07-12
    • 1970-01-01
    相关资源
    最近更新 更多