线程有不同的堆栈和堆?

时间:2014-12-09 16:58:05

标签: c++ c linux multithreading

线程有自己的堆栈,但共享相同的堆[请参阅:Do threads have a distinct heap?]。

但是,有人可以解释以下程序的输出吗?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

void f(void)
{
    char *pt = malloc(1024);
    printf("     f(). stack: %p, malloc: %p\n", &pt, pt);
}

void *thread_func(void *i)
{
    char *pt = malloc(1024);
    printf("thread(). stack: %p, malloc: %p\n", &pt, pt);
    return NULL;
}

int main(void)
{
    char *pt = malloc(1024);

    printf("  main(). stack: %p, malloc: %p\n", &pt, pt);
    f();
    pthread_t thread1, thread2;
    pthread_create(&thread1, NULL, thread_func, NULL);
    pthread_create(&thread2, NULL, thread_func, NULL);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    while(1);
    return 0;
}

[/tmp/t1]$ a.out
  main(). stack: 0x7fff9bedff88, malloc: 0x1527010      -> using same stack and heap with f()
     f(). stack: 0x7fff9bedff48, malloc: 0x1527420      -> using same stack and heap with main()
thread(). stack: 0x7f3c67378ea8, malloc: 0x7f3c580008c0 -> own stack and heap? (first thread)
thread(). stack: 0x7f3c67d79ea8, malloc: 0x7f3c600008c0 -> own stack and heap? (second thread)

$ pmap 106202
106202:   a.out
0000000000400000      4K r-x--  /tmp/t1/a.out
0000000000600000      4K rw---  /tmp/t1/a.out
0000000001527000    132K rw---    [ anon ]              -> heap for main() and f()
0000003c57200000    128K r-x--  /lib64/ld-2.12.so
0000003c5741f000      4K r----  /lib64/ld-2.12.so
0000003c57420000      4K rw---  /lib64/ld-2.12.so
0000003c57421000      4K rw---    [ anon ]
0000003c57600000   1576K r-x--  /lib64/libc-2.12.so
0000003c5778a000   2044K -----  /lib64/libc-2.12.so
0000003c57989000     16K r----  /lib64/libc-2.12.so
0000003c5798d000      4K rw---  /lib64/libc-2.12.so
0000003c5798e000     20K rw---    [ anon ]
0000003c57e00000     92K r-x--  /lib64/libpthread-2.12.so
0000003c57e17000   2048K -----  /lib64/libpthread-2.12.so
0000003c58017000      4K r----  /lib64/libpthread-2.12.so
0000003c58018000      4K rw---  /lib64/libpthread-2.12.so
0000003c58019000     16K rw---    [ anon ]
00007f3c58000000    132K rw---    [ anon ]               -> malloc (first thread)
00007f3c58021000  65404K -----    [ anon ]
00007f3c60000000    132K rw---    [ anon ]               -> malloc (second thread)
00007f3c60021000  65404K -----    [ anon ]
00007f3c66979000      4K -----    [ anon ]
00007f3c6697a000  10240K rw---    [ anon ]               -> stack (10240K) (first thread)
00007f3c6737a000      4K -----    [ anon ]
00007f3c6737b000  10252K rw---    [ anon ]               -> stack (10252K?) (second thread)
00007f3c67d88000      8K rw---    [ anon ]
00007fff9becc000     84K rw---    [ stack ]              -> stack for main() and f()
00007fff9bf42000      4K r-x--    [ anon ]
ffffffffff600000      4K r-x--    [ anon ]
 total           157776K

似乎两个线程有​​不同的堆栈和堆。

另一个问题是ulimit -s显示10240,但是一个线程的堆栈是10240K,另一个是10252K。

该程序在64位计算机上运行。操作系统:红帽企业Linux服务器版本6.4(圣地亚哥),内核:2.6.32,以及gcc:4.4.7。

感谢。

----更新:

使用32位操作系统(Ubuntu 12.04),发现两个线程只有一个堆区域。但它仍然是一个与main()和f()堆不同的区域。

任何人都可以尝试使用自己的机器进行验证吗?

在上面的链接和其他资源中,人们说所有线程都有一个堆,因为线程必须共享数据。任何人都可以举例说明两个线程如何通过堆共享数据?如果32位操作系统有一个堆并且线程可以用来共享,那么原始64位操作系统示例中的不同堆如何呢?

感谢。

1 个答案:

答案 0 :(得分:2)

最重要的部分:堆是一个实现细节,就像堆栈一样,并且有许多不同的方法来实现它。

实际上,桌面或服务器环境的每个严肃实现都将使用某种线程本地存储,因为您希望最小化同步开销。对于一个众所周知的示例,请参阅tcmalloc。因此,分配最终将在地址空间的不同部分结束并不特别令人惊讶(尽管即使使用简单的malloc也可以相对容易地进行分配 - 例如,首先适用于免费列表)