一、底层结构

采用三层结构,实际使用中可以方便映射到两层或者三层结构,以适用不同的硬件结构。最下层的申请内存函数get_free_page。之上有三种类型的内存分配函数:

1.kmalloc类型。内核进程使用,基于切片(slab)技术,用于管理小于内存页的内存申请。思想出发点和应用层的内存缓冲池同出一辙。但它针对内核结构,特别处理应用场景固定,不考虑释放。

2.vmalloc类型。内核进程使用。用于申请不连续内存。

3.brk/mmap类型。用户进程使用。malloc/free实现的基础。

二、内存管理的相关函数图

STL  ->  内存自动分配和自动回收(C++)

|

C++  ->  new分配内存,delete回收内存

|

C  ->  malloc分配内存,free回收内存

|

Unix 系统函数 ->  sbrk/brk  分配和回收内存

|

Unix底层系统函数  ->  mmap/munmap分配回收

(用户层)

----------------------------------------------------------------------------

(内核层)

Unix内核函数  kmalloc/vmalloc/get_free_page

三、进程与内存

a.所有进程(执行的程序)都必须占用一定数量的内存

b.对任何一个普通进程来讲,它都会涉及到5种不同的数据段,其内存空间划分为:

1.代码区    ——    存放代码/函数,也就是说它是可执行程序的内存中的镜像。(只读)

2.全局区    ——    保存全局变量,static局部变量。

3.BSS段     ——    未初始化的全局变量,BSS段在main函数执行之前会自动清零

4.栈区       ——    局部变量,包括函数的形参,栈区内存自动分配和自动回收。

5.堆区       ——    程序员自己管理的区域,malloc/free操作的都是堆区。

6.只读常量区    ——    存放字符串常量和const修饰的全局变量

注:只读常量区和代码区非常接近,有些书把只读常量区和代码区合并为代码区。

c.进程如何组织这些区域?

从小到大次序:代码区、只读常量区、全局区、BSS段、堆区、栈区

堆区在离前面四个区不远的地址空间开始,从小到大分配,栈区从3G开始,从大到小分配。主要为了避免堆区和栈区重叠。

d.查看内存分配

Linux把一切都看做成文件,内存也可以在文件中查看。每个进程都在/proc目录下有一个对应的子目录,以进程ID作为子目录名。进程ID是系统对进程的标识。可以用ps-aux命令查看进程。

cat /proc/进程ID/maps    可以查看当前进程的内存情况。

四、虚拟内存管理技术

Linux使用了虚拟内存地址。每个Linux中的进程都有0~4G的虚拟内存地址,就是0~4G的数字。虚拟内存地址在开始时只是一个数字,不对应任何的内存。虚拟内存地址必须先映射一段物理内存或硬盘上的文件才能被使用。所谓的分配内存其实就是让虚拟内存地址映射一段物理内存。如果使用没有映射的虚拟内存地址就会引发段错误。

程序员所操作的内存地址都是虚拟内存地址,看不到物理内存地址。

0~4G的虚拟内存地址中,0~3G是用户使用,叫做“用户空间”,3G~4G是内核使用的,叫做“内核空间”。用户空间不能直接使用内核空间,但可以通过内核空间提供的一些函数(系统调用)访问内核空间。

注:内存管理的基本单位是4096 byte (4K),叫内存页。内存的映射和回收都是以内存页作为基本单位。

五、进程内存管理

进程内存管理的对象是进程线性地址空间上的内存镜像,这些内存镜像其实就是进程使用的虚拟内存区域(memory region)。进程虚拟空间是个32或64位的“平坦”(独立的连续区间)地址空间(空间的具体大小取决于体系结构)。要统一管理这么大的平坦空间可绝非易事,为了方便管理,虚拟空间被划分为许多大小可变的(但必须是4096byte的整数倍数)内存区域,这些区域在进程线性地址中像停车位一样有序排列。这些区域的划分原则是“将访问属性一致的地址空间存放在一起”,所谓访问属性一致无非是指“可读、可写、可执行等”。

六、物理内存管理(页管理)

