LInux内核学习 -- perCPU变量

环境

linux 4.19

关于perCPU变量

percpu变量的介绍,这位老哥做了介绍,包括为什么要有这样的变量以及优势:linux内核之Per-CPU变量,我把这个老哥的总结复制下来:

  1. 通过Per-cpu变量除了可以分配内存,还有一个最大的好处就是不需要考虑同步。最好的同步技术就是把不需要同步的内核放在首位,因为每种显示的同步原语都有不容忽视的开销。
  2. 本质:Per-cpu变量主要是数据结构的数组,每个cpu对应数组中的一个元素。
  3. 位置:Per-cpu数组在主存中被排列,以使每个数据结构放在硬件高速缓存中的不同行(参考第二章硬件高速缓存)。这样,对每cpu数组的并发访问不会造成高速缓存行的窃用和实效(这种操作会带来昂贵的系统性能开销)。

同时简单讲了下percpu变量的初始化方法和获取方式。但是这篇老哥没有讲的很细。但是这篇博客讲的很细节:PERCPU变量实现

最终,获取获取percpu变量相当于percpu变量指针的ptr(符号地址)加上__my_cpu_offset,__my_cpu_offset宏即是从当前cpu的tpidr_el1、tpidr_el2寄存器中取出此前设置的__per_cpu_offset[cpu]值,得到这个percpu变量。能使用__per_cpu_offset[cpu]获取到percpu变量,是因为在初始化静态percpu的时候使用了这个数组。具体的实现过程可以看上面引用的博客。

perCPU变量:__entry_task

该变量已经在内核中静态定义为percpu变量:

arch/arm64/kernel/process.c:
// 该宏是内核中用于声明和定义 per-CPU 变量的宏。这些宏允许内核在每个 CPU 上拥有独立的变量副本
// __attribute__((section(".data..percpu"))) int per_cpu_n。这意味着我们在 .data..percpu 段有了一个 per_cpu_n 变量
DEFINE_PER_CPU(struct task_struct *, __entry_task);

static void entry_task_switch(struct task_struct *next)
{
	__this_cpu_write(__entry_task, next);
}

首先定义了__entry_task这个percpu变量(其实是一片连续内存,每个cpu都有一个对应的offset从这个percpu对应的内存中取到本cpu id号对应的变量)。然后在调用entry_task_switch()时,通过__this_cpu_write()函数修改本cpu的percpu变量值,从而记录next进程的task_struct。该函数在__switch_to()函数中调用,进程切换函数:

arch/arm64/kernel/process.c:
__notrace_funcgraph struct task_struct *__switch_to(struct task_struct *prev,
				struct task_struct *next)
{
	struct task_struct *last;
	...
	...
	entry_task_switch(next);
	...
	...
	last = cpu_switch_to(prev, next);

	return last;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值