Linux内核中的per-cpu变量

版权声明:本文为博主原创文章,未经博主允许不得转载。 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, "")

猜你喜欢

转载自blog.csdn.net/rikeyone/article/details/84960446