最近研究内核,但是一直有几个问题不太明白,请教一下内核专家,希望能帮我解决:1、内核直接映射低于896MB的物理内存,我理解映射了那么页表项应该设置了,至少页表项的Field字段(20位,即页框物理地址最高20位)已经指向了相应物理内存?2、内核直接映射了前896MB的物理内存,映射了不一定代表页框已经分配给内核了?即映射了但是可能页表项的Present字段(为1表示所指的页在主存中)还是为0?因为如果这里内核映射了前896MB就代表页框已经分配的话,那么当主机所有物理内存少于896MB的时候,用户进程就没有页框可以分配了?3、如果我第2点是正确的话,那么内核访问映射了但没分配页框的页,这时应该会产生缺页异常吧?应该就是发现Present为0,所以产生缺页异常吧?

解决方案 »

  1.   

    1. 内核直接映射了前896M物理内存,用3G+X的虚拟地址就能访问X的物理地址,这是内核初始化内存管理器时建立的映射,这里的页表中的p位都是1,这套页表只确保线性一致映射,保证任何时刻内核都能直接访问物理内存(先不管高端内存)。
    2. 这些内存被内存管理器再分配,比如建立用户进程虚拟地址空间的映射,这时其实一个物理页可以通过多个虚拟地址访问。(是内核管理着内存,它把内存分给进程,不存在别人分配内存给它这个说法)
    3. 最后建议了解下旧版本内核内存管理器的建立过程,bootmem和buddy分配器代码可参考2.4.0的内核,配合内核情景分析那本书。
      

  2.   

    Linux中的地址有很多种类型,总线地址,逻辑地址,虚拟地址等等,映射关系相当复杂。
    在我记忆中,少于896兆的情况下,内核是会给所有内存建立表单,并且内核虚拟地址和物理地址一一对应,这个虚拟地址在整个操作系统中是唯一的,不论在哪个进程想访问这些虚拟地址都是最终访问到相同的物理地址,并且访问的唯一途径是进入内核态。
    而你在用户空间malloc出来的虚拟地址跟内核态的就完全不是一回事,用户空间的虚拟地址,只有当你需要用到的时候才会生成,并且这个虚拟地址也是向内核空间申请到的,也就是说用户态并没有其本身的内存池,一切内存都是通过类似于malloc的函数,进行brk之类系统调用进入内核态申请,并更新进程的虚拟地址表。内核拿出池子里的一块空闲内存交给进程使用,并且赋予其一个用户态虚拟地址,也就是说此时此处物理内存至少拥有一个内核虚拟地址以及一个用户态虚拟地址。这一部分可以参照mmap的用法,mmap就是利用了这个原理实现了内核同用户态之间的快捷数据交互。