CSAPP第九章读书笔记

本文围绕虚拟内存与缓存展开,介绍了虚拟内存的分割、虚拟页的分类,阐述了页表的作用、页命中与缺页的概念及处理过程,还讲解了地址翻译、Linux虚拟内存组织、内存映射、共享对象的内存映射,以及内存分配器、碎片类型、空闲链表和垃圾收集器等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

虚拟内存与缓存的关系(在这一篇中,缓存,内存和物理内存是同样的东西

虚拟内存被分割为若干个虚拟页,物理内存(也就是主存)也被分割为若干个物理页

虚拟内存开始是被存放在磁盘上的(个人理解),要想被程序使用,先要从磁盘中将内容复制到物理内存中,才可以被使用。

所以虚拟页分为三种:

1.未分配的:虚拟内存还未分配或者创建的虚拟页(我的理解是在linux系统中,每个进程都有4G的虚拟内存,但是并不是都要用4G的内存,所以有很大一部分虚拟内存中完全没有数据,这一部分的虚拟页就是未分配的),这一部分是不占用磁盘空间的。

2.未缓存的:虚拟页已经被创建了(就是虚拟页中存在有用的数据,但是没有被加入到缓存中),这一部分占用磁盘空间,但是不占用内存空间

3.缓存的:这一部分是已经加入到缓存中的,这一部分既占用磁盘空间,又占用缓存空间。

页表就是判断虚拟内存中每一页是否被加入缓存的表格,页表的每一行被称为页表条目(PTE)都代表了虚拟内存的一页(单级页表是这样,多级页表的每一列代表了一片,片是由若干页构成的),页表时存储在缓存中的

页命中就是当使用到某一虚拟页时,如果该虚拟页的PTE中的有效位时1.就是命中了。如果是0,就是没有命中,本质上说就是如果所用的虚拟页已经存入内存了,就是命中了,如果没有存入就是未命中。

缺页就是没有命中,如果发生缺页,会执行缺页异常,整个过程如下:

1.通过PTE发现所需虚拟页不在缓存中

2.触发缺页异常,在缓存中设置牺牲页(牺牲页就是准备把所需的虚拟页加入到缓存的位置,可能是空白的物理页,也可能是暂时不用的存放虚拟页的物理页)

3.如果牺牲页上有数据并且发生更改,就将牺牲页的内容放回磁盘中

4.将所需虚拟页存入缓存中

5.重新执行命中虚拟页

页表有一个特殊的功能就是可以带许可位,也就是这块页可以执行那些权限(比如读写等操作)

地址翻译

就是将虚拟地址变成缓存中的物理地址。

物理地址分为物理页号(PPN)和物理地址偏移量(PPO)两部分

虚拟地址分为虚拟页号(VPN)和虚拟地址偏移量(VPO)两部分,

通过VPN可以找到页表中的物理页号(就是除了有效位以外PTE的其他数位),而根据有效位可以判断是否执行缺页异常,

这样就将物理地址的PPN和PPO找到了,这样就完成翻译了。

 

 

整个过程可以参考这个流程图

linux虚拟内存组织

linux是虚拟内存是分段的,比如代码段,数据段等等,用一下的数据结构来记录一个进程中虚拟内存的存储区域

内存映射

就是讲磁盘中的一片地址和虚拟内存关联起来,可以理解为将磁盘中的一片数据存放到虚拟内存中。

这里有个地方比较难以理解:就是本来虚拟内存就是存放在磁盘上的,为什么还要从磁盘上去映射。

这是因为本来虚拟内存可能是4G,但是磁盘上真正占用的空间小于等于4G,如果小于4G的情况下。我想让磁盘上的另一块空间使用虚拟内存的方式存入缓存,就可以使用内存映射的方式。

共享对象的内存映射

内存映射分为两种,一种私有对象,也就是这种映射只能一个进程使用,一种是共享对象,这样可以多个进程共用一个映射对象。

注意:如果有多个进程的虚拟内存中映射了磁盘上的同一份地址空间,那么在缓存中也只会复制一次该磁盘上的内容,如果都是共享对象,就多个进程一起在缓存中修改那一块内容,如果是私有对象,那么就采用写时复制的策略。

fork函数创建子进程时就是采用的这个策略,子进程和父进程的进程信息是在同一块缓存空间中的,但是如果需要修改进程信息都是采用写时复制的策略。所以在子进程创建开始,子进程的信息和父进程时一样的,除了PID号。

 

内存分配器(主要分配的是虚拟内存中堆上内存空间)

内部碎片:内部碎片就是已经被分配出去(能明确指出属于哪个进程)却不能被利用的内存空间;内部碎片是处于(操作系统分配的用于装载某一进程的内存)区域内部或页面内部的存储块。占有这些区域或页面的进程并不使用这个存储块。而在进程占有这块存储块时,系统无法利用它。直到进程释放它,或进程结束时,系统才有可能利用这个存储块。

外部碎片:指的是还没有被分配出去(不属于任何进程),但由于太小了无法分配给申请内存空间的新进程的内存空闲区域。

隐式空闲链表:空闲块的头部存储的是该空闲块的大小

显式空闲链表:除了存储空闲块的大小外,还会存储两个指针,一个指向前一个空闲块,一个指向后一个空闲块。

 

分离的空闲链表:就是将大小相近的空闲链表分成一组,这样减少寻找合适空闲链表的时间

伙伴系统:每一类的大小都是2的幂(linux中就是使用的伙伴系统,但是我现在还不清楚linux如何避免内部碎片的产生)。

垃圾收集器:将堆中不可达的内存都销毁,腾出更多堆栈的空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值