linux内核源码分析之per-CPU
Posted 为了维护世界和平_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux内核源码分析之per-CPU相关的知识,希望对你有一定的参考价值。
目录
per_cpu机制就是让每个处理器都分配了该变量的副本,有自己的私有数据段,不需要考虑与其他它处理器的竞争的问题,该副本可以充分利用处理器本地的硬件缓冲cache来提供访问速度。
per-CPU按照存储变量的空间来源分为
- 静态per-CPU变量:存储空间是在代码编译时静态分配的
- 动态per-CPU变量,存储空间是在代码的执行期间动态分配的
静态声明与定义
#define DECLARE_PER_CPU(type, name) \\
DECLARE_PER_CPU_SECTION(type, name, "")
#define DECLARE_PER_CPU_SECTION(type, name, sec) \\
extern __PCPU_ATTRS(sec) __typeof__(type) name
#define __PCPU_ATTRS(sec) \\
__percpu __attribute__((section(PER_CPU_BASE_SECTION sec))) \\
PER_CPU_ATTRIBUTES
申请动态per-CPU变量
分配per-CPU变量
#define alloc_percpu(type) \\
(typeof(type) __percpu *)__alloc_percpu(sizeof(type), \\
__alignof__(type))
释放:
void free_percpu(void __percpu *ptr)
使用静态per-CPU变量
#define get_cpu_var(var) \\
(*( \\
preempt_disable(); \\
this_cpu_ptr(&var); \\
))
#define put_cpu_var(var) \\
do \\
(void)&(var); \\
preempt_enable(); \\
while (0)
使用一、CPU并行访问计数
多线程中,每个CPU执行的次数
long DriverIOControl( struct file *pslFileStruct, unsigned int uiCmd, unsigned long ulArg )
long *pUsage = NULL;
/* printk( KERN_ALERT DEVICE_NAME ": pUsage = 0x%lx %lx %ld", (unsigned long) pUsage, (unsigned long) (&gUsage), (*pUsage) ); */
preempt_disable();
pUsage = this_cpu_ptr( (long *) (&gUsage) );
(*pUsage)++;
preempt_enable();
return(0);
使用二、在软中断中唤醒
softirq软中断源码,__this_cpu_read()
static void wakeup_softirqd(void)
/* Interrupts are disabled: no need to stop preemption */
struct task_struct *tsk = __this_cpu_read(ksoftirqd);
if (tsk && tsk->state != TASK_RUNNING)
wake_up_process(tsk);
使用三、静/动态per-CPU验证
静态和动态变量的使用,遍历每个CPU的值
#include <linux/module.h>
#include <linux/init.h>
#include <linux/percpu.h>
#include <linux/cpumask.h>
static DEFINE_PER_CPU(long, cpuvar) = 5;
static long __percpu *cpualloc;
static int __init my_init(void)
int cpu;
pr_info("module loaded at 0x%p\\n", my_init);
/* modify the cpuvar value */
for_each_possible_cpu(cpu)
per_cpu(cpuvar, cpu) = 10;
pr_info("init: cpuvar on cpu%d = %ld\\n",
cpu, get_cpu_var(cpuvar));
put_cpu_var(cpuvar);
__this_cpu_write(cpuvar, 10);
/* alloc a percpu value */
cpualloc = alloc_percpu(long);
/* set all cpu for this value */
for_each_possible_cpu(cpu)
*per_cpu_ptr(cpualloc, cpu) = 666;
pr_info("init: cpu:%d cpualloc = %ld\\n",
cpu, *per_cpu_ptr(cpualloc, cpu));
return 0;
static void __exit my_exit(void)
int cpu;
pr_info("exit module...\\n");
for_each_possible_cpu(cpu)
pr_info("cpuvar cpu%d = %ld\\n", cpu, per_cpu(cpuvar, cpu));
pr_info("exit: cpualloc%d = %ld\\n", cpu, *per_cpu_ptr(cpualloc, cpu));
free_percpu(cpualloc);
pr_info("Bye: module unloaded from 0x%p\\n", my_exit);
module_init(my_init);
module_exit(my_exit);
MODULE_AUTHOR("WY");
MODULE_LICENSE("GPL");
[134657.935134] init: cpuvar on cpu0 = 5
[134657.935134] init: cpuvar on cpu1 = 5
[134657.935134] init: cpuvar on cpu2 = 10
[134657.935135] init: cpuvar on cpu3 = 10
[134657.935135] init: cpuvar on cpu4 = 10
[134657.935135] init: cpuvar on cpu5 = 10
[134657.935135] init: cpuvar on cpu6 = 10
[134657.935135] init: cpuvar on cpu7 = 10
[134657.935136] init: cpuvar on cpu8 = 10
[134657.935136] init: cpuvar on cpu9 = 10
[134657.935136] init: cpuvar on cpu10 = 10
[134657.935137] init: cpuvar on cpu11 = 10
[134657.935137] init: cpuvar on cpu12 = 10
[134657.935137] init: cpuvar on cpu13 = 10
[134657.935137] init: cpuvar on cpu14 = 10
[134657.935137] init: cpuvar on cpu15 = 10
[134657.935138] init: cpuvar on cpu16 = 10
[134657.935138] init: cpuvar on cpu17 = 10
[134657.935138] init: cpuvar on cpu18 = 10
[134657.935138] init: cpuvar on cpu19 = 10
[134657.935139] init: cpuvar on cpu20 = 10
[134657.935139] init: cpuvar on cpu21 = 10
[134657.935139] init: cpuvar on cpu22 = 10
[134657.935139] init: cpuvar on cpu23 = 10
[134657.935140] init: cpuvar on cpu24 = 10
[134657.935140] init: cpuvar on cpu25 = 10
[134657.935140] init: cpuvar on cpu26 = 10
[134657.935140] init: cpuvar on cpu27 = 10
[134657.935141] init: cpuvar on cpu28 = 10
[134657.935141] init: cpuvar on cpu29 = 10
[134657.935141] init: cpuvar on cpu30 = 10
[134657.935141] init: cpuvar on cpu31 = 10
[134657.935142] init: cpuvar on cpu32 = 10
[134657.935142] init: cpuvar on cpu33 = 10
[134657.935142] init: cpuvar on cpu34 = 10
[134657.935142] init: cpuvar on cpu35 = 10
[134657.935142] init: cpuvar on cpu36 = 10
[134657.935143] init: cpuvar on cpu37 = 10
[134657.935143] init: cpuvar on cpu38 = 10
[134657.935143] init: cpuvar on cpu39 = 10
[134657.935143] init: cpuvar on cpu40 = 10
[134657.935144] init: cpuvar on cpu41 = 10
[134657.935144] init: cpuvar on cpu42 = 10
[134657.935144] init: cpuvar on cpu43 = 10
[134657.935144] init: cpuvar on cpu44 = 10
[134657.935145] init: cpuvar on cpu45 = 10
[134657.935145] init: cpuvar on cpu46 = 10
[134657.935145] init: cpuvar on cpu47 = 10
[134657.935145] init: cpuvar on cpu48 = 10
[134657.935146] init: cpuvar on cpu49 = 10
[134657.935146] init: cpuvar on cpu50 = 10
[134657.935146] init: cpuvar on cpu51 = 10
[134657.935146] init: cpuvar on cpu52 = 10
[134657.935147] init: cpuvar on cpu53 = 10
[134657.935147] init: cpuvar on cpu54 = 10
[134657.935147] init: cpuvar on cpu55 = 10
[134657.935147] init: cpuvar on cpu56 = 10
[134657.935148] init: cpuvar on cpu57 = 10
[134657.935148] init: cpuvar on cpu58 = 10
[134657.935148] init: cpuvar on cpu59 = 10
[134657.935148] init: cpuvar on cpu60 = 10
[134657.935149] init: cpuvar on cpu61 = 10
[134657.935149] init: cpuvar on cpu62 = 10
[134657.935149] init: cpuvar on cpu63 = 10
[134657.935149] init: cpuvar on cpu64 = 10
[134657.935150] init: cpuvar on cpu65 = 10
[134657.935150] init: cpuvar on cpu66 = 10
[134657.935150] init: cpuvar on cpu67 = 10
[134657.935150] init: cpuvar on cpu68 = 10
[134657.935151] init: cpuvar on cpu69 = 10
[134657.935151] init: cpuvar on cpu70 = 10
[134657.935151] init: cpuvar on cpu71 = 10
[134657.935151] init: cpuvar on cpu72 = 10
[134657.935151] init: cpuvar on cpu73 = 10
[134657.935152] init: cpuvar on cpu74 = 10
[134657.935152] init: cpuvar on cpu75 = 10
[134657.935152] init: cpuvar on cpu76 = 10
[134657.935152] init: cpuvar on cpu77 = 10
[134657.935153] init: cpuvar on cpu78 = 10
[134657.935153] init: cpuvar on cpu79 = 10
[134657.935153] init: cpuvar on cpu80 = 10
[134657.935153] init: cpuvar on cpu81 = 10
[134657.935154] init: cpuvar on cpu82 = 10
[134657.935154] init: cpuvar on cpu83 = 10
[134657.935154] init: cpuvar on cpu84 = 10
[134657.935154] init: cpuvar on cpu85 = 10
[134657.935155] init: cpuvar on cpu86 = 10
[134657.935155] init: cpuvar on cpu87 = 10
[134657.935155] init: cpuvar on cpu88 = 10
[134657.935155] init: cpuvar on cpu89 = 10
[134657.935156] init: cpuvar on cpu90 = 10
[134657.935156] init: cpuvar on cpu91 = 10
[134657.935156] init: cpuvar on cpu92 = 10
[134657.935156] init: cpuvar on cpu93 = 10
[134657.935156] init: cpuvar on cpu94 = 10
[134657.935157] init: cpuvar on cpu95 = 10
[134657.935157] init: cpuvar on cpu96 = 10
[134657.935157] init: cpuvar on cpu97 = 10
[134657.935157] init: cpuvar on cpu98 = 10
[134657.935158] init: cpuvar on cpu99 = 10
[134657.935158] init: cpuvar on cpu100 = 10
[134657.935158] init: cpuvar on cpu101 = 10
[134657.935158] init: cpuvar on cpu102 = 10
[134657.935159] init: cpuvar on cpu103 = 10
[134657.935159] init: cpuvar on cpu104 = 10
[134657.935159] init: cpuvar on cpu105 = 10
[134657.935159] init: cpuvar on cpu106 = 10
[134657.935160] init: cpuvar on cpu107 = 10
[134657.935160] init: cpuvar on cpu108 = 10
[134657.935160] init: cpuvar on cpu109 = 10
[134657.935160] init: cpuvar on cpu110 = 10
[134657.935161] init: cpuvar on cpu111 = 10
[134657.935161] init: cpuvar on cpu112 = 10
[134657.935161] init: cpuvar on cpu113 = 10
[134657.935161] init: cpuvar on cpu114 = 10
[134657.935162] init: cpuvar on cpu115 = 10
[134657.935162] init: cpuvar on cpu116 = 10
[134657.935162] init: cpuvar on cpu117 = 10
[134657.935162] init: cpuvar on cpu118 = 10
[134657.935163] init: cpuvar on cpu119 = 10
[134657.935163] init: cpuvar on cpu120 = 10
[134657.935163] init: cpuvar on cpu121 = 10
[134657.935163] init: cpuvar on cpu122 = 10
[134657.935164] init: cpuvar on cpu123 = 10
[134657.935164] init: cpuvar on cpu124 = 10
[134657.935164] init: cpuvar on cpu125 = 10
[134657.935164] init: cpuvar on cpu126 = 10
[134657.935165] init: cpuvar on cpu127 = 10
[134657.935171] init: cpu:0 cpualloc = 666
[134657.935171] init: cpu:1 cpualloc = 666
[134657.935172] init: cpu:2 cpualloc = 666
[134657.935172] init: cpu:3 cpualloc = 666
[134657.935172] init: cpu:4 cpualloc = 666
[134657.935172] init: cpu:5 cpualloc = 666
[134657.935172] init: cpu:6 cpualloc = 666
[134657.935173] init: cpu:7 cpualloc = 666
[134657.935173] init: cpu:8 cpualloc = 666
[134657.935173] init: cpu:9 cpualloc = 666
[134657.935173] init: cpu:10 cpualloc = 666
[134657.935173] init: cpu:11 cpualloc = 666
[134657.935174] init: cpu:12 cpualloc = 666
[134657.935174] init: cpu:13 cpualloc = 666
[134657.935174] init: cpu:14 cpualloc = 666
[134657.935174] init: cpu:15 cpualloc = 666
[134657.935175] init: cpu:16 cpualloc = 666
[134657.935175] init: cpu:17 cpualloc = 666
[134657.935175] init: cpu:18 cpualloc = 666
[134657.935175] init: cpu:19 cpualloc = 666
[134657.935175] init: cpu:20 cpualloc = 666
[134657.935176] init: cpu:21 cpualloc = 666
[134657.935176] init: cpu:22 cpualloc = 666
[134657.935176] init: cpu:23 cpualloc = 666
[134657.935176] init: cpu:24 cpualloc = 666
[134657.935177] init: cpu:25 cpualloc = 666
[134657.935177] init: cpu:26 cpualloc = 666
[134657.935177] init: cpu:27 cpualloc = 666
[134657.935177] init: cpu:28 cpualloc = 666
[134657.935178] init: cpu:29 cpualloc = 666
[134657.935178] init: cpu:30 cpualloc = 666
[134657.935178] init: cpu:31 cpualloc = 666
[134657.935178] init: cpu:32 cpualloc = 666
[134657.935179] init: cpu:33 cpualloc = 666
[134657.935179] init: cpu:34 cpualloc = 666
[134657.935179] init: cpu:35 cpualloc = 666
[134657.935179] init: cpu:36 cpualloc = 666
[134657.935179] init: cpu:37 cpualloc = 666
[134657.935180] init: cpu:38 cpualloc = 666
[134657.935180] init: cpu:39 cpualloc = 666
[134657.935180] init: cpu:40 cpualloc = 666
[134657.935180] init: cpu:41 cpualloc = 666
[134657.935181] init: cpu:42 cpualloc = 666
[134657.935181] init: cpu:43 cpualloc = 666
[134657.935181] init: cpu:44 cpualloc = 666
[134657.935181] init: cpu:45 cpualloc = 666
[134657.935181] init: cpu:46 cpualloc = 666
[134657.935182] init: cpu:47 cpualloc = 666
[134657.935182] init: cpu:48 cpualloc = 666
[134657.935182] init: cpu:49 cpualloc = 666
[134657.935182] init: cpu:50 cpualloc = 666
[134657.935183] init: cpu:51 cpualloc = 666
[134657.935183] init: cpu:52 cpualloc = 666
[134657.935183] init: cpu:53 cpualloc = 666
[134657.935183] init: cpu:54 cpualloc = 666
[134657.935183] init: cpu:55 cpualloc = 666
[134657.935184] init: cpu:56 cpualloc = 666
[134657.935184] init: cpu:57 cpualloc = 666
[134657.935184] init: cpu:58 cpualloc = 666
[134657.935184] init: cpu:59 cpualloc = 666
[134657.935184] init: cpu:60 cpualloc = 666
[134657.935185] init: cpu:61 cpualloc = 666
[134657.935185] init: cpu:62 cpualloc = 666
[134657.935185] init: cpu:63 cpualloc = 666
[134657.935185] init: cpu:64 cpualloc = 666
[134657.935194] init: cpu:65 cpualloc = 666
[134657.935194] init: cpu:66 cpualloc = 666
[134657.935194] init: cpu:67 cpualloc = 666
[134657.935195] init: cpu:68 cpualloc = 666
[134657.935195] init: cpu:69 cpualloc = 666
[134657.935195] init: cpu:70 cpualloc = 666
[134657.935195] init: cpu:71 cpualloc = 666
[134657.935196] init: cpu:72 cpualloc = 666
[134657.935196] init: cpu:73 cpualloc = 666
[134657.935196] init: cpu:74 cpualloc = 666
[134657.935196] init: cpu:75 cpualloc = 666
[134657.935196] init: cpu:76 cpualloc = 666
[134657.935197] init: cpu:77 cpualloc = 666
[134657.935197] init: cpu:78 cpualloc = 666
[134657.935197] init: cpu:79 cpualloc = 666
[134657.935197] init: cpu:80 cpualloc = 666
[134657.935198] init: cpu:81 cpualloc = 666
[134657.935198] init: cpu:82 cpualloc = 666
[134657.935198] init: cpu:83 cpualloc = 666
[134657.935198] init: cpu:84 cpualloc = 666
[134657.935198] init: cpu:85 cpualloc = 666
[134657.935199] init: cpu:86 cpualloc = 666
[134657.935199] init: cpu:87 cpualloc = 666
[134657.935199] init: cpu:88 cpualloc = 666
[134657.935200] init: cpu:89 cpualloc = 666
[134657.935200] init: cpu:90 cpualloc = 666
[134657.935200] init: cpu:91 cpualloc = 666
[134657.935200] init: cpu:92 cpualloc = 666
[134657.935201] init: cpu:93 cpualloc = 666
[134657.935201] init: cpu:94 cpualloc = 666
[134657.935201] init: cpu:95 cpualloc = 666
[134657.935201] init: cpu:96 cpualloc = 666
[134657.935202] init: cpu:97 cpualloc = 666
[134657.935202] init: cpu:98 cpualloc = 666
[134657.935202] init: cpu:99 cpualloc = 666
[134657.935202] init: cpu:100 cpualloc = 666
[134657.935203] init: cpu:101 cpualloc = 666
[134657.935203] init: cpu:102 cpualloc = 666
[134657.935203] init: cpu:103 cpualloc = 666
[134657.935203] init: cpu:104 cpualloc = 666
[134657.935203] init: cpu:105 cpualloc = 666
[134657.935204] init: cpu:106 cpualloc = 666
[134657.935204] init: cpu:107 cpualloc = 666
[134657.935204] init: cpu:108 cpualloc = 666
[134657.935204] init: cpu:109 cpualloc = 666
[134657.935205] init: cpu:110 cpualloc = 666
[134657.935205] init: cpu:111 cpualloc = 666
[134657.935205] init: cpu:112 cpualloc = 666
[134657.935205] init: cpu:113 cpualloc = 666
[134657.935206] init: cpu:114 cpualloc = 666
[134657.935206] init: cpu:115 cpualloc = 666
[134657.935206] init: cpu:116 cpualloc = 666
[134657.935206] init: cpu:117 cpualloc = 666
[134657.935206] init: cpu:118 cpualloc = 666
[134657.935207] init: cpu:119 cpualloc = 666
[134657.935207] init: cpu:120 cpualloc = 666
[134657.935207] init: cpu:121 cpualloc = 666
[134657.935207] init: cpu:122 cpualloc = 666
[134657.935208] init: cpu:123 cpualloc = 666
[134657.935208] init: cpu:124 cpualloc = 666
[134657.935208] init: cpu:125 cpualloc = 666
[134657.935208] init: cpu:126 cpualloc = 666
[134657.935209] init: cpu:127 cpualloc = 666
参考
内核必须懂(五): per-CPU变量 - 简书 (jianshu.com)
Linux内核源码/内存调优/文件系统/进程管理/设备驱动/网络协议栈-学习视频教程-腾讯课堂 (qq.com)
以上是关于linux内核源码分析之per-CPU的主要内容,如果未能解决你的问题,请参考以下文章
Linux 内核 内存管理Linux 内核堆内存管理 ③ ( CPU 计数器瓶颈 | per-CPU 计数器 | Linux 内核 percpu_counter 结构体源码 )