正常的全局变量不是每个CPU.自动变量在堆栈上,不同的CPU使用不同的堆栈,所以自然会得到单独的变量.
我想你是指Linux的每CPU可变基础架构.
大部分魔法都在这里(asm-generic / percpu.h):
extern unsigned long __per_cpu_offset[NR_CPUS];
#define per_cpu_offset(x) (__per_cpu_offset[x])
/* Separate out the type, so (int[3], foo) works. */
#define DEFINE_PER_CPU(type, name) \
__attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name
/* var is in discarded region: offset to particular copy we want */
#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
#define __get_cpu_var(var) per_cpu(var, smp_processor_id())
宏RELOC_HIDE(ptr,offset)简单地将ptr以给定的偏移量(以字节为单位)进行,而不管指针类型如何.
它有什么作用?
>定义DEFINE_PER_CPU(int,x)时,在特殊的.data.percpu部分中创建一个整数__per_cpu_x.>当内核加载时,这个部分被加载多次 – 每个CPU一次(这部分魔法不在上面的代码中).> __per_cpu_offset数组填充了副本之间的距离.假设使用每个cpu数据的1000字节,__per_cpu_offset [n]将包含1000 * n.>符号per_cpu__x将在加载期间重新定位到CPU 0的per_cpu__x.> __get_cpu_var(x),当在CPU 3上运行时,将转换为* RELOC_HIDE(& per_cpu__x,__per_cpu_offset [3]).这从CPU 0的x开始,添加CPU 0的数据和CPU 3之间的偏移,并最终取消引用结果指针.