虚拟内存与物理内存与内存碎片-杂谈

内存杂谈

虚拟内存与物理内存

为什么要有虚拟内存???

1.每个进程有独立的虚拟地址空间,进程访问的虚拟地址并不是真正的物理地址(每个进程都假设自己看到的是完整的从0开始的内存)
2.程序可以使用一系列虚拟地址来访问大于可用物理内存的内存缓冲区。当物理内存的供应量变小时,内存管理器会将物理内存页(通常大小为 4 KB)保存到磁盘文件。数据或代码页会根据需要在物理内存与磁盘之间移动。(如linux swap 分区)

如何实现虚拟内存???

虚拟内存与物理内存存在映射关系, 这样"逻辑上的虚拟内存连续"在"实际物理内存上"其实是不连续的.
虚拟内存通过 MMU(映射算法)与页表组成, MMU操作的最小基本单位为 页.

内存碎片

现代OS如何避免内存碎片???

基础

  1. 页,页面,与框
    https://blog.csdn.net/displayMessage/article/details/80905810
  2. 页中断

Linux 通过 buddy system 避免内存碎片

即使合并内存, 减少内存碎片的产生, 详情百度即可

什么是内存碎片

碎片只会在虚拟内存中产生,是不会映射到物理内存上的。
碎片只会在虚拟内存中产生,是不会映射到物理内存上的。
碎片只会在虚拟内存中产生,是不会映射到物理内存上的。
重要的事说三遍
采用分区式存储管理的系统,在储存分配过程中产生的、不能供用户作业使用的主存里的小分区称成“内存碎片”。内存碎片分为内部碎片和外部碎片。

内存的静态分配与动态分配

内存分配有静态分配和动态分配两种。静态分配在程序编译链接时分配的大小和使用寿命就已经确定,而应用上要求操作系统可以提供给进程运行时申请和释放任意大小内存的功能,这就是内存的动态分配, 动态内存会导致内存碎片的产生。

内部碎片与外部碎片

内部碎片: 众所周知,内存需要对齐(起点落在 4 的倍数上), 所以如果申请27byte内存实际上会给分配28byte内存。 eg: linux 最小页面长度为 4096 byte, 用 c 语言malloc 一个 char(1byte) 的空间, 则必须最少申请 4k 的空间吗??
外部碎片: 频繁的申请与释放内存,会导致有很多不连续的可用的小内存在已分配的页面中, 此时如果申请一片较大的内存(申请的内存是连续的),即使这些小内存加起来 > 要申请的内存,也不能申请成功(因为这些小的可用内存不是连续的).

c/c++ 如何避免内存碎片

所有语言都会有内存碎片,内存碎片只能减少而不能避免.
减少内存碎片可以用第三方库来实现.

  1. 少用动态内存分配的函数(尽量使用栈空间)
  2. 分配内存和释放的内存尽量在同一个函数中
  3. 申请内存的大小尽量为 2^n, 以避免内部内存碎片, 而不要反复申请小内存(少进行内存的分割, 得益于os用 buddy system来管理内存)
  4. 不要频繁的申请小内存
  5. 尽可能少地申请空间。
  6. 尽量少使用堆上的内存空间~
  7. 做内存池,也就是自己一次申请一块足够大的空间,然后自己来管理,用于大量频繁地new/delete操作。(我们可以推断出 自动回收机制也是有弊端的)

eg: linux 最小页面长度为 4096 byte, 用 c 语言malloc 一个 char(1byte) 的空间, 则必须最少申请 4k 的空间吗??
进程占有逻辑上的全部内存(虚拟内存),malloc 占用的是堆区的空间 . 在申请小内存时(以 glibc 中 小于128kb时), 仅仅移动brk指针向高地址
//会在第一次使用时产生页中断,才建立映射关系(延时映射机制).
答: 只用16byte(或许包含了内存对齐和其他的数据),远远没有使用 4kb 的内存.(这个问题目前还没有想出来答案)

gcc中 vector 的默认扩增倍数k为什么为2而不是常量??? 2是否是最优解
  1. 为什么不是常量???
    答: 进行 n 次push_back , 在内存复制方面,k 为倍数要比k为常量的时间复杂度小的多.

  2. 用 2 有什么好处???
    答:

  3. 2 倍不是最优解???
    答:倍数为1.618为最优,由于vector使用copy扩增会重新申请一块大的内存然后再, 将对象复制进新的内存,然后释放掉原来的内存。那么在下次扩充的时候,由于每次申请的都比之前所有释放的空间加起来都大(k==2的特性),就导致之前释放的的内存不能用, 详情见:
    https://www.zhihu.com/question/36538542/answer/67929747

//2. 是为了防止内部内存碎片的发生. 内存以2^n对齐, 如果不为2^n,则

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值