同步与互斥_percpu变量
percpu变量的关键就是:要求根据CPU的个数,在内存中生成多份拷贝,并且能够根据变量名和CPU编号,正确的对各个CPU的变量进行寻址。
采用per-cpu变量有下列好处:所需数据很可能存在于处理器的缓存中,因此可以更快速地访问。如果在多处理器系统中多个CPU可能同时访问变量,会引发一些通信方面的问题,采用percpu变量恰好规避了这个问题。
这里读者只需要记住percpu变量每个CPU都有一个就行了,看完本篇文章后,再回来阅读前面加粗的话,相信会有更深刻的理解。
首先来看如何定义一个percpu变量:
DEFINE_PER_CPU(int, cpu_number); #define DEFINE_PER_CPU(type, name) \
__attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name
上面的代码定义了一个类型为int,名字为per_cpu_cpu_number的percpu变量。__typeof__(type)得到的就是int,而per_cpu__##name得到的就是per_cpu_cpu_number,并且通过__section__把这个变量放到名为.data.percpu的数据段。因此在编译时所有的percpu变量都会统一放到.data.percpu数据段,当内核启动后,会根据检测到的cpu个数从数据段.data.percpu为各个CPU单独复制一份。start_kernel函数调用setup_per_cpu_areas()来完成这个工作,setup_per_cpu_areas定义如下:
//__per_cpu_offset数组用来保存CPU对应 percpu段 相对ptr的偏移
unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; static void __init setup_per_cpu_areas(void)
{
unsigned long size, i;
char *ptr;
//取CPU的数量
unsigned long nr_possible_cpus = num_possible_cpus(); /* Copy section for each CPU (we discard the original) */
/* 计算每个CPU所需要的percpu段大小。
*
* @PERCPU_ENOUGH_ROOM:__per_cpu_end - __per_cpu_start + PERCPU_MODULE_RESERVE
* @ALIGN():使percpu段大小向上对齐
*/
size = ALIGN(PERCPU_ENOUGH_ROOM, PAGE_SIZE);
//分配内存
ptr = alloc_bootmem_pages(size * nr_possible_cpus); for_each_possible_cpu(i) {
/* __per_cpu_start对于每个CPU来讲是个定值,它和__per_cpu_end都是由链接器生成的
* 计算每个CPU的__per_cpu_start相对于真实存放percpu段线性地址 的偏移
* 请参考代码下方的示意图
* memcpy拷贝所有percpu变量至每个CPU自己的percpu段
*/
__per_cpu_offset[i] = ptr - __per_cpu_start;
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
ptr += size;
}
}