Linux内核管理物理内存是通过分页机制实现的,它将整个内存划分成无数4K(在i386体系结构中)大小页,从而分配和回收内存的基本单位便是内存页了。利用分页管利用助于灵活分配内存地址,因为分配时不必要求必须有大块的连续内存,系统可以东一页、西一页的凑出所需要的内存供进程使用。虽然如此,但是实际上系统使用内存还是倾向于分配连续的内存块,因为分配连续内存时,页表不需要修改,因此能降低刷新率(频繁刷新会很大增加访问速度)。

七、brk/sbrk的虚拟内存管理

void *sbrk(int size);

size = 0    返回sbrk/brk上次的末尾地址,代表取当前的位置,

size > 0    分配内存空间,返回上次的末尾地址,代表分配size字节的内存,

size < 0    释放空间,代表回收size字节内存。

int brk(void* ptr);

直接修改访问的有效范围的末尾地址,释放空间形成一个完整的page,则该页映射被解除

返回:0    分配成功

-1    分配失败

经验:sbrk在分配内存上简单,brk在释放内存上简单。因此,开发大多数使用sbrk分配内存,使用brk释放内存。

八、系统底层的内存映射(mmap/munmap)

#include

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

int munmap(void *start, size_t length);

参数公共部分:

start:指向欲映射的内存起始地址,通常设为 NULL,代表让系统自动选定地址,映射成功后返回该地址。

length:代表将文件中多大的部分映射到内存。    映射空间大小。建议4k倍数,不是4K倍数,自动对齐。

mmap独有部分:

prot:映射区域的保护方式。可以为以下几种方式的组合:

1.PROT_EXEC 映射区域可被执行

2.PROT_READ 映射区域可被读取

3.PROT_WRITE 映射区域可被写入

4.PROT_NONE 映射区域不能存取

flags:影响映射区域的各种特性。在调用mmap()时必须要指定MAP_SHARED 或MAP_PRIVATE。

1.MAP_FIXED 如果参数start所指的地址无法成功建立映射时,则放弃映射,不对地址做修正。通常不鼓励用此标志。

2.MAP_SHARED对映射区域的写入数据会复制回文件内,而且允许其他映射该文件的进程共享。

3.MAP_PRIVATE 对映射区域的写入操作会产生一个映射文件的复制,即私人的“写入时复制”(copy on write)对此区域作的任何修改都不会写回原来的文件内容。

4.MAP_ANONYMOUS建立匿名映射。此时会忽略参数fd,不涉及文件,而且映射区域无法和其他进程共享。

5.MAP_DENYWRITE只允许对映射区域的写入操作,其他对文件直接写入的操作将会被拒绝。

6.MAP_LOCKED 将映射区域锁定住,这表示该区域不会被置换(swap)。

fd:要映射到内存中的文件描述符。如果使用匿名内存映射时,即flags中设置了MAP_ANONYMOUS,fd设为-1。有些系统不支持匿名内存映射,则可以使用fopen打开/dev/zero文件,然后对该文件进行映射,可以同样达到匿名内存映射的效果。

offset:文件映射的偏移量,通常设置为0,代表从文件最前方开始对应,offset必须是分页大小的整数倍。

返回值:

若映射成功则返回映射区的内存起始地址,否则返回MAP_FAILED(-1),错误原因存于errno 中。

九、errno错误代码

1.EBADF 参数fd 不是有效的文件描述词

2.EACCES 存取权限有误。如果是MAP_PRIVATE 情况下文件必须可读,使用MAP_SHARED则要有PROT_WRITE以及该文件要能写入。

3.EINVAL 参数start、length 或offset有一个不合法。

4.EAGAIN 文件被锁住,或是有太多内存被锁住。

5.ENOMEM 内存不足。

