我正在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
Run Code Online (Sandbox Code Playgroud)
似乎maps所有程序的文件都显示每个程序的可执行代码都是从一个内存块开始加载的0x00400000.
我知道这些是虚拟地址.但是,我不知道这些地址对于多个并发运行的进程是如何相同的.使用公共起始地址加载所有进程的原因是什么,以及操作系统如何区分一个进程的虚拟加载点与另一个进程的虚拟加载点?
编辑:
根据我对使用分页的地址空间虚拟化的理解,我认为部分虚拟地址用于通过使用它来索引一个或多个页表来查找内存块(帧)的物理地址.考虑这种情况.地址看起来是32位(这是令我感到困惑的另一件事 - 为什么程序地址为32位,但加载库的地址是64位?).将地址分成对应于页面目录条目,页面表条目和页面偏移的十位,十位和十二位,不应0x00400000总是表示"页面目录条目1,页面表条目0,偏移0",否什么程序执行地址转换?
我可以看到如何做到这一点的一种方法是,如果操作系统在每次执行任务切换时修改了页面目录条目#1以指向与该程序相对应的页面表.如果是这种情况,那听起来似乎增加了许多复杂性 - 假设程序代码与位置无关,那么只是将程序加载到任意虚拟地址并且从那里开始就不容易了吗?
链接目标文件以生成ELF文件,并确定其虚拟地址。例如,.text的虚拟地址为0x8048000。当ELF文件要映射到虚拟空间时,另一个ELF已经映射到该地址。操作系统应该做什么?为什么在将ELF的虚拟地址映射到虚拟空间之前就可以确定它的原因。
我对多级分页方案的概念感到困惑。
让一个 32 位虚拟地址和一个页面为 4 KiB,那么我将有 2 20页/页表条目。
设一个页表条目的大小为 4 个字节,因此页表的大小为 2 20 * 4 个字节。
如果我把虚拟地址分成10 | 10 | 12,那么我的理解是:
我有一个页表目录,它由虚拟地址的最高有效 10 位索引,因此它有 2 10个条目并指向 2 10 个不同的页表(即,在第二级)。
每2次电平表再次可以通过(中间)10位和相应的条目将持有的实际页帧号来索引。
我的问题是:
我试图通过一次使用整个页面来优化我的程序的内存分配.
我抓住这样的页面大小:sysconf(_SC_PAGESIZE);然后计算适合页面的元素总数,如下所示:elements=pageSize/sizeof(Node);
我的想法是,当我真正去malloc我的记忆时,我会用malloc(elements*sizeof(Node)); 它似乎sifeof(Node)的乘法和除法会抵消,但是对于整数除法,我不相信那是这种情况.
这是一次malloc整个页面的最佳方式吗?
谢谢
我们知道,当创建一个进程时,会为此进程分配一个堆栈.在linux中,堆栈的大小通常为8 Mb.我的问题是,从这个堆栈分配的位置?从用户空间还是从系统空间?
我用Google搜索了很长时间,但我仍然不明白它是如何工作的,因为大多数解释都是非常技术性的,没有任何插图可以让它更清晰.我的主要困惑是它与虚拟内存有什么不同?
我希望这个问题在这里有一个非常好的解释,以便其他提出相同问题的人可以在谷歌时找到它.
那么页框号和页表项到底有什么区别呢?
以下哪一项是正确的:
physical_address = PTE * page_size + offset
Run Code Online (Sandbox Code Playgroud)
physical_address = PFN * page_size + offset
Run Code Online (Sandbox Code Playgroud) 我阅读了一些关于页目录和页表的手册,但对这些概念仍然很困惑。例如在这里我发现只进行单级分页是在浪费内存。所以在x86架构中我们使用 2 级分页。
cr3 --> PageDirectory --> PageTable --> Page
Run Code Online (Sandbox Code Playgroud)
所以考虑下面的线性地址。
01001010101 1010101101 10101110101010
page tbl page offset
Run Code Online (Sandbox Code Playgroud)
使用page tbl位我们找到页目录条目的物理地址。PD = cr3 + L * (page tbl)其中包含页表物理地址PT。现在我们正在寻找我们的页面P = PT + L * page。所以在单层我们有一个 4MiB 的页表。现在我们总共有 1024 个页表 4KiB = 4MiB。不要看内存经济。
我错过了什么?