内核内存管理

一、内核内存管理的物理单位:页
1、物理页的结构
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
flags :用来存放页的状态,每一位可以表示一种状态,共可以表示32中状态
(page-flags.h)
_count : 用来存放页的引用次数,内核代码不可以直接检查该域,应该使用page_count()函数来检查,返回值为0则代表该页空闲,返回值为正数则表示该页正在被使用
virtual:页在虚拟内存中的地址
2、内核使用struct page结构的原因:内核需要知道该页是否空闲,且知道拥有者
二、区
1.由于硬件的限制,有些页在物理内存的特定物理地址上,不能用于某些特定的任务,所以将页划分为不同的区,内核使用区对具有相似特性的页进行分组
2.Linux处理由于硬件存在而引起的内存寻址问题:
(1)一些硬件只能用某些特定的内存地址来执行DMA(直接内存访问)
(2)一些体系结构其内存的物理寻址范围比虚拟寻址范围大的多,从而有些内存不能永久的映射到内核空间上
3.由于这些制约条件,划分了三个区(mmzone.h)
(1)ZONE_DMA:这个区包含的页用来执行DMA操作;
(2)ZONE_NORMAL:这个区包含的都是能够正常映射的页
(3)ZONE_HIGHMEM:这个区包含“高端内存”,其中的页并不能永久的映射到内核地址空间
在这里插入图片描述
在这里插入图片描述
4.区的实际使用和分布是和体系结构有关的,区的划分并没有任何意义,只是根据用途将页进行分配,从而方便了内核对页的管理
5.区的结构
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
区的结构很大,系统中只有三个区;
lock:是个自旋锁,防止该结构体并发被访问,该域只保护结构,不保护区中的页
free_page:表示该区中空闲页的个数
name:表示该区的名字,内核启动期间初始化此值
三、获得页和释放页
1.获得页
(1)内核提供了请求内存的底层机制,并提供了进行访问的几个接口;
(2)获得页使用的函数:
struct page alloc_pages(unsigned int gfp_mask,unsigned int order);
//该函数可分配2^order个连续的物理页,返回值为指向第一个页page结构体的指针,若申请失败,则返回NULL。
在这里插入图片描述
unsigned long_get_free_pages(unsigned int gfp_mask,unsigned int order)
// 该函数也是用来获得页的,但它的返回值是第一个页的逻辑地址
在这里插入图片描述
void
page_address(struct page
page)
//该函数返回值为指向给定物理页当前所在的逻辑地址
unsigned long get_zeroed_pages(unsigned int gfp_mask)
//该函数将返回的页全部填充为0,为了分配给用户时防止分配的随机信息包括某些敏感数据,从而做到了保障系统安全
2.释放页
(1)释放页用的函数:
在这里插入图片描述
void _free_pages(strcut page *page,unsigned int order);
//传入释放的页的结构体
void free_pages(unsigned long addr,unsigned int order);
//传入释放的页的地址
void free_page(unsigned long addr);//释放一页的函数
(2)释放页之前都应该先做检查,防止未申请到页而导致释放引出错误
四、kmalloc()函数、gfp_mask标志、kfree()函数、vmalloc()函数
1、kmalloc():内核空间申请以字节为单位且连续的物理地址内存的函数
与用户空间申请内存的malloc()函数类似,区别在于多了一个flags参数
Void *kmalloc(size_t size,int flags);
//该函数返回一块指向连续且大小为size的内存块的指针,flags标志使用来标志内存分配器在获取内存且返回给kmalloc调用者时所采取的方法
确保页在物理地址上是连续的
在这里插入图片描述
2.gfp_mask标志:分配器标志
(1)分为三种:
行为修饰符:表示内核分配所需内存的方法;
在这里插入图片描述
区修饰符:表示内核分配内存的地方;一般优先从ZONE_NORMAL区开始,以确保其他区有足够的空闲页可以使用;
在这里插入图片描述
类型标志:指定所需的行为和区描述符以完成特殊类型的而处理
在这里插入图片描述
在这里插入图片描述
3.kfree()函数:内核用于释放有kmalloc()分配出来的内存块,不能释放除kmalloc() 分配的内存
在这里插入图片描述
4.vmalloc()函数:该函数分配的是连续的虚拟地址内存,而物理地址是不连续的;先通过分配非连续的物理内存块,再修正页表,把内存映射到连续区域的逻辑地址上。一般只使用kmalloc()函数分配内存,vmalloc一般只会用在申请大块内存上。
在这里插入图片描述
在这里插入图片描述
五、slab层
1.slab层使用来解决频繁的分配和释放页的问题,扮演着数据结构缓存层的角色
2.slab层设计:为了将不同的对象划分为所谓高速缓存组,每个高速缓存组都存放着不同类型的对象,即高速缓存被划分为slab,slab由一个或多个物理上连续的页组成,每个slab又包含一些对象成员(对象即被缓存的数据结构);
在这里插入图片描述
高速缓存的内存区被划分为多个slab,每个slab由一个或多个连续的页框组成
每个slab页框中既包含已分配的对象,也包含空闲的对象。
3.slab层有三种状态:满(slab层所有层对象都已被分配)、部分满(部分对象被分配)、空(所有对象都为空);当内核某部分需要一个新对象时,先从部分满的进行分配,再从空的进行分配,从而解少了内存碎片的问题
4.slab层的管理是在每个高速缓存的基础上通过一个接口来创建和销毁新的高速缓存,
当创建了一个新的高级缓存,slab层就如一个专用的分配器,为具体的对象类型进行分配
5、slab分配器接口
六、栈上的静态分配
1.内核栈的大小是固定的,为每个进程分配一个固定大小的栈,每个进程的内核栈的大小既取决于体系结构又取决于编译时的选项
2.中断栈:为每个进程提供用于中断程序处理程序的栈,解决了内核栈小的问题;
3.内核栈大小一般在4kb-16kb范围之内
七、高端内存的映射
由于在高端内存中的页不能永久的映射到内核地址空间上,所以获得具有GFP_HIGHMEM标志的页不具有逻辑地址;
在x86体系中,大于896MB的物理内存为高端内存
1.永久映射:
Void *kmap(struct page *page);
//对于低端内存:该函数单纯的返回该页的虚拟地址
//对于高端内存:会建立一个永久映射,再返回地址
//这个函数可以睡眠,只能用在进程上下文
//允许永久映射的数量有限,所以当不再需要高端映射时需要void kunmap(struct page *page) 来解除永久映射

