简短回答:是的,每个进程都有自己的堆栈(必须是
这种情况,因为每个正在运行的实体都必须有一个)和堆。
长答案:继续阅读。
地址空间
每个进程都拥有一个地址空间,其中一部分是堆栈和
堆。代码和全局数据(只读和读写)也是
包含在该地址空间中。
当我说一个进程拥有一个地址空间时,这意味着一个
进程不能窥视另一个进程的地址空间。这
内存保护是在硬件中完成的,使用一种叫做
内存管理单元 (MMU),通常是 CPU 的一部分。一
可以说地址空间是硬件的抽象
实现细节称为 MMU。
所说的抽象——地址空间——赋予每个进程感知
它有一个可用的线性字节数组,编号从 0 到
2^64-1(在 64 位系统上)。现代系统很少配备
有这么大的内存,所以通常只有该地址的一部分
空间由物理内存支持。
每当一个进程访问在其内部无效的内存时
地址空间,它被终止:它崩溃了。一个抽象的
崩溃(人们喜欢抽象的软件)正在接收信号 -
SIGSEGV(“分段违规”)在无效内存的情况下
访问。
/proc 文件系统
一种称为proc 的特殊文件系统通常安装在
/proc。为了演示地址空间及其布局,我开始了一个
任意程序,
$ sleep 10000&
[1] 12010
在后台启动它 (&) 会给我进程 ID,我
用于 cd 进入/proc 中的进程目录,
$ cd /proc/12010
请注意,/proc 不是磁盘上的目录,而是某个
有一个有趣的名称(进程 ID),看起来像一个目录,是一个
目录,并具有呈现给用户的文件和子目录
进程的属性。在这里,我们感兴趣的是
地址空间的内存布局 - 地址中的有效区域
空间。
这是 `/proc/PID/maps 文件显示的内容,
$ cat maps
55b782825000-55b782827000 r--p 00000000 fd:00 1180965 /usr/bin/sleep
55b782827000-55b78282b000 r-xp 00002000 fd:00 1180965 /usr/bin/sleep
55b78282b000-55b78282d000 r--p 00006000 fd:00 1180965 /usr/bin/sleep
55b78282e000-55b78282f000 r--p 00008000 fd:00 1180965 /usr/bin/sleep
55b78282f000-55b782830000 rw-p 00009000 fd:00 1180965 /usr/bin/sleep
55b783115000-55b783136000 rw-p 00000000 00:00 0 [heap]
7ff262d19000-7ff26fcfe000 r--p 00000000 fd:00 1188440 /usr/lib/locale/locale-archive
7ff26fcfe000-7ff26fd23000 r--p 00000000 fd:00 1183177 /usr/lib64/libc-2.30.so
7ff26fd23000-7ff26fe72000 r-xp 00025000 fd:00 1183177 /usr/lib64/libc-2.30.so
7ff26fe72000-7ff26febc000 r--p 00174000 fd:00 1183177 /usr/lib64/libc-2.30.so
7ff26febc000-7ff26febd000 ---p 001be000 fd:00 1183177 /usr/lib64/libc-2.30.so
7ff26febd000-7ff26fec0000 r--p 001be000 fd:00 1183177 /usr/lib64/libc-2.30.so
7ff26fec0000-7ff26fec3000 rw-p 001c1000 fd:00 1183177 /usr/lib64/libc-2.30.so
7ff26fec3000-7ff26fec9000 rw-p 00000000 00:00 0
7ff26feeb000-7ff26feed000 r--p 00000000 fd:00 1180257 /usr/lib64/ld-2.30.so
7ff26feed000-7ff26ff0d000 r-xp 00002000 fd:00 1180257 /usr/lib64/ld-2.30.so
7ff26ff0d000-7ff26ff15000 r--p 00022000 fd:00 1180257 /usr/lib64/ld-2.30.so
7ff26ff16000-7ff26ff17000 r--p 0002a000 fd:00 1180257 /usr/lib64/ld-2.30.so
7ff26ff17000-7ff26ff18000 rw-p 0002b000 fd:00 1180257 /usr/lib64/ld-2.30.so
7ff26ff18000-7ff26ff19000 rw-p 00000000 00:00 0
7ffffb0e8000-7ffffb10a000 rw-p 00000000 00:00 0 [stack]
7ffffb1eb000-7ffffb1ee000 r--p 00000000 00:00 0 [vvar]
7ffffb1ee000-7ffffb1ef000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
以这一行为例
55b78282f000-55b782830000 rw-p 00009000 fd:00 1180965 /usr/bin/sleep
是进程中r读取-w可读取的全局数据的映射,
从 /usr/bin/sleep 填充(在文件中的偏移量不是
此处显示)。
另一个映射,
55b782827000-55b78282b000 r-xp 00002000 fd:00 1180965 /usr/bin/sleep
是r可读且executable - 代码,由
相同的二进制文件。文件中的其他行显示取自的映射
包含类似工件的共享库。
最后有两个映射stack和heap不是
从文件中填充,而是由
进程创建时的内核。