Linux Unix内存管理,简述:Unix/Linux内存管理相关推荐

  1. linux驱动程序是什么,简述一个Linux驱动程序的主要流程与功能

    1. 简述一个Linux驱动程序的主要流程与功能. 2. 请列举一个软件中时间换空间或者空间换时间的例子. void swap(int a,int b) { int c; c=a;a=b;b=a; } ...

  2. Unix/Linux操作系统分析实验二 内存分配与回收:Linux系统下利用链表实现动态内存分配

    Unix/Linux操作系统分析实验一 进程控制与进程互斥 Unix/Linux操作系统分析实验三 文件操作算法: 实现在/proc目录下添加文件 Unix/Linux操作系统分析实验四 设备驱动: ...

  3. linux获取共享内存失败2,unix/linux共享内存应用与陷阱

    共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区.在/proc/sys/kernel/目录下,记录着共享内存的一些限制,如一 个共享内存区的最大字节数shmmax,系统范围内最大共享内存 ...

  4. Unix/Linux环境C编程入门教程(27) 内存那些事儿

    calloc() free() getpagesize() malloc() mmap() munmap()函数介绍 calloc(配置内存空间) 相关函数 malloc,free,realloc,b ...

  5. Linux操作系统原理与应用04:内存管理

    目录 1. Linux内存管理概述 1.1 内存的层次结构 1.2 虚拟内存概述 1.2.1 虚拟内存基本思想 1.2.2 进程虚拟地址空间 1.3 内核空间到物理空间的映射 1.3.1 内核空间的线 ...

  6. linux内存管理子系统采用基于内存区域,Linux 内存管理之highmem简介

    一.Linux内核地址空间 一般来说Linux 内核按照 3:1 的比率来划分虚拟内存(X86等):3 GB 的虚拟内存用于用户空间,1GB 的内存用于内核空间.当然有些体系结构如MIPS使用2:2 ...

  7. Linux 操作系统原理 — 内存 — 页式管理、段式管理与段页式管理

    目录 文章目录 目录 前文列表 页式管理 快表 多级页表 基于页表的虚实地址转换原理 应用 TLB 快表提升虚实地址转换速度 页式虚拟存储器工作的全过程 缺页中断 为什么 Linux 默认页大小是 4 ...

  8. Linux内存管理之高端内存映射

    一:引子 我们在前面分析过,在linux内存管理中,内核使用3G->4G的地址空间,总共1G的大小.而且有一部份用来做非连续空间的物理映射(vmalloc).除掉这部份空间之外,只留下896M大 ...

  9. 【Linux 内核 内存管理】内存管理架构 ② ( 用户空间内存管理 | malloc | ptmalloc | 内核空间内存管理 | sys_brk | sys_mmap | sys_munmap)

    文章目录 一.用户空间内存管理 ( malloc / free / ptmalloc / jemalloc / tcmalloc ) 二.内核空间内存管理 1.内核内存管理系统调用 ( sys_brk ...

最新文章

  1. Linux下的Shell编程(2)环境变量和局部变量
  2. 回顾2018——区块链行业十大关键词
  3. 《利用Python》进行数据分析:Numpy基础2 创建数组
  4. 软考-信息系统项目管理师-项目合同管理
  5. 搜索2.0:利用用户点击记录改善搜索结果
  6. 2019-03-15-算法-进化(有效的数独)
  7. JavaScript网络地址作为参数_JavaScript之bind的模拟实现
  8. sql内部连接_SQL内部联接的分步演练
  9. ASPxGridView数据汇总收藏
  10. 官方高清标准地图素材下载地址
  11. wds(无线分布式系统)
  12. 利用清华镜像站解决pip超时问题
  13. 【gym 101991 E】(ACPC 2018) E. Exciting Menus 题解
  14. 联想全系列官方WIN10工具
  15. 数据结构中树的直径问题
  16. Kafka消费者不消费数据
  17. surface pro java_【微软SurfacePro4评测】两代产品外观对比_微软 Surface Pro 4_笔记本评测-中关村在线...
  18. indexedDB 存储 js文件 xml文件 大文件缓存 并导出使用
  19. 公众号视频查找接口,支持自定义接口,支持水印
  20. 上海外服与埃森哲签约“数字外服”转型升级项目;剑桥量子将推出全球首款量子增强型加密密钥生成平台 | 全球TMT...

热门文章

  1. 火蚁机器人_科学网—红火蚁的“生命之舟” - 赵序茅的博文
  2. python起点小说字体加密
  3. 揭开关于Kindle Fire的一些重要信息
  4. 优化隔离传感器接口的功率转换
  5. 淘淘商城第95讲——单点登录之用户注册
  6. 国外也卷:(Nature)大学教职有多难拿?要名校毕业,还要家里有人
  7. 第三章:使用云产品的优势
  8. 恶补CSS的布局知识
  9. BPM实施:成功的 BPM 需要真正的团队解决方案
  10. 【MSP430】如何用USB转TTL 串口下载