╔════════╗ ╔════════╗ ╔═══════╗
║ Code ║ ║ Data ║ ║ Stack ║
╚════════╝ ╟────────╢ ╚═══════╝
╔════════╗ ║ BSS ║
║ ROdata ║ ╟────────╢
╚════════╝ ║ Heap ║
╔════════╗ ╚════════╝
║ Libs ║
╚════════╝
brk()
或 sbrk()
系统调用进行扩展)。在类POSIX的系统(如Linux),以及大多数其他系统中,进程可以通过(匿名)内存映射获得额外的“堆”。/proc/self/maps
(或 /proc/PID/maps
对于进程的进程 ID 为 PID
)伪文件描述了进程拥有的所有内存映射。如果我们运行 cat /proc/self/maps
,我们可以看到 cat
进程本身的映射。在我的机器上(一个运行在 x86-64 架构上的 64 位 Linux),它显示:
00400000-0040c000 r-xp 00000000 08:05 2359392 /bin/cat
0060b000-0060c000 r--p 0000b000 08:05 2359392 /bin/cat
0060c000-0060d000 rw-p 0000c000 08:05 2359392 /bin/cat
0215f000-02180000 rw-p 00000000 00:00 0 [heap]
7f735b70f000-7f735c237000 r--p 00000000 08:05 658950 /usr/lib/locale/locale-archive
7f735c237000-7f735c3f6000 r-xp 00000000 08:05 1179825 /lib/x86_64-linux-gnu/libc-2.23.so
7f735c3f6000-7f735c5f6000 ---p 001bf000 08:05 1179825 /lib/x86_64-linux-gnu/libc-2.23.so
7f735c5f6000-7f735c5fa000 r--p 001bf000 08:05 1179825 /lib/x86_64-linux-gnu/libc-2.23.so
7f735c5fa000-7f735c5fc000 rw-p 001c3000 08:05 1179825 /lib/x86_64-linux-gnu/libc-2.23.so
7f735c5fc000-7f735c600000 rw-p 00000000 00:00 0
7f735c600000-7f735c626000 r-xp 00000000 08:05 1179826 /lib/x86_64-linux-gnu/ld-2.23.so
7f735c7fe000-7f735c823000 rw-p 00000000 00:00 0
7f735c823000-7f735c825000 rw-p 00000000 00:00 0
7f735c825000-7f735c826000 r--p 00025000 08:05 1179826 /lib/x86_64-linux-gnu/ld-2.23.so
7f735c826000-7f735c827000 rw-p 00026000 08:05 1179826 /lib/x86_64-linux-gnu/ld-2.23.so
7f735c827000-7f735c828000 rw-p 00000000 00:00 0
7ffeea455000-7ffeea476000 rw-p 00000000 00:00 0 [stack]
7ffeea48b000-7ffeea48d000 r--p 00000000 00:00 0 [vvar]
7ffeea48d000-7ffeea48f000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
r-xp
),只读数据(r--p
)和已初始化数据(rw-p
)。进程可以使用sbrk()
扩展的数据段(或"堆")是第三个(即sbrk(0)
将返回0x60d000
)。r-xp
)、一个通常无法访问的映射,某种方式被C库使用/需要(---p
),只读数据(r--p
)和已初始化数据(rw-p
)。rw-p
),是单独的数据段或堆。ld.so
。同样,有一个代码段(r-xp
),只读数据段(r--p
)和已初始化数据段(rw-p
)。
[stack]
段是初始线程的堆栈。 (cat
是单线程的,所以它只有一个线程。) [vvar]
段由内核提供(允许进程直接访问某些内核提供的数据,而不必承担系统调用的开销)。[vdso]
和[vsyscall]
段由内核提供,用于加速不需要完整上下文切换即可完成的系统调用。
因此,正如您所看到的,完整的图像要更加分散,但也更加自由(更加自由形式),而不是老式C和操作系统书籍所描述的那样。