博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OK6410A 开发板 (八) 67 linux-5.11 OK6410A linux 内核同步机制 per-cpu的实现
阅读量:4285 次
发布时间:2019-05-27

本文共 3263 字,大约阅读时间需要 10 分钟。

  • 解决的问题是什么
SMP 引起的竞态 // 其实是避开了 SMP的竞态 , 因为 每个cpu 一个同名变量,SMP间根本不会有竞态发生不能解决 其他原因 引起的竞态
  • 其他要点
在 CONFIG_SMP  下才有意义, 不配置 CONFIG_SMP   也能用,但是就失去了他的意义(作用,) 	// 没有SMP,SMP引起的竞态根本就不存在了	// 而 per-cpu 就是 因为 SMP引起的竞态 才被设计出来的在某些体系结构上,per-CPU变量可使用的地址空间是受限的,要尽量保持这些变量比较小 // 在 arm 上好像没限制per-cpu 并没有利用 同步原语 和 屏障,因为 per-cpu的实现 是 避开了SMP的竞态
  • 参考资料
https://zhuanlan.zhihu.com/p/157563328https://zhuanlan.zhihu.com/p/260986194

应用场景及API

per-cpu 机制 解决了 三个情景下的 per-cpu 变量	1. 内核静态percpu变量	2. 模块静态percpu变量	3. 动态percpu变量	// 每个情景的实现有相同部分,又有不同部分per-cpu 机制 针对 三个情景 提供了 几种初始化,几种api	A. 	 per-cpu机制的初始化 setup_per_cpu_areas		B1.  内核静态percpu变量的定义  DEFINE_PER_CPU(type, name)	B2.  模块静态percpu变量的定义  DEFINE_PER_CPU(type, name)	B3.  动态percpu变量的定义		alloc_percpu(type)		C.   percpu变量地址的获取 	this_cpu_ptr(var)	D.   percpu变量的获取			per_cpu(var,cpu)

per-cpu变量 内存相关

  • per-cpu变量 相关内存的初始化
给每一个cpu分配了一块内存pcpu_area(xKB)每个cpu的xKB内存都是连续的(同group的才连续).N个cpu对应的内存大小是 N*x一个xKB内存分块 分为 static reserved dynamic// 整个 NR_CPU 个内存块 从 pcpu_base_addr 开始每个cpu对应的内存块 大小是怎么决定的// 根据 下面的三个值 以及一些 最大最小值(某个区间最小不能比什么小) 决定的值为Y,然后Y*cpu个数= x// 1. static_size = __per_cpu_end - __per_cpu_start;// 2. pcpu_embed_first_chunk 的第一个参数:reserved_size// 2. pcpu_embed_first_chunk 的第二个参数:dyn_size从 pcpu_base_addr  开始的 N*x大小的 空间是什么时候申请的//setup_per_cpu_areas->pcpu_embed_first_chunk->alloc_fn/pcpu_dfl_fc_alloc->memblock_virt_alloc_from_nopanic
  • per-cpu变量 相关内存的管理方法(pcpu_slot)
一个xKB内存分块 分为 static reserved dynamicreserved dynamic 被 chunk 管理 ,而 static 没有用 chunk 管理per-cpu 有一个内存代理商 pcpu_slot , 管理了 这些 reserved dynamicpcpu_slot 也是像 buddy 一样(利用order)管理内存的pcpu_slot  是 从 buddy 和 memblock 申请的内存,申请的内存通过pcpu_chunk_relocate 加入 per-cpu // pcpu_slot 没有内存时,会从buddy申请	其中一个内存块 pcpu_first_chunk 是 从 memblock 申请的	其他的内存 都是从buddy申请的  pcpu_slot  的消费者	per-cpu 创建per-cpu变量的时候,会用到内存,则会从 pcpu_slot  申请	只供 动态percpu变量 使用 alloc_percpu   申请	模块静态percpu变量 也会使用

per-cpu变量的存放与获取

percpu变量的存放	内核静态percpu变量 被 复制到 每个cpu的内存块的static区域,static 不可扩展(不存在空间不够的情况) 	模块静态percpu变量 被 复制到 每个cpu的内存块的reserved区域,空间不够,reserved 可扩展	动态percpu变量	 被 放在   每个cpu的内存块的dynamic 区域,空间不够,dynamic 可扩展percpu变量的获取	percpu变量存放后 给出一个 值 ptr,通过this_cpu_ptr(即ptr + delta + pcpu_unit_offsets[cpu]) 获取 percpu变量的 实际地址	针对 内核静态percpu变量 	: ptr 的值 位于 __per_cpu_start __per_cpu_end 之间		// 值是在编译的时候决定的	针对 模块静态percpu变量 	: ptr 的值 为 chunk->base_addr + off - delta // delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;		// 针对cpu0不同的per-cpu变量, off 肯定不同,chunk->base_addr可能不同	针对 动态percpu变量 	 	: ptr 的值 为 chunk->base_addr + off - delta // 和 模块静态percpu变量 的chunk 不是一个chunk		// 针对cpu0不同的per-cpu变量, off 肯定不同,chunk->base_addr可能不同

其他

// linux-4.0setup_per_cpu_areas	pcpu_embed_first_chunk		pcpu_build_alloc_info			ptr = memblock_virt_alloc_nopanic(PFN_ALIGN(ai_size), 0) // 1000		areas = memblock_virt_alloc_nopanic(areas_size, 0); // 1000		ptr = alloc_fn(cpu, gi->nr_units * ai->unit_size, atom_size);/pcpu_dfl_fc_alloc			memblock_virt_alloc_from_nopanic // 2c000	// ---------------------- per-cpu变量区域的申请,4核心,一个0xb000大小		pcpu_setup_first_chunk			group_offsets = memblock_virt_alloc // 4			group_sizes = memblock_virt_alloc 	// 4			unit_map = memblock_virt_alloc 			// 10			unit_off = memblock_virt_alloc 			// 10 			pcpu_slot = memblock_virt_alloc(		// 78			schunk = memblock_virt_alloc 			// 44			dchunk = memblock_virt_alloc 			// 44

转载地址:http://ynigi.baihongyu.com/

你可能感兴趣的文章
PHP制作验证码
查看>>
常用的CSS Hack技术集锦
查看>>
IE 8兼容:X-UA-Compatible的解释
查看>>
关于form.submit()不能提交表单的错误原因
查看>>
初识HTML 5:关于它的三个三
查看>>
Canvas入门(1):绘制矩形、圆、直线、曲线等基本图形
查看>>
Canvas入门(2):图形渐变和图像形变换
查看>>
Canvas入门(3):图像处理和绘制文字
查看>>
《千与千寻》给读者带来了什么?
查看>>
JQuery笔记:JQuery和JavaScript的联系与区别
查看>>
PHP的MySQL扩展:PHP访问MySQL的常用扩展函数
查看>>
PHP实现分页:文本分页和数字分页
查看>>
博客收录集的源代码分享,需要那就快来吧
查看>>
杂谈:HTML 5的消息通知机制
查看>>
Ajax异步请求PHP数据
查看>>
百家搜索:在网站中添加Google、百度等搜索引擎
查看>>
关于坛友的一个布局问题的解答
查看>>
网页抓取:PHP实现网页爬虫方式小结
查看>>
国民岳父的“屁民理论”
查看>>
我为什么要写博客?
查看>>