2.临时映射
(1)当创建一个映射而当前进程的上下文不能睡眠时,出现了临时映射
(2)内核将高端内存中的一个页映射到某个保留的映射中存放新创建的临时映射
(3)建立临时映射的函数:
void *kmap——atomic(struct page *page,enmu km_type type);
//type:是一个枚举类型,描述了临时映射的目的

八、cpu的分配
1.现代操作系统使用每个cpu上的数据,对与给定的处理器的数据是唯一的,每个cpu数据存放在一个数组中,数组中的每一项对应着系统上一个存在的处理器,由于所操作的数据对当前的处理器是唯一的,所以不存在并发访问问题;
2.唯一的安全问题在于内核抢占,“只有这个处理器能访问这个数据”这个规则省去了很多数据上锁问题
九、分配函数的选择
1.连续的物理页需要kmalloc()或某个低级页分配器
2.高端内存分配,使用alloc_pages()
3.仅需要虚拟地址上连续的页,不需要物理上连续的页使用vmalloc()
4.创建和销毁很多大的数据结构,需要考虑建立slab告诉缓存

伙伴系统算法:(用来解决外碎片问题)
外碎片问题:频繁的请求和释放不同大小的一组连续页框,必然导致在已分配页框的块内分散许多小块的空闲页框。
把所有的空闲页框分组为10个块链表,每个块链表分别包含1,2,4,8,16,32,64,128,256,512个连续的页框,每个框的第一个页框的物理地址是该块大小的整数倍。
一块链表包含的内容
一个块链表包含的内容
在这里插入图片描述
内核试图把b的一对空闲伙伴->大小为2b的单独块,满足以下条件的两个块称为伙伴:
1.两个块大小相同2.物理地址连续3.第一个块的第一个页框的物理地址2b2^12的倍数
该算法是迭代的,如果它成功合并所释放的块,她会试图合并2b的块来形成更大的块。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值