每-CPU变量

现代SMP操作系统使用每-CPU数据——这些数据对每个处理器都是唯一的。通常,每-CPU数据存储在一个数组中。数组中的每项对应系统上的一个可能的处理器。如:

unsigned long my_percpu[NR_CPUS];

访问的方式如下:

int cpu;

cpu = get_cpu(); /* get current processor and disable kernel preemption */

my_percpu[cpu]++; /* ... or whatever */

printk(“my_percpu on cpu=%d is %lu\n”, cpu, my_percpu[cpu]);

put_cpu(); /* enable kernel preemption */

 

访问每-CPU数据唯一需要考虑的就是内核抢占。内核抢占导致了两个问题,如下所示:

l  如果运行的代码被抢占并被调度到另一个处理器上运行,cpu变量不再合法,因为它指向了错误的处理器(通常,代码在获得当前处理器后不能睡眠)。

l  如果另一个任务抢占了当前运行的代码,它可能并发地访问相同处理器上的my_percpu,从而导致了一个竞态发生。

然而,任何担心都是多余的,因为get_cpu()在返回处理器编号的同时,也会禁用内核抢占。put_cpu()则恢复内核抢占。注意:如果使用smp_processor_id()来获取当前处理器的编号,内核抢占则并不会被禁止。

新的percpu接口(2.6后)

2.6内核引入了一个新的接口,称为percpu,,用于创建和操作每-CPU数据。该接口扩展了上述例子。新的接口更简单,但旧的接口依然有效。

定义:

DEFINE_PER_CPU(type, name);

声明:

DECLARE_PER_CPU(type, name);

操作变量函数:

get_cpu_var()   put_cpu_var()

如:

get_cpu_var(name)++; /* increment name on this processor,同时禁用内核抢占 */

put_cpu_var(name); /* done; enable kernel preemption */

访问另一个处理器的每-CPU数据:

per_cpu(name, cpu)++; /* increment name on the given processor */,注意,该函数并没有禁用内核抢占。

动态分配每-CPU数据

内核实现了一个动态分配器,类似于kmalloc(),用于创建每-CPU数据。这些函数原型如下:

void *alloc_percpu(type); /* a macro */

void *__alloc_percpu(size_t size, size_t align);

void free_percpu(const void *);

get_cpu_var(ptr); /* return a void pointer to this processor’s copy of ptr */

put_cpu_var(ptr); /* done; enable kernel preemption */

使用例子如下:

void*percpu_ptr;

unsignedlong*foo;

percpu_ptr=alloc_percpu(unsignedlong);

if(!ptr)

/*errorallocatingmemory..*/

foo=get_cpu_var(percpu_ptr);

/*manipulatefoo..*/

put_cpu_var(percpu_ptr);

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值