CSAPP阅读笔记-第十章

虚拟存储器
1. 物理和虚拟地址
2. 地址空间
3. 虚拟存储器作为缓存的工具
4. 虚拟存储器作为存储器管理的工具
5. 虚拟存储器作为存储器保护的工具
6. 地址翻译
7. Pentium/Linux存储器系统
8. 存储器映射
9. 动态存储器分配
10. 垃圾收集
11. C程序中常见的与存储器有关的错误
12. 重述虚拟粗存其的关键概念

读前感:

读前对虚拟内存的认识是,内存是硬盘的缓存区,CPU读内存的速度要远远快于读硬盘,物理内存到虚拟内存有一个映射关系,虚拟内存有分页机制,每页都对应硬盘上的一块,如果访问虚拟内存未命中,那么就需要换页,好的换页算法会对性能有很大影响。对GC只是知道有这么个概念,具体实现不太清楚。

读后感:

  • 虚拟内存
    虚拟内存是对物理内存的抽象表示,或者说是为了多进程能高效安全使用物理内存的一套方法,是一个sandbox。有了虚拟内存,每个进程得以有独立的统一的虚拟地址空间,如下图: 同时虚拟内存也保证了使用内存超过物理内存大小的程序得以运行,首先,虚拟内存会被分页,每一页都会映射到物理内存上,好吧是对应到物理内存上,我之前的理解对应硬盘上是错误的,当CPU寻址发过来一个虚拟内存地址,经过MMU和OS的配合完成地址翻译后,才对应到物理地址,这个物理地址其实对程序来说是透明的,程序根本不需要知道它,地址翻译的关键是OS为每个进程维护了一份页表,页表里包括了这个页是不是在物理内存中,如果不在就要申请换页,频繁的换页会影响系统性能,叫做“抖动”。多个进程的页表可能映射同一块物理内存,这也方便了进程间数据共享。下图清楚表明这一点:

第一张图是很重要的,它表明了进程的虚拟内存布局,比如栈从高地址向低地址增长,栈下边(低地址方向定义为向下)是存储器映射区,一般用于共享库,再往下是堆,bss,data,text。网上有一张图更清晰一点:

  • 存储器映射和动态内存分配
    内存映射linux里用户可以通过mmap函数实现的,进程虚拟地址空间中的栈和堆之间的部分就是内存映射,内存映射可以将磁盘文件和虚拟内存联系起来,据说这样效率会比较高。对于动态内存分配就是常用的malloc函数,C++的new只是对malloc的封装,当然malloc也是对系统调用sbrk的封装,malloc封装的分配器的算法,比如怎么处理块的合并,怎样避免碎片,malloc分配的堆内存是要用户程序手动释放,不释放是内存泄露,释放错误也不行,越界访问不在stack或者heap上的内存也不行,都会导致segment fault。对于垃圾回收,实在是没看太懂,表示这个主题有点深奥,有空仔细深入研究下Mark&Sweep法。另外关于free命令查看内存的说明,我觉得这个链接说的比较清楚