我在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
似乎所有程序的地图文件都显示每个程序的可执行代码被加载到从0x00400000开始的内存块中.
我明白这些是虚拟地址.但是,我不知道这些地址对于多个并发运行的进程可能是一样的.使用通用起始地址加载所有进程的原因是什么?操作系统如何区分一个进程的虚拟加载点与另一个进程的区别?
编辑:
从我对使用分页的地址空间虚拟化的理解,我认为虚拟地址的一部分用于通过使用它来索引一个或多个页表来查找内存块(一个帧)的物理地址.考虑这种情况.地址看起来是32位(这是另一件让我困惑的事情 – 为什么程序地址为32位,但加载库的地址是64位?).将地址分别分别对应于页目录项,页表项和页偏移量的十位,十位和十二位,不应该是0x00400000总是指“页目录项1,页表项0,偏移量0”无论什么程序执行地址转换?
我可以看到如何做到这一点的一个方法是,如果操作系统在每次执行任务切换时,将页面目录条目#1修改为指向与该程序相对应的页面表.如果是这样的话,这听起来像是很多额外的复杂性 – 鉴于程序代码与位置无关,只要将程序加载到任意的虚拟地址并且从那里开始就不容易了
解决方法
答案是每个进程都有自己的页表.当切换进程时,它们被切换.
http://www.informit.com/articles/article.aspx?p=101760&seqNum=3的更多信息.
当上下文切换发生时,内核会切换页表.在内核映射到每个进程的操作系统上,内核页面可以保留.另一方面,为用户进程提供4GiB的操作系统(32bit)也必须在进入内核(系统调用)时执行上下文切换.
虽然虚拟寻址不需要不同的进程来具有不同的页表(依赖关系相反),但我不能想到任何当前的操作系统不给每个进程自己的页表.