求教linux里的一道分页原理相关的题目

发布于 2022-10-15 08:04:06 字数 184 浏览 29 评论 0

假定为一个进程分配的线性地址范围为0x00e80000~0xc0000000
并假定这个进程要读取线性地址0x00faf000中的内容
试按照分页原理描述其处理过程

题目出处是:《linux操作系统原理与应用》(清华大学出版社)36页第14题
可以参考29页的。。不过本人看了好久还是没明白。。求指教。。。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

不一样的天空 2022-10-22 08:04:06

没有人知道吗

╰ゝ天使的微笑 2022-10-22 08:04:06

我的理解是 当cpu得知要读取0x00faf000的时候,就把这个地址交给了MMU,接下来的所有的就交给了MMU

故事未完 2022-10-22 08:04:06

摘自毛德操-情景分析,希望对你有帮助。

举个地址映射的例子:
----------------------------
foo()
{
        printf("hello\n");
}

main()
{
        foo();
}
----------------------------
用objdump -d xxx反汇编一下,可以看到:
80483f8:        55                           push   %ebp
80483f9:        89 e5                        mov    %esp,%ebp
80483fb:        83 e4 f0                     and    $0xfffffff0,%esp
80483fe:        e8 e1 ff ff ff               call   8048368 <foo>
ld(链接器)为foo分配的地址是0x8048368,Linux内核设计的段式映射机制把地址0x8048368映射到了自身,现在作为线性地址出现,真正做的工作是页式映射。我们看下页式映射的过程:
每个进程都有其自身的页面目录PGD,指向这个目录的指针保存在每个进程的mm_struct数据结构中。每当调度一个进程进入运行的时候,内核都要为即将运行的进程设置好控制寄存器CR3,而MMU的硬件则总是从CR3中取得指向当前页面目录的指针。不过,CPU在执行程序时使用的是虚拟地址,而MMU硬件在进行映射时所用的是物理地址。
arch/x86/include/asm/page.h
#define __pa(x)         __phys_addr((unsigned long)(x))
arch/x86/include/asm/page_32.h
#define __phys_addr(x)          __phys_addr_nodebug(x)
#define __phys_addr_nodebug(x)  ((x) - PAGE_OFFSET)
#define PAGE_OFFSET             0xfffffc0000000000UL
通过__pa()把页面目录PGD的物理地址装入寄存器CR3中。当我们在程序中要转移到地址0x8048368去的时候,进程正在运行中,CR3早已设置好,指向我们这个进程的页面目录了。将0x8048368展开:

0000 1000 0000 0100 1000 0011 0110 1000

最高10位为二进制0000 1000 00,即十进制32。i386 CPU中的MMU会以32为下标去页面目录中找到其目录项。这个目录项中的高20位指向一个页面表。CPU在这20位后边添上12个0就得到该页面表的指针(每个页面表占一个页面,自然就是4K字节边界对齐的,其起始地址的低12位一定是0.正因为如此,才可以把32位目录项中的低12位挪作它用,其中最低位为P标志位,为1时表示该页面表在内存中)。找到页面表以后,CPU再来看线性地址的中间10位,00 0100 1000。即十进制72。于是CPU就以此为下标在已经找到的页面表中找到相应的表项。与目录项相似,当页面表的P标志位,为1时表示该页面表在内存中。32位页面表项中的高20位指向一个物理内存页面,在后边添上12个0就得到这个物理内存页面的起始地址。在其起始地址上加上线性地址中的最低12位,就得到了foo()在内存中最终的物理地址。这个线性地址的最低12位是0x368,所以,如果目标页面的起始地址为0x740000的话(具体取决于内核中的动态分配),那么foo()入口的物理地址就是0x740368,foo()的执行代码就存储在这里。
在页面映射的过程中,i386要访问内存三次。第一次是页面目录,第二次是页面表,第三次是访问真正的物理地址。

i386页式内存管理的基本思路是:通过页面目录和页面表分两个层次实现从线性地址到物理地址的映射。这种映射模式在大多数情况下可以节省页面表所占用的空间。因为大多数进程不会用到整个虚拟存储空间,在虚拟存储空间中通常都留有很很大的“空洞”。采用两层的方式,只要一个目录项所对应的那部分空间是个空洞,就可以把该目录项设置成“空”,从而省下了与之对应的页面表(1024个页面描述项)。当地址的宽度为32位时,两层映射机制比较有效也比较合理。但是,当地址的宽度大于32位时,两层映射就显得不尽合理,不够有效了。

梦屿孤独相伴 2022-10-22 08:04:06

解释的非常清晰!

不及他 2022-10-22 08:04:06

回复 4# wibnmo
经典书籍的确不错啊。。。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文