为什么VSIZE对于64位Linux进程来说要大得多?

ksc*_*der 8 linux memory-management

我的基本问题是为什么64位进程的VSIZE比为32位编译的完全相同的程序大得多?

以下是32位进程的/ proc/<pid>/maps文件的输出.

00148000-00149000 r-xp 00000000 00:00 0               [vdso]
00149000-002d2000 r-xp 00000000 fd:02 8914142         /lib/libc-2.12.so
002d2000-002d3000 ---p 00189000 fd:02 8914142         /lib/libc-2.12.so
002d3000-002d5000 r--p 00189000 fd:02 8914142         /lib/libc-2.12.so
002d5000-002d6000 rw-p 0018b000 fd:02 8914142         /lib/libc-2.12.so
002d6000-002d9000 rw-p 00000000 00:00 0 
005c9000-005da000 r-xp 00000000 fd:02 17059392        /tmp/vsizetest/lib/libtesting.so
005da000-005db000 rw-p 00010000 fd:02 17059392        /tmp/vsizetest/lib/libtesting.so
005db000-0061b000 rw-p 00000000 00:00 0 
00661000-00689000 r-xp 00000000 fd:02 8917713         /lib/libm-2.12.so
00689000-0068a000 r--p 00027000 fd:02 8917713         /lib/libm-2.12.so
0068a000-0068b000 rw-p 00028000 fd:02 8917713         /lib/libm-2.12.so
00694000-006ab000 r-xp 00000000 fd:02 8917680         /lib/libpthread-2.12.so
006ab000-006ac000 r--p 00016000 fd:02 8917680         /lib/libpthread-2.12.so
006ac000-006ad000 rw-p 00017000 fd:02 8917680         /lib/libpthread-2.12.so
006ad000-006af000 rw-p 00000000 00:00 0 
006e5000-00703000 r-xp 00000000 fd:00 3150403         /lib/ld-2.12.so
00703000-00704000 r--p 0001d000 fd:00 3150403         /lib/ld-2.12.so
00704000-00705000 rw-p 0001e000 fd:00 3150403         /lib/ld-2.12.so
00983000-009a0000 r-xp 00000000 fd:02 8914997         /lib/libgcc_s-4.4.5-20110214.so.1
009a0000-009a1000 rw-p 0001d000 fd:02 8914997         /lib/libgcc_s-4.4.5-20110214.so.1
00ca5000-00d86000 r-xp 00000000 fd:02 6300601         /usr/lib/libstdc++.so.6.0.13
00d86000-00d8a000 r--p 000e0000 fd:02 6300601         /usr/lib/libstdc++.so.6.0.13
00d8a000-00d8c000 rw-p 000e4000 fd:02 6300601         /usr/lib/libstdc++.so.6.0.13
00d8c000-00d92000 rw-p 00000000 00:00 0 
08048000-08049000 r-xp 00000000 fd:02 21134666        /tmp/vsizetest/bin/testvsz
08049000-0804a000 rw-p 00000000 fd:02 21134666        /tmp/vsizetest/bin/testvsz
09b8d000-09bae000 rw-p 00000000 00:00 0               [heap]
f7796000-f779c000 rw-p 00000000 00:00 0 
ff998000-ff9ae000 rw-p 00000000 00:00 0               [stack]
Run Code Online (Sandbox Code Playgroud)

这导致总VSIZE为3656.

以下是64位进程的/ proc/<pid>/maps文件的输出.