那么在编译期源程序如何访问percpu变量呢?内核定义了几个宏来实现对percpu变量的访问:
//smp_processor_id()可以返回当前活动处理器的ID,用作下面的cpu参数。
#define per_cpu(var, cpu) (*({ \
extern int simple_identifier_##var(void); \
RELOC_HIDE(&per_cpu__##var, __per_cpu_offset(cpu)); }))
这里我们举一个例子进行说明:假设访问per_cpu(var,1),由于percpu变量在定义时由DEFINE_PER_CPU展开成per_cpu_var,因此RELOC_HIDE的第一个参数就是编译时per_cpu_var的地址,第二个参数__per_cpu_offset(cpu)为前面setup_per_cpu_areas计算出来的,它表示运行时复制的percpu数据区首地址与编译期确定的首地址的差值,这两个值相加就是实际存储percpu变量的地址。示意图如下:

在更(geng)新的内核(2.6.32)中,percpu变量的定义(DEFINE_PER_CPU)和存取(per_cpu(var, cpu))方式没有发生改变,主要是__per_cpu_offset数组的初始化方式发生了改变,见arch\x86\kernel\setup_percpu.c中函数:setup_per_cpu_areas()。
同步与互斥_percpu变量的更多相关文章
- UNIX环境高级编程——线程同步之互斥锁、读写锁和条件变量(小结)
一.使用互斥锁 1.初始化互斥量 pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER;//静态初始化互斥量 int pthread_mutex_init( ...
- 【转载】同步和互斥的POSIX支持(互斥锁,条件变量,自旋锁)
上篇文章也蛮好,线程同步之条件变量与互斥锁的结合: http://www.cnblogs.com/charlesblc/p/6143397.html 现在有这篇文章: http://blog.cs ...
- 转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)
Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥) 介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可 ...
- Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)
介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可以看作是Unix进程的表亲,同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间, ...
- Linux驱动之同步、互斥、阻塞的应用
同步.互斥.阻塞的概念: 同步:在并发程序设计中,各进程对公共变量的访问必须加以制约,这种制约称为同步. 互斥机制:访问共享资源的代码区叫做临界区,这里的共享资源可能被多个线程需要,但这些共享资源又不 ...
- linux下的同步与互斥
linux下的同步与互斥 谈到linux的并发,必然涉及到线程之间的同步和互斥,linux主要为我们提供了几种实现线程间同步互斥的 机制,本文主要介绍互斥锁,条件变量和信号量.互斥锁和条件变量包含在p ...
- linux内核同步之每CPU变量、原子操作、内存屏障、自旋锁【转】
转自:http://blog.csdn.net/goodluckwhh/article/details/9005585 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 一每 ...
- 【Java并发基础】并发编程领域的三个问题:分工、同步和互斥
前言 可以将Java并发编程抽象为三个核心问题:分工.同步和互斥. 这三个问题的产生源自对性能的需求.最初时,为提高计算机的效率,当IO在等待时不让CPU空闲,于是就出现了分时操作系统也就出现了并发. ...
- 线程同步 - POSIX互斥锁
线程同步 - POSIX互斥锁 概括 本文讲解POSIX中互斥量的基本用法,从而能达到简单的线程同步.互斥量是一种特殊的变量,它有两种状态:锁定以及解锁.如果互斥量是锁定的,就有一个特定的线程持有或者 ...
随机推荐
- 林大妈的JavaScript进阶知识(三):HTML5 History API
HTML5中新增了History API,它用于管理浏览器路由跳转的一个url栈.History是window对象的一部分,它也是一个对象,因此称它是BOM(类似DOM,Browser Object ...
- C++ STL vector的学习
vector就是一个不定长数组,vector是动态数组,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素,使用vector之前,必须包含相应的头文件和命名空间. #include <vec ...
- 【Redis】哨兵机制
一.概述 什么是哨兵机制 二.环境配置 2.1 虚拟机 2.2 安装Redis 2.3 配置主从复制 2.4 配置哨兵 2.5 测试 2.6 疑惑(待解决) 一.概述 什么是哨兵机制 Redis的哨兵 ...
- (一)分布式数据库tidb-简介
因为数据磁盘问题,最近进行了更换库,所以决定写关于这方面的专题的博客,博客信息参考的官方文档. 一.分布式数据库使用背景 随着互联网的飞速发展,业务量可能在短短的时间内爆发式地增长,对应的数据量可能快 ...
- springcloud超简单的入门2--Eureka服务治理
Eureka服务治理 下面请听第一个话题,母...咳咳,拿错书了. Eureka简介 eureka是什么呢? 简单来说呢,当我的微服务应用多了起来,一个一个写死再程序里是件很不优雅的事情,而且同一服务 ...
- Java测试(二)
一.选择题(每题2分,共40分) 1.下面哪个是Java语言中正确的标识符(C ) a) 3com b)import c)that d)this 2.下面哪个语句 ...
- jar包部署到window系统服务器的办法
1:把jar包和lib(如果打包出现有lib目录)放在同级目录 2:windows服务器安装jdk等 3:通过bat批处理命令或者 cmd命令启动jar包,其中之一就可以 3.1:bat命令如下: @ ...
- 漫谈Java中的OOPS
什么是OOPS? 面向对象编程是一种编程概念,其工作原理是对象是程序中最重要的部分.它允许用户创建他们想要的对象,然后创建处理这些对象的方法.操作这些对象以获得结果是面向对象编程的目标. 面向对象编程 ...
- ASP.NET Core 2.2 : 二十二. 多样性的配置方式
大多数应用都离不开配置,本章将介绍ASP.NET Core中常见的几种配置方式及系统内部实现的机制. 说到配置,第一印象可能就是“.config”类型的xml文件或者“.ini”类型的ini文件,在A ...
- Nginx正确配置Location
文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号. 之前已经讲过Nginx的基本配置,本篇文章主要对Nginx中Location指令的作用进行介绍.本篇文章主要对 ...