OK6410A 开发板 (八) 40 linux-5.11 OK6410A buddy 的 alloc 和 free

第三阶段建立的是 buddy
  • buddy 的使用期限
mm_init->mem_init返回 - 无结束点
  • buddy 管理的内存大小
buddy 管理的内存 是 memblock 决定的
属于 memblock.memory 中 但不包括 memblock.reserved 的部分

memblock 可以通过 memblock_alloc或memblock_reserve 来 预留内存

buddy 的使用方法
  • alloc
alloc_pages/alloc_page // 返回的是 struct page
get_zeroed_page 	// 返回的是虚拟地址
__get_free_pages/__get_free_page // 返回的是虚拟地址
get_dma_pages


__get_free_pages
	struct page *page = alloc_pages
		alloc_pages_node
			__alloc_pages_node
				__alloc_pages
					__alloc_pages_nodemask
						struct page * page = get_page_from_freelist
	return (unsigned long) page_address(page);


__alloc_pages_nodemask 的 具体细节
	__alloc_pages_nodemask
	  prepare_alloc_context   //1.准备参数
	  get_page_from_freelist  //2.根据prepare_alloc_context 得到的参数 , 快路径尝试分配内存 
	  __alloc_pages_slowpath  //3.如果快路径尝试分配内存失败,慢路径尝试分配内存
	
	具体 查看 https://zhuanlan.zhihu.com/p/258921453
	强烈推荐


prepare_alloc_context   // 设置 get_page_from_freelist  函数的三个参数
	1. struct alloc_context *ac
		ac->migratetype = gfp_migratetype(gfp_mask); // 设置 需要的 迁移类型 , 与 zone->free_area[order].free_list[migratetype] 相关
	2. gfp_t *alloc_mask
		*alloc_mask |= __GFP_HARDWALL;
	3. unsigned int *alloc_flags
		*alloc_flags = current_alloc_flags(gfp_mask, *alloc_flags);

get_page_from_freelist 
	for_next_zone_zonelist_nodemask(zone, z, ac->highest_zoneidx, ac->nodemask) { // 按照 ZONE_HIGHMEM ZONE_NORMAL ZONE_DMA 的优先级 遍历zone
		mark = wmark_pages(zone, alloc_flags & ALLOC_WMARK_MASK); // 获取当前水位线
		if (!zone_watermark_fast(zone, order, mark, ac->highest_zoneidx, alloc_flags, gfp_mask)) { 
			// 与 alloc_pages 设置的 水位线FLAG 比较
			// 此时进入 if 函数体 表示, 当前水位线 <= alloc_pages 设置的水位线FLAG,表示不能再分配物理页面
			
			if (alloc_flags & ALLOC_NO_WATERMARKS) goto try_this_zone;	
				// 表示 alloc_pages 设置的 水位线FLAG 表示 忽略 水位线,则直接到 try_this_zone 标号 直接 分配 页面
		}
		try_this_zone:
		page = rmqueue(ac->preferred_zoneref->zone, zone, order, gfp_mask, alloc_flags, ac->migratetype);
			if (likely(order == 0)) rmqueue_pcplist(preferred_zone, zone, gfp_flags, migratetype, alloc_flags);
				// 查询 per_cpu_pages (pcp) 维护的 链表 是否可以满足内存申请
			else  __rmqueue(zone, order, migratetype, alloc_flags);
				// 从伙伴系统申请,查询的链表为
				// zone->free_area[order].free_list[migratetype]
				
				__rmqueue_smallest(zone, order, migratetype);
					area = &(zone->free_area[current_order]);
					page = get_page_from_free_area(area, migratetype);
					del_page_from_free_list(page, zone, current_order);
	}

__alloc_pages_slowpath
	调用内存短缺的各种机制
		... relaim
		... compact
		... oom killer
		... kswapd
	get_page_from_freelist(gfp_mask, order, alloc_flags, ac);


  • free
free_pages/free_page
__free_pages/__free_page


free_pages(unsigned long addr, unsigned int order)
	__free_pages(virt_to_page((void *)addr), order);
		free_the_page(page, order)
			__free_pages_ok
				free_one_page
					__free_one_page
						add_to_free_list(page, zone, order, migratetype);
	
其他
  • buddy 的 本质
buddy系统 只会维护空闲的块,已经分配出去的块不属于buddy系统
对某一些块 调用 free_pages 后, 才会将其 放入 buddy 系统中
---

拆解&合并
buddy的本质就是按照 2^n 拆解&合并

  • buddy 的问题及解决方案

// 有没有 存在的 虚拟内存 的问题


1. 物理内存碎片问题
	buddy 合并
		时机: free_pages
		方法:
		线程:无
	规整 compact
		时机: alloc
		方法:
		线程: 1个线程 kcompactd0
2. 物理内存不足问题
	回收 reclaim
		时机: alloc内存紧缺时/周期/系统睡眠
		方法:
		线程: 2个线程 kswapd0 oom_reaper
3. 无法申请到连续的物理页
	CMA  contiguous memory allocator
		时机: alloc连续内存时
		方法: 
			预留一段的内存给驱动使用,但当驱动不用的时候,CMA区域可以分配给用户进程用作匿名内存或者页缓存。
			而当驱动需要使用时,就将进程占用的内存通过回收或者迁移的方式将之前占用的预留内存腾出来,供驱动使用。
		线程:
---
5. 如果 __GFP_DMA 被置位, 则 只能从 ZONE_DMA 内存管理区获取 page
6. 如果 __GFP_HIGH 没被置位, 则 依次从  ZONE_NORMAL ZONE_DMA 内存管理区获取 page
7. 如果 __GFP_HIGH 被置位, 则 依次从  ZONE_HIGHMEM ZONE_NORMAL ZONE_DMA 内存管理区获取 page

---


页框无限制,可存储任意数据
x86硬件对页框有限制			导致新增ZONE(ZONE对页框分类)
原来没有ZONE,或者只有一个ZONE 	: 		ZONE_NORMAL		16MB 	-	896MB
1.DMA只能对RAM前16MB寻址		: 新增了 ZONE_DMA		0MB 	-	16MB
2.32bit不能寻址所有的物理内存 	: 新增了 ZONE_HIGHMEM	896M 	- 

arm32呢???
页框无限制,可存储任意数据
arm32硬件对页框有限制			导致新增ZONE(ZONE对页框分类)
原来没有ZONE,或者只有一个ZONE 	: 		ZONE_NORMAL		0MB 	-	760MB
1.32bit不能寻址所有的物理内存 	: 新增了 ZONE_HIGHMEM	760MB 	-  


---

现状
没有配置CONFIG_ZONE_DMA CONFIG_ZONE_DMA32 CONFIG_HIGHMEM
只有两个 ZONE : ZONE_NORMAL ZONE_MOVABLE

---
对于arm32来讲,什么时候需要配置 CONFIG_HIGHMEM?
200MB 是不需要配置 CONFIG_HIGHMEM的
1GB 是需要配置的,因为内核空间只有1G,memblock预留之后小于1G,不能完全映射

---


  • S3C6410 的 DMA

6410 是 有 DMA 的
源和目标 在 系统总线/外围总线 中(4种情况) 皆可用
采用的是 ARM的 IP PL080
4个DMA ,每个DMA 8个通道

对内存没有限制
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值