00400000-00401000 r-xp 00000000 fd:02 21134667              /tmp/vsizetest/bin64/testvsz
00600000-00601000 rw-p 00000000 fd:02 21134667              /tmp/vsizetest/bin64/testvsz
02301000-02322000 rw-p 00000000 00:00 0                     [heap]
3b7c800000-3b7c820000 r-xp 00000000 fd:00 661349            /lib64/ld-2.12.so
3b7ca1f000-3b7ca20000 r--p 0001f000 fd:00 661349            /lib64/ld-2.12.so
3b7ca20000-3b7ca21000 rw-p 00020000 fd:00 661349            /lib64/ld-2.12.so
3b7ca21000-3b7ca22000 rw-p 00000000 00:00 0 
3b7cc00000-3b7cd86000 r-xp 00000000 fd:00 661350            /lib64/libc-2.12.so
3b7cd86000-3b7cf86000 ---p 00186000 fd:00 661350            /lib64/libc-2.12.so
3b7cf86000-3b7cf8a000 r--p 00186000 fd:00 661350            /lib64/libc-2.12.so
3b7cf8a000-3b7cf8b000 rw-p 0018a000 fd:00 661350            /lib64/libc-2.12.so
3b7cf8b000-3b7cf90000 rw-p 00000000 00:00 0 
3b7d000000-3b7d083000 r-xp 00000000 fd:00 661365            /lib64/libm-2.12.so
3b7d083000-3b7d282000 ---p 00083000 fd:00 661365            /lib64/libm-2.12.so
3b7d282000-3b7d283000 r--p 00082000 fd:00 661365            /lib64/libm-2.12.so
3b7d283000-3b7d284000 rw-p 00083000 fd:00 661365            /lib64/libm-2.12.so
3b7d800000-3b7d817000 r-xp 00000000 fd:00 661352            /lib64/libpthread-2.12.so
3b7d817000-3b7da16000 ---p 00017000 fd:00 661352            /lib64/libpthread-2.12.so
3b7da16000-3b7da17000 r--p 00016000 fd:00 661352            /lib64/libpthread-2.12.so
3b7da17000-3b7da18000 rw-p 00017000 fd:00 661352            /lib64/libpthread-2.12.so
3b7da18000-3b7da1c000 rw-p 00000000 00:00 0 
3b7e000000-3b7e007000 r-xp 00000000 fd:00 661361            /lib64/librt-2.12.so
3b7e007000-3b7e206000 ---p 00007000 fd:00 661361            /lib64/librt-2.12.so
3b7e206000-3b7e207000 r--p 00006000 fd:00 661361            /lib64/librt-2.12.so
3b7e207000-3b7e208000 rw-p 00007000 fd:00 661361            /lib64/librt-2.12.so
3b87000000-3b87016000 r-xp 00000000 fd:00 664219            /lib64/libgcc_s-4.4.6-20110824.so.1
3b87016000-3b87215000 ---p 00016000 fd:00 664219            /lib64/libgcc_s-4.4.6-20110824.so.1
3b87215000-3b87216000 rw-p 00015000 fd:00 664219            /lib64/libgcc_s-4.4.6-20110824.so.1
3d44c00000-3d44ce8000 r-xp 00000000 fd:00 3019214           /usr/lib64/libstdc++.so.6.0.13
3d44ce8000-3d44ee8000 ---p 000e8000 fd:00 3019214           /usr/lib64/libstdc++.so.6.0.13
3d44ee8000-3d44eef000 r--p 000e8000 fd:00 3019214           /usr/lib64/libstdc++.so.6.0.13
3d44eef000-3d44ef1000 rw-p 000ef000 fd:00 3019214           /usr/lib64/libstdc++.so.6.0.13
3d44ef1000-3d44f06000 rw-p 00000000 00:00 0 
7f30ab397000-7f30ab39c000 rw-p 00000000 00:00 0 
7f30ab39c000-7f30ab3ad000 r-xp 00000000 fd:02 21127804      /tmp/vsizetest/lib64/libtesting.so
7f30ab3ad000-7f30ab5ac000 ---p 00011000 fd:02 21127804      /tmp/vsizetest/lib64/libtesting.so
7f30ab5ac000-7f30ab5ad000 rw-p 00010000 fd:02 21127804      /tmp/vsizetest/lib64/libtesting.so
7f30ab5ad000-7f30ab5ee000 rw-p 00000000 00:00 0 
7f30ab606000-7f30ab609000 rw-p 00000000 00:00 0 
7fff69512000-7fff69528000 rw-p 00000000 00:00 0             [stack]
7fff695ff000-7fff69600000 r-xp 00000000 00:00 0             [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall]
Run Code Online (Sandbox Code Playgroud)

这导致VSIZE为18480.

两个映射之间的主要区别是64位数据中的以下条目:

