linux 每-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私有变量(per-CPU变量)
一.简介2.6内核上一个新的特性就是per-CPU变量.顾名思义,就是每个处理器上有此变量的一个副本.per-CPU的最大优点就是,对它的访问几乎不需要锁,因为每个CPU都在自己的副本上工作.task ...
- linux:cpu 每-CPU 的变量
每-CPU 的变量 每-CPU 变量是一个有趣的 2.6 内核的特性. 当你创建一个每-CPU变量, 系统中每个处理器获得它自己的这个变量拷贝. 这个可能象一个想做的奇怪的事情, 但是它有自己的优点. ...
- Linux内核同步 - Per-CPU变量
一.源由:为何引入Per-CPU变量? 1.lock bus带来的性能问题 在ARM平台上,ARMv6之前,SWP和SWPB指令被用来支持对shared memory的访问: SWP <Rt&g ...
- LINUX内核CPU负载均衡机制【转】
转自:http://oenhan.com/cpu-load-balance 还是神奇的进程调度问题引发的,参看Linux进程组调度机制分析,组调度机制是看清楚了,发现在重启过程中,很多内核调用栈阻塞在 ...
- linux定时任务crond export变量问题
linux定时任务crond export变量问题 1)我写了一个重启resin的脚本,由于业务原因,需要定时在某一个时间重启下resin服务器,于是就在 crontab里配置了如下内容: 50 17 ...
- linux配置java环境变量(详细)
linux配置java环境变量(详细) 本文完全引用自: http://www.cnblogs.com/samcn/archive/2011/03/16/1986248.html 一. 解压安装jdk ...
- linux配置java环境变量
linux配置java环境变量(详细) 一. 解压安装jdk 在shell终端下进入jdk-6u14-linux-i586.bin文件所在目录, 执行命令 ./jdk-6u14-linux-i586. ...
- Linux 查看CPU,内存,硬盘 !转
Linux 查看CPU,内存,硬盘 本文转自:http://hi.baidu.com/mumachuntian/item/a401368dbe8a66cab07154e8 1 查看CPU 1.1 查看 ...
- Linux里设置环境变量的方法(export PATH)
1.动态库路径的设置 Linux下调用动态库和windows不一样.linux 可执行程序是靠配置文件去读取路径的,因此有些时候需要设置路径 具体操作如下 export LD_LIBRARY_PATH ...
随机推荐
- Directx11教程(44) alpha blend(1)
原文:Directx11教程(44) alpha blend(1) 我们知道,D3D11中按Frame来渲染物体,每个Frame中又可能包含若干个primitive,如下面的示意图所示: ...
- 原生js分页
<html> <head> <meta charset='utf-8'> <style type="text/css"> #idDa ...
- WPF自定义控件 依赖属性绑定
控件cs文件 using System.ComponentModel; using System.Windows; using System.Windows.Controls; using Syste ...
- phpmyadmin误删表后的恢复过程
转自:http://blog.csdn.net/ssrc0604hx/article/details/18717983 话说今天不知道是抽风了还是失魂了,在用phpmyadmin删除测试数据时,竟然将 ...
- hdu1532&&poj1273 最大流
Dinic算法: 层次图:根据源点到该点的距离建图,这里设相邻的都差1. (下面部分转) 在这幅图中我们首先要增广1->2->4->6,这时可以获得一个容量为2的流,但是如果不建立4 ...
- KiCad 5.1.0 镜像圆弧后错位问题
KiCad 5.1.0 镜像圆弧后错位问题 看官方回复这个问题将在 5.1.3 进行修复,因为这段时间在举行 KiCon 活动. 看到这个问题并不是非常严重,不是致命的,所以已经从 5.1.0 跳到 ...
- 洛谷2375 BZOJ 3670动物园题解
题目链接 洛谷链接 我们发现题目要我们求的num[i]东西本质上其实是 求有多少以i结尾的非前缀且能与前缀匹配的字符串,而且要求字符串长度小于(i/2) 我们先不考虑字符串长度的限制,看所有以i结尾的 ...
- 巨蟒python全栈开发-第11阶段 ansible_project4
1.主机的增删改查 2.初始化的增删改查 3.项目的增删改查
- Visual Studio中,无法嵌入互操作类型“……”,请改用适用的接口的解决方法
解决方案:选中项目中引入的dll,鼠标右键,选择属性,把“嵌入互操作类型”设置为False,问题轻松解决. 问题分析: 1.”嵌入互操作类型”中的嵌入就是引进.导入的意思,类似于c#中using,c中 ...
- 21Hash算法以及暴雪Hash
一:哈希表简介 哈希表是一种查找效率极高的数据结构,理想情况下哈希表插入和查找操作的时间复杂度均为O(1),任何一个数据项可以在一个与哈希表长度无关的时间内计算出一个哈希值(key),然后在常量时间内 ...