linux 每-CPU 的变量

linux 每-CPU 的变量,第1张

概述每-CPU 变量是一个有趣的 2.6 内核的特性. 当你创建一个每-CPU 变量, 系统中每个处理 器获得它自己的这个变量拷贝. 这个可能象一个想做的奇怪的事情, 但是它有自己的优点. 存取每-CPU 变量不需要(几乎)加锁, 因为每个处理器使用它自己的拷贝. 每-CPU 变量也 可存在于它们各自的处理器缓存中, 这样对于频繁更新的量子带来了显著的更好性能.   一个每-CPU 变量的好的使用例子

每-cpu 变量是一个有趣的 2.6 内核的特性. 当你创建一个每-cpu 变量,系统中每个处理 器获得它自己的这个变量拷贝. 这个可能象一个想做的奇怪的事情,但是它有自己的优点. 存取每-cpu 变量不需要(几乎)加锁,因为每个处理器使用它自己的拷贝. 每-cpu 变量也 可存在于它们各自的处理器缓存中,这样对于频繁更新的量子带来了显著的更好性能.

 

一个每-cpu 变量的好的使用例子可在网络子系统中找到. 内核维护无结尾的计数器来跟踪 有每种报文类型有多少被接收; 这些计数器可能每秒几千次地被更新. 不去处理缓存和加 锁问题,网络开发者将统计计数器放进每-cpu 变量. 现在更新是无锁并且快的. 在很少的 机会用户空间请求看到计数器的值,相加每个处理器的版本并且返回总数是一个简单的事 情.

 

每-cpu 变量的声明可在 <linux/percpu.h> 中找到. 为在编译时间创建一个每-cpu 变量,使用这个宏定义:

 

define_PER_cpu(type,name);

 

如果这个变量(称为 name 的)是一个数组,包含这个类型的维数信息. 因此,一个有 3 个整数的每-cpu 数组应当被创建使用:

 

define_PER_cpu(int[3],my_percpu_array);

 

每-cpu 变量几乎不必使用明确的加锁来 *** 作. 记住 2.6 内核是可抢占的; 对于一个处理 器,在修改一个每-cpu 变量的临界区中不应当被抢占. 并且如果你的进程在对一个每-cpu 变量存取时将,要被移动到另一个处理器上,也不好. 因为这个原因,你必须显式使用 get_cpu_var 宏来存取当前处理器的给定变量拷贝,并且当你完成时调用 put_cpu_var. 对 get_cpu_var 的调用返回一个 lvalue 给当前处理器的变量版本并且禁止抢占. 因为 一个 lvalue 被返回,它可被赋值给或者直接 *** 作. 例如,一个网络代码中的计数器时使 用这 2 个语句来递增的:

 

get_cpu_var(sockets_in_use)++; put_cpu_var(sockets_in_use);

 

你可以存取另一个处理器的变量拷贝,使用: per_cpu(variable,int cpu_ID);

如果你编写使处理器涉及到对方的每-cpu 变量的代码,你,当然,一定要实现一个加锁机 制来使存取安全.

动态分配每-cpu 变量也是可能的. 这些变量可被分配,使用: voID *alloc_percpu(type);

voID *  alloc_percpu(size_t size,size_t align);

 

在大部分情况,alloc_percpu 做的不错; 你可以调用 alloc_percpu 在需要一个特别 的对齐的情况下. 在任一情况下,一个 每-cpu 变量可以使用 free_percpu 被返回给系 统. 存取一个动态分配的每-cpu 变量通过 per_cpu_ptr 来完成:

 

per_cpu_ptr(voID *per_cpu_var,int cpu_ID);

 

这个宏返回一个指针指向 per_cpu_var 对应于给定 cpu_ID 的版本. 如果你在简单地读 另一个 cpu 的这个变量的版本,你可以解引用这个指针并且用它来完成. 如果,但是,你在 *** 作当前处理器的版本,你可能需要首先保证你不能被移出那个处理器. 如果你存取 这个每-cpu 变量的全部都持有一个自旋锁,万事大吉. 常常,你需要使用 get_cpu 来阻止在使用变量时的抢占. 因此,使用动态每-cpu 变量的代码会看来如此:

 

int cpu;

cpu = get_cpu()

ptr = per_cpu_ptr(per_cpu_var,cpu);

/* work with ptr */ put_cpu();

 

当使用编译时每-cpu 变量时,get_cpu_var 和 put_cpu_var 宏来照看这些细节. 动态 每-cpu 变量需要更多的显式的保护.

 

每-cpu 变量能够输出给每个模块,但是你必须使用一个特殊的宏版本:

 

EXPORT_PER_cpu_SYMBol(per_cpu_var); EXPORT_PER_cpu_SYMBol_GPL(per_cpu_var);

 

为在一个模块内存取这样一个变量,声明它,使用: DECLARE_PER_cpu(type,name);

DECLARE_PER_cpu 的使用(不是 define_PER_cpu)告知编译器进行一个外部引用.

 

如果你想使用每-cpu 变量来创建一个简单的整数计数器,看一下在

<linux/percpu_counter.h> 中的现成的实现. 最后,注意一些体系有有限数量的地址空 间变量给每-cpu 变量. 如果你创建每-cpu 变量在你自己的代码,你应当尽量使它们小.

总结

以上是内存溢出为你收集整理的linux 每-CPU 的变量全部内容,希望文章能够帮你解决linux 每-CPU 的变量所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/1019050.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存