物理和虚拟寻址
地址空间
虚拟内从作为缓存的工具
DRAM缓存的组织结构
页表
页命中
缺页
分配页面
又是布局性拯救了我们
虚拟内存作为内存管理的工具
虚拟内存作为内存保护的工具
地址翻译
结合高速缓存和虚拟内存
利用TLB加速地址翻译
多级页表
综合:端到端的地址翻译
案例研究: Intel Core i7 / Linux
Core i7地址翻译
Linux虚拟内存系统
内存映射
再看共享对象
再看fork函数
再看execve函数
使用mmap函数的用户级内存映射
动态内存分配
malloc和free函数
为什么要使用动态内存分配
分配器的要求和目标
碎片
实现问题
隐式空闲链表
放置已分配的块
分割空闲块
获取额外的堆内存
合并空闲块
带边界标记的合并
综合:实现一个简单的分配器
显示空闲链表
分离的空闲链表
垃圾收集
垃圾收集器的基本知识
Mark&Sweep垃圾收集器
C程序中的保守Mark&Sweep
C程序中常见的与内存有关的错误
间接引用坏指针
读未初始化的内存
允许栈缓冲区溢出
假设指针和他们指向的对象时相同大小的
造成错位错误
引用指针,而不是它所指向的对象
误解指针运算
引用不存在的变量
引用空闲堆块中的数据
引起内存泄露
- 程序代码和数据。对所有的进程来说,代码是从同一固定地址开始,紧接着的是和C 全局变量相对应的数据位置。
- 堆。代码和数据区在进程一开始运行时就被指定了大小,与此不同,当调用像 malloc 和 free 这样的 C 标准库函数时,堆可以在运行时动态地扩展和收缩。
- 共享库。大约在地址空间的中间部分是一块用来存放像 C 标准库和数学库这样的共
享库的代码和数据的区域。 - 栈。位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数调用。和堆一
样,用户栈在程序执行期间可以动态地扩展和收缩。特别地,每次我们调用一个函
数时,栈就会增长;从一个函数返回时,栈就会收缩。 - 内核虚拟内存。地址空间顶部的区域是为内核保留的。不允许应用程序读写这个区
域的内容或者直接调用内核代码定义的函数。它们只能调用内核来执行这些操作。