每-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 的变量的更多相关文章

  1. linux:CPU私有变量(per-CPU变量)

    一.简介2.6内核上一个新的特性就是per-CPU变量.顾名思义,就是每个处理器上有此变量的一个副本.per-CPU的最大优点就是,对它的访问几乎不需要锁,因为每个CPU都在自己的副本上工作.task ...

  2. linux:cpu 每-CPU 的变量

    每-CPU 的变量 每-CPU 变量是一个有趣的 2.6 内核的特性. 当你创建一个每-CPU变量, 系统中每个处理器获得它自己的这个变量拷贝. 这个可能象一个想做的奇怪的事情, 但是它有自己的优点. ...

  3. Linux内核同步 - Per-CPU变量

    一.源由:为何引入Per-CPU变量? 1.lock bus带来的性能问题 在ARM平台上,ARMv6之前,SWP和SWPB指令被用来支持对shared memory的访问: SWP <Rt&g ...

  4. LINUX内核CPU负载均衡机制【转】

    转自:http://oenhan.com/cpu-load-balance 还是神奇的进程调度问题引发的,参看Linux进程组调度机制分析,组调度机制是看清楚了,发现在重启过程中,很多内核调用栈阻塞在 ...

  5. linux定时任务crond export变量问题

    linux定时任务crond export变量问题 1)我写了一个重启resin的脚本,由于业务原因,需要定时在某一个时间重启下resin服务器,于是就在 crontab里配置了如下内容: 50 17 ...

  6. linux配置java环境变量(详细)

    linux配置java环境变量(详细) 本文完全引用自: http://www.cnblogs.com/samcn/archive/2011/03/16/1986248.html 一. 解压安装jdk ...

  7. linux配置java环境变量

    linux配置java环境变量(详细) 一. 解压安装jdk 在shell终端下进入jdk-6u14-linux-i586.bin文件所在目录, 执行命令 ./jdk-6u14-linux-i586. ...

  8. Linux 查看CPU,内存,硬盘 !转

    Linux 查看CPU,内存,硬盘 本文转自:http://hi.baidu.com/mumachuntian/item/a401368dbe8a66cab07154e8 1 查看CPU 1.1 查看 ...

  9. Linux里设置环境变量的方法(export PATH)

    1.动态库路径的设置 Linux下调用动态库和windows不一样.linux 可执行程序是靠配置文件去读取路径的,因此有些时候需要设置路径 具体操作如下 export LD_LIBRARY_PATH ...

随机推荐

  1. git reset三种模式

    reset三种模式区别和使用场景 区别: --hard:重置位置的同时,直接将 working Tree工作目录. index 暂存区及 repository 都重置成目标Reset节点的內容,所以效 ...

  2. jQuery圆盘抽奖

    在线演示 本地下载

  3. python 正则表达式简介

  4. ACK容器服务虚拟节点使用阿里云日志服务来收集业务容器日志

    按照这篇博文的介绍,可以在ACK集群上通过Helm的方式部署虚拟节点,提升集群的弹性能力.现在,通过虚拟节点部署的ECI弹性容器实例也支持将stdout输出.日志文件同步到阿里云日志服务(SLS)进行 ...

  5. Windows中查看PowerShell版本和virbox版本,vagrant 版本

    我并不是很熟悉什么是PowerShell,但是有种直觉是:如果想在Windows中使用系统自带的功能取代bash shell,PowerShell或许是比DOS批处理更好的选择.不过,从头开始再来一门 ...

  6. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十六章:实例化和截头锥体裁切

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十六章:实例化和截头锥体裁切 代码工程地址: https://git ...

  7. python 源文件编码

  8. el-dialog 一些问题 局中滚动

    .el-dialog { position: absolute; top: 50%; left: 50%; margin: 0 !important; transform: translate(-50 ...

  9. 动态设置iframe高度

    <%//动态设置iframe高度 %><script language="javascript" type="text/javascript" ...

  10. 2019-11-20-dotnet-Blazor-用-C#-控制界面行为

    title author date CreateTime categories dotnet Blazor 用 C# 控制界面行为 lindexi 2019-11-20 18:26:25 +0800 ...