Chinaunix首页 | 论坛 | 博客
  • 博客访问: 409050
  • 博文数量: 70
  • 博客积分: 87
  • 博客等级: 民兵
  • 技术积分: 446
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-10 22:18
文章分类

全部博文(70)

文章存档

2020年(3)

2018年(1)

2017年(4)

2016年(1)

2015年(3)

2014年(11)

2013年(22)

2012年(25)

我的朋友

分类:

2012-08-30 13:53:42

原文地址:kernel中的per_cpu变量 作者:zhangliangfnst

per-cpu 变量的引入有效的解决了SMP系统中处理器对锁得竞争,每个cpu只需访问自己的本地变量。本文阐述了per-cpu变量在2.6内核上的实现和相关操作。
在系统编译阶段我们就手工的定义了一份所有的per-cpu变量,这些变量的定义是通过宏DEFINE_PER_CPU实现的:
  1. 11 #define DEFINE_PER_CPU(type, name) \
  2.   12 __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name

从上面的代码我们可以看出,手工定义的所有per-cpu变量都是放在.data.percpu段的。注意上面的宏只是在SMP体系结构下才如此定义。如果不是SMP结构的计算机那么只是简单的把所有的per-cpu变量放到全局变量应该放到的地方。

单CPU的per-cpu变量定义:

  1. 27 #else /* ! SMP */
  2.   28
  3.   29 #define DEFINE_PER_CPU(type, name) \
  4.   30 __typeof__(type) per_cpu__##name

在了解了上述代码后,我们还必须弄清楚一点:单CPU的计算机中使用的per-cpu变量就是通过上述宏定义的放在全局数据区的per-cpu变量。而在SMP体系结构中,我们使用却不是放在.data.percpu段的变量,设想一下如果使用这个变量,那么应该哪个CPU使用呢?事实上,SMP下,每个cpu使用的都是在.data.percpu段中的这些per-cpu变量的副本,有几个cpu就创建几个这样的副本。

在系统初始化期间,start_kernel()函数中调用setup_per_cpu_areas()函数,用于为每个cpu的per-cpu变量副本分配空间,注意这时alloc内存分配器还没建立起来,该函数调用alloc_bootmem函数为初始化期间的这些变量副本分配物理空间。

  1. 332 static void __init setup_per_cpu_areas(void)
  2.      /* */
  3.  333 {
  4.  334 unsigned long size, i;
  5.  335 char *ptr;
  6.  336
  7.  337 /* Copy section for each CPU (we discard the original) */
  8.  338 size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
  9.  339 #ifdef CONFIG_MODULES
  10.  340 if (size < PERCPU_ENOUGH_ROOM)
  11.  341 size = PERCPU_ENOUGH_ROOM;
  12.  342 #endif
  13.  343
  14.  344 ptr = alloc_bootmem(size * NR_CPUS);
  15.  345
  16.  346 for (i = 0; i < NR_CPUS; i++, ptr += size) {
  17.  347 __per_cpu_offset[i] = ptr - __per_cpu_start;
  18.  348 memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
  19.  349 }
  20.  350 }
  21.  351 #endif /* !__GENERIC_PER_CPU */

上述函数,在分配好每个cpu的per-cpu变量副本所占用的物理空间的同时,也对__per_cpu_offset[NR_CPUS]数组进行了初始化用于以后找到指定CPU的这些per-cpu变量副本。

 

  1. 15 #define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
  2.   16 #define __get_cpu_var(var) per_cpu(var, smp_processor_id())
这两个宏一个用于获得指定cpu的per-cpu变量,另一个用于获的本地cpu的per-cpu变量,可以自己分析一下。
阅读(1631) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~