3b7cd86000-3b7cf86000 ---p 00186000 fd:00 661350             /lib64/libc-2.12.so
3b7d083000-3b7d282000 ---p 00083000 fd:00 661365             /lib64/libm-2.12.so
3b7d817000-3b7da16000 ---p 00017000 fd:00 661352             /lib64/libpthread-2.12.so
3b7e007000-3b7e206000 ---p 00007000 fd:00 661361             /lib64/librt-2.12.so
3b87016000-3b87215000 ---p 00016000 fd:00 664219             /lib64/libgcc_s-4.4.6-20110824.so.1
3d44ce8000-3d44ee8000 ---p 000e8000 fd:00 3019214            /usr/lib64/libstdc++.so.6.0.13
7f30ab3ad000-7f30ab5ac000 ---p 00011000 fd:02 21127804       /tmp/vsizetest/lib64/libtesting.so
Run Code Online (Sandbox Code Playgroud)

其中18480 VSIZE占14316.

对其他程序的其他实验似乎表明,在64位中,您似乎为进程使用的每个共享库获得了这些私有的,不可读的,不可写的,不可执行的内存块之一,而在32位中几乎没有任何这些块.

有谁知道这些内存是什么?

注意:根据类似问题的一些答案,这些内存区域来自Linux进程?,这不是一个多线程进程,它已经编译-fPIC.

alc*_*chi 8

VSIZE的主要区别在于如何在32位和64位版本的情况下完成共享库的PROT_NONE映射(模式"--- p").

这些正是您发现产生差异的映射.

通常,对于每个加载的共享库,我们将有四个映射:

3b7cc00000-3b7cd86000 r-xp 00000000 fd:00 661350            /lib64/libc-2.12.so
3b7cd86000-3b7cf86000 ---p 00186000 fd:00 661350            /lib64/libc-2.12.so
3b7cf86000-3b7cf8a000 r--p 00186000 fd:00 661350            /lib64/libc-2.12.so
3b7cf8a000-3b7cf8b000 rw-p 0018a000 fd:00 661350            /lib64/libc-2.12.so
Run Code Online (Sandbox Code Playgroud)

第一个是具有可执行权限的代码段,第二个是PROT_NONE(模式---)映射(可能无法访问页面),最后两个是数据段(只读部分和读写).

PROT_NONE的大小为MAXPAGESIZE,因此在32位和64位版本中创建的大小不同.在32位版本的情况下,它具有4KB大小(对于i386是MAXPAGESIZE),在64位版本的情况下是2MB(对于x86_64系统是标准MAXPAGESIZE).

应该注意的是,这个内存实际上并没有消耗(它只占用了地址空间的地址),如下所示:

http://www.greenend.org.uk/rjk/tech/dataseg.html

"这个附加功能不会花费你任何RAM或交换空间,只是每个进程内的地址空间,这在64位平台上供应充足.其根本原因是保持库有效共享,但实现有点奇."

只是最后一招,我发现使用pmap实用程序比检查映射文件更容易检查内存映射,并生成更简单的读取输出:

基本信息:

pmap <PID>
Run Code Online (Sandbox Code Playgroud)

有关扩展信息:

pmap -x <PID>
Run Code Online (Sandbox Code Playgroud)


9mj*_*mjb 1

[这不是一个真正的答案......超出我的知识范围]

如果内存段确实是“私有、不可读、不可写、不可执行”,那么它们永远不应该被引用,即使它们存在于虚拟内存空间中,它们也永远不会占用任何真实内存,因此没什么好担心的。(?)

这一定是某种簿记或碎片问题。由于它们是共享库 (*.so) 的一部分,因此它们就是构建这些库的方式。除了链接到这些库之外,它实际上与您的程序无关。除非您想重建这些库,或者不使用它们,否则没有什么可做的(并且无论如何也没有太多收获,因为它们无论如何都不应该使用真正的内存)。

也许有关?Linux 进程中的这些内存区域有何用途

@caf 说一些“---p”的内存段是“保护页”。

这表明它们的存在只是为了捕获杂散指针或堆栈增长到远错误...有点像内存中的硬分隔符,以便系统可以捕获常见错误并停止处理,而不是让这些常见错误溜走(这是一个致命错误根本不会引用它们,而且它们实际上永远不会使用任何真实的内存)。