CSAPP阅读笔记-第十章
虚拟存储器
- 物理和虚拟地址
- 地址空间
- 虚拟存储器作为缓存的工具
- 虚拟存储器作为存储器管理的工具
- 虚拟存储器作为存储器保护的工具
- 地址翻译
- Pentium/Linux存储器系统
- 存储器映射
- 动态存储器分配
- 垃圾收集
- C程序中常见的与存储器有关的错误
- 重述虚拟粗存其的关键概念
###读前感:
读前对虚拟内存的认识是,内存是硬盘的缓存区,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命令查看内存的说明,我觉得这个链接说的比较清楚