我正在研究 64 位机器上的 Linux 2.6.32 上的进程执行。在研究 的输出时/proc/$PID/maps
,我观察到一件事:
$ cat /proc/2203/maps | head -1
00400000-004d9000 r-xp 00000000 08:02 1050631 /bin/bash
$ cat /proc/27032/maps | head -1
00400000-00404000 r-xp 00000000 08:02 771580 /sbin/getty
似乎maps
所有程序的文件都显示每个程序的可执行代码都加载到从0x00400000
.
我知道这些是虚拟地址。但是,我不明白这些地址对于多个同时运行的进程是如何相同的。使用公共起始地址加载所有进程的原因是什么?操作系统如何区分一个进程的虚拟加载点与另一个进程的虚拟加载点?
编辑:
根据我对使用分页的地址空间虚拟化的理解,我认为部分虚拟地址用于通过使用它来索引一个或多个页表来查找内存块(一帧)的物理地址。考虑这种情况。地址看起来是 32 位的(这是另一件让我感到困惑的事情——为什么程序地址是 32 位的,但加载的库的地址是 64 位的?)。将地址分成十位、十位和十二位分别对应于页目录项、页表项和页偏移量,不应0x00400000
总是表示“页目录项 1、页表项 0、偏移量 0”,没有什么程序执行地址转换?
我可以看到如何做到这一点的一种方法是,如果操作系统在每次执行任务切换时修改页面目录条目 #1 以指向与程序对应的页表。如果是这样的话,这听起来会增加很多复杂性——鉴于程序代码是与位置无关的,将程序加载到任意虚拟地址并从那里开始不是更容易吗?