七.关于内存部分扩展探讨
1.逻辑地址 线性地址(虚拟地址)物理地址
逻辑地址(Logical Address) 是指由程式产生的和段相关的偏移地址部分。例如,你在进行C语言指针编程中,能读取指针变量本身值(&操作),实际上这个值就是逻辑地址,他是相对于你当前进程数据段的地址,不和绝对物理地址相干。只有在Intel实模式下,逻辑地址才和物理地址相等(因为实模式没有分段或分页机制,Cpu不进行自动地址转换);逻辑也就是在Intel保护模式下程式执行代码段限长内的偏移地址(假定代码段、数据段如果完全相同)。应用程式员仅需和逻辑地址打交道,而分段和分页机制对你来说是完全透明的,仅由系统编程人员涉及。应用程式员虽然自己能直接操作内存,那也只能在操作系统给你分配的内存段操作。
线性地址(Linear Address) 是逻辑地址到物理地址变换之间的中间层。程式代码会产生逻辑地址,或说是段中的偏移地址,加上相应段的基地址就生成了一个线性地址。如果启用了分页机制,那么线性地址能再经变换以产生一个物理地址。若没有启用分页机制,那么线性地址直接就是物理地址。Intel 80386的线性地址空间容量为4G(2的32次方即32根地址总线寻址)。
物理地址(Physical Address) 是指出目前CPU外部地址总线上的寻址物理内存的地址信号,是地址变换的最终结果地址。如果启用了分页机制,那么线性地址会使用页目录和页表中的项变换成物理地址。如果没有启用分页机制,那么线性地址就直接成为物理地址了。
虚拟内存(Virtual Memory)是指计算机呈现出要比实际拥有的内存大得多的内存量。因此他允许程式员编制并运行比实际系统拥有的内存大得多的程式。这使得许多大型项目也能够在具有有限内存资源的系统上实现。一个非常恰当的比喻是:你不必非常长的轨道就能让一列火车从上海开到北京。你只需要足够长的铁轨(比如说3公里)就能完成这个任务。采取的方法是把后面的铁轨即时铺到火车的前面,只要你的操作足够快并能满足需求,列车就能象在一条完整的轨道上运行。这也就是虚拟内存管理需要完成的任务。在Linux0.11内核中,给每个程式(进程)都划分了总容量为64MB的虚拟内存空间。因此程式的逻辑地址范围是0x0000000到0x4000000。有时我们也把逻辑地址称为 虚拟地址。因为和虚拟内存空间的概念类似,逻辑地址也是和实际物理内存容量无关的。逻辑地址和物理地址的“差距”是0xC0000000,是由于虚拟地址->线性地址->物理地址映射正好差这个值。这个值是由操作系统指定的。机理 逻辑地址(或称为虚拟地址)到线性地址是由CPU的段机制自动转换的。如果没有开启分页管理,则线性地址就是物理地址。如果开启了分页管理,那么系统程式需要参和线性地址到物理地址的转换过程。具体是通过设置页目录表和页表项进行的
https://blog.csdn.net/do2jiang/article/details/4512417
https://blog.csdn.net/do2jiang/article/details/4512417
2.实地址模式
3.保护地址模式
2.3在一起:https://blog.csdn.net/lemon1999123/article/details/84554068
4.内核代码中关于mm_struct结构熟悉
https://blog.csdn.net/tiankong_/article/details/75676131
5.进程地址空间
1)4G地址空间的布局
https://blog.csdn.net/f__yuan/article/details/96335327
《liunx内核设计与实现》第14章
6.内核空间内存管理
1)linux把内存划分成那三个区
虚拟地址布局:https://blog.csdn.net/abc3240660/article/details/81484984
2)内核空间kmalloc分配内存
https://www.cnblogs.com/sky-heaven/p/7390370.html
3)slab,建立高速缓存分配空间
《liunx内核设计与实现》第11章
4)缺页异常,do_page_fault()方法总结
//regs 发生异常时寄存器的值
//error_code 5位的值,第3位标志异常发生在内核态还是用户态
do_page_fault函数:
{
//获得产生缺页异常的地址,该地址保存在cr2寄存器
address = read_cr2();
//检查线性地址是否属于第4个G
//如果内核访问不存在的内存页框,则执行vmalloc_fault
//该部分代码处理可能由于在内核态访问非连续内存区而引起的缺页
跨过一部分检测
//接下来,检查异常发生时,是否正在执行一些关键例程或正在执行内核线程
//假设缺页没有发生在中断处理,可延迟函数,临界区或者内核线程中
//检查进程的线性区以决定引起缺页的线性地址是否包含在进程的地址空间中
//获得mmap_sem信号量
//查找发生异常的地址所属的vma
//如果vma为空,说明address这后没有线性区,因此这个地址肯定是无效的
//如果address之后的第一个线性区包含address,则跳到good area处理
//以上两者都不成立,则可能是用户态栈上的Push或pusha操作引起的
//栈映身到线性区上的话,该vma被标志为VM_GROWSDOWN
//expand_stack扩展进程地址空间的栈
//接着执行handle_mm_fault处理缺页异常
}