创建线程时Linux进程内存增长问题

3

创建线程时,使用pthread_create函数,通过top和ps命令可以看到内存地址空间显著增长,如下所示:

线程的堆栈大小已经明确设置,因此这很好,在pmap中可以看到。

但我无法解释的是65404 KB的增加量? 这是Linux内核映射还是什么?

线程的detachstate属性也被设置,即使它在<1秒内完成,内存映射仍然存在于pmap中。

这是否仅仅是Linux内存管理的一部分,一旦映射就可以重新使用?可以调整65M的增加量吗?这是单线程情况,当同时创建多个线程时,报告的进程地址空间占用量急剧增加。10个线程,650M的膨胀在进程地址空间中报告。

...shared libs
...shared libs
2adf40000000 (132 KB)  rw-p (00:00 0)        <--- stack size for the thread.
2adf40021000 (65404 KB)  ---p (00:00 0)      <--- what is this? 
7ffcb8bed000 (128 KB)  rwxp (00:00 0)        [stack]
7ffcb8c0d000 (4 KB)    rw-p (00:00 0)        
7ffcb8dc6000 (8 KB)    r--p (00:00 0)        [vvar]
7ffcb8dc8000 (8 KB)    r-xp (00:00 0)        [vdso]
ffffffffff600000 (4 KB)  r-xp (00:00 0)      [vsyscall]
mapped:   116172 KB writable/private: 1140 KB shared: 0 KB

谢谢。
编辑:
所以我添加了第二个线程,现在pmap显示:
2adf40000000 (132 KB)  rw-p (00:00 0)        
2adf40021000 (65404 KB)  ---p (00:00 0)      
2adf44000000 (132 KB)  rw-p (00:00 0)        
2adf44021000 (65404 KB)  ---p (00:00 0)      
7ffcb8bed000 (128 KB)  rwxp (00:00 0)        [stack]
7ffcb8c0d000 (4 KB)    rw-p (00:00 0)        
7ffcb8dc6000 (8 KB)    r--p (00:00 0)        [vvar]
7ffcb8dc8000 (8 KB)    r-xp (00:00 0)        [vdso]   
ffffffffff600000 (4 KB)  r-xp (00:00 0)      [vsyscall]
mapped:   181840 KB writable/private: 1400 KB shared: 0 KB

现在有两个堆栈和65M的区域,这两个都增加了报告的虚拟地址空间。

编辑: 环境:glibc: ldd(Ubuntu EGLIBC 2.19-0ubuntu6.6)2.19和内核为4.4.103


我的猜测是为了适应页面大小而进行的填充。但我还不能确认... - Fabien Bouleau
1
看看权限,里面没有映射任何东西,也没有实际使用的内存。这只是保留的地址空间。如果我必须猜测,我会猜测这是为了能够在将来扩展堆栈而保留的空间。或者只是一个红色区域,以使缓冲区溢出不太可能意外地溢出到其他线程堆栈中。 - Art
1
@Art:如果是这样的话,它们似乎应该在栈下面而不是上面。 - R.. GitHub STOP HELPING ICE
值得一提的是,strace 可能是确定这些映射是如何产生的有用工具。您还应该指定您正在使用的确切内核和 glibc 版本(如果您正在使用已修补它们的硬化发行版,则几乎肯定与正在发生的事情相关)。 - R.. GitHub STOP HELPING ICE
由于栈向下(低地址)增长,因此它位于栈的上方(高地址)。因此,不应为栈保留它。我想知道是否为 TLS(线程本地存储)保留了它。由于动态库可能会分配新的 TLS 变量,必须为进一步加载库保留内存空间。 - Zang MingJie
显示剩余2条评论
1个回答

3

在这里找到了答案(链接),它是每个线程的竞技场,主要用于减少malloc锁定。

线程:在Linux早期,dlmalloc被用作默认的内存分配器。但由于ptmalloc2的线程支持,它成为Linux的默认内存分配器。线程支持有助于提高内存分配器性能,从而提高应用程序性能。在dlmalloc中,当两个线程同时调用malloc时,只有一个线程可以进入关键部分,因为freelist数据结构在所有可用线程之间共享。因此,在多线程应用程序中,内存分配需要时间,导致性能下降。而在ptmalloc2中,当两个线程同时调用malloc时,立即分配内存,因为每个线程维护一个单独的堆段,因此维护这些堆的freelist数据结构也是单独的。为每个线程维护单独的堆和freelist数据结构的行为称为每个线程的竞技场。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接