版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rikeyone/article/details/84960446
per CPU变量
per-CPU变量从字面上即可猜出它大概的含义,这种类型的变量实际上每个CPU都分配了一个该变量的副本。对于per-CPU的访问几乎不需要锁定,因为每个CPU都工作在自己的副本上,另外per CPU变量还可以保存在CPU自己的缓存上,这样就最大的优化访问速度和减少竞争。
静态定义和访问
#define DEFINE_PER_CPU(type, name)
DEFINE_PER_CPU_SECTION(type, name, "")
我们使用DEFINE_PER_CPU宏定义在编译创建一个per cpu变量。
访问当前处理的变量的副本可以使用如下API:
get_cpu_var()
set_cpu_var()
他们的实现如下所示:
#define get_cpu_var(var)
(*({
preempt_disable();
this_cpu_ptr(&var);
}))
#define put_cpu_var(var)
do {
(void)&(var);
preempt_enable();
} while (0)
那么假如我们想要访问其他CPU上的变量,那就需要通过如下接口:
#define per_cpu(var, cpu) (*per_cpu_ptr(&(var), cpu))
通过传入变量名和对应CPU的id,即可访问到该CPU上的变量副本。这个时候我们访问其他CPU上的数据就需要特别小心,必须加上锁,避免出现同步访问的情况。
动态定义和访问
per cpu变量支持动态定义,相关API如下:
#define alloc_percpu(type) \
(typeof(type) __percpu *)__alloc_percpu(sizeof(type), \
__alignof__(type))
我们一般都可以使用alloc_percpu接口来动态的创建一个per cpu变量。通过如下接口来释放per cpu变量:
void free_percpu(void __percpu *__pdata);
访问我们动态创建的per cpu变量需要使用如下接口:
per_cpu_ptr(void *val, int cpu_id)
如果我们的per cpu变量需要在另一个模块中使用,还需要import导出该变量:
#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(var)
#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(var)
在其他的模块访问时需要先声明:
DECLARE_PER_CPU(type, name)
#define DECLARE_PER_CPU(type, name) \
DECLARE_PER_CPU_SECTION(type, name, "")