当前位置: 首页 > news >正文

网站不备案 能打开吗深圳网站定制开发

网站不备案 能打开吗,深圳网站定制开发,seo网络推广哪家专业,wordpress在php下安装教程视频Linux 2.6 kernel 中的 percpu 变量是经常用到的东西#xff0c;因为现在很多计算机都已经支持多处理器了#xff0c;而且 kernel 默认都会被编译成 SMP 的#xff0c;相对于原来多个处理器共享数据并进行处理的方式#xff0c;用 percpu 变量在 SMP、NUMA 等架构下可以提高…Linux 2.6 kernel 中的 percpu 变量是经常用到的东西因为现在很多计算机都已经支持多处理器了而且 kernel 默认都会被编译成 SMP 的相对于原来多个处理器共享数据并进行处理的方式用 percpu 变量在 SMP、NUMA 等架构下可以提高性能而且很多情况下必须用 percpu 来对不同的处理器做出数据区分。本文以 kernel 中的 softirq 为例简单说下 percpu 变量我们先来看看 kernel 中唤醒 ksoftirqd 的实现ksoftirqd 在 ps 命令看到的进程列表中很容易找到是每个处理器都有一个(如果有 4 个处理器则有 4 个 kernel 线程名称分别从 ksoftirqd/0 到 ksoftirqd/3)关于 softirq 本身的实现不在本文讨论范围内唤醒 ksoftirqd 的实现在 kernel/softirq.c 文件中static DEFINE_PER_CPU(struct task_struct *, ksoftirqd);void wakeup_softirqd(void){/* Interrupts are disabled: no need to stop preemption */struct task_struct *tsk __get_cpu_var(ksoftirqd);if (tsk tsk-state ! TASK_RUNNING)wake_up_process(tsk);}这里就用到了 percpu 变量 ksoftirqd它是通过 DEFINE_PER_CPU 宏来进程定义的 percpu task_struct 列表通过 __get_cpu_var 宏来得到相应处理器的 ksoftirqd/n 的 task_struct然后调用 wake_up_process 函数唤醒进程(也就是 ksoftirqd/n kernel 线程)关于 wake_up_process 等进程调度的相关实现在之前的日志中有介绍的请参考 [这里]。__get_cpu_var、DEFINE_PER_CPU 等 percpu 宏的实现在 include/linux/percpu.h、include/asm-generic/percpu.h 等头文件中。先看看 include/asm-generic/percpu.h 中的一些定义#ifdef CONFIG_SMP/** per_cpu_offset() is the offset that has to be added to a* percpu variable to get to the instance for a certain processor.** Most arches use the __per_cpu_offset array for those offsets but* some arches have their own ways of determining the offset (x86_64, s390).*/#ifndef __per_cpu_offsetextern unsigned long __per_cpu_offset[NR_CPUS];#define per_cpu_offset(x) (__per_cpu_offset[x])#endif/** Determine the offset for the currently active processor.* An arch may define __my_cpu_offset to provide a more effective* means of obtaining the offset to the per cpu variables of the* current processor.*/#ifndef __my_cpu_offset#define __my_cpu_offset per_cpu_offset(raw_smp_processor_id())#endif#ifdef CONFIG_DEBUG_PREEMPT#define my_cpu_offset per_cpu_offset(smp_processor_id())#else#define my_cpu_offset __my_cpu_offset#endif/** Add a offset to a pointer but keep the pointer as is.** Only S390 provides its own means of moving the pointer.*/#ifndef SHIFT_PERCPU_PTR/* Weird cast keeps both GCC and sparse happy. */#define SHIFT_PERCPU_PTR(__p, __offset)({\__verify_pcpu_ptr((__p));\RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset)); \})#endif/** A percpu variable may point to a discarded regions. The following are* established ways to produce a usable pointer from the percpu variable* offset.*/#define per_cpu(var, cpu) \(*SHIFT_PERCPU_PTR((var), per_cpu_offset(cpu)))#define __get_cpu_var(var) \(*SHIFT_PERCPU_PTR((var), my_cpu_offset))#define __raw_get_cpu_var(var) \(*SHIFT_PERCPU_PTR((var), __my_cpu_offset))#define this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, my_cpu_offset)#define __this_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, __my_cpu_offset)#ifdef CONFIG_HAVE_SETUP_PER_CPU_AREAextern void setup_per_cpu_areas(void);#endif#else /* ! SMP */#define per_cpu(var, cpu)(*((void)(cpu), (var)))#define __get_cpu_var(var)(var)#define __raw_get_cpu_var(var)(var)#define this_cpu_ptr(ptr) per_cpu_ptr(ptr, 0)#define __this_cpu_ptr(ptr) this_cpu_ptr(ptr)#endif/* SMP */#ifndef PER_CPU_BASE_SECTION#ifdef CONFIG_SMP#define PER_CPU_BASE_SECTION .data.percpu#else#define PER_CPU_BASE_SECTION .data#endif#endif#ifdef CONFIG_SMP#ifdef MODULE#define PER_CPU_SHARED_ALIGNED_SECTION #define PER_CPU_ALIGNED_SECTION #else#define PER_CPU_SHARED_ALIGNED_SECTION .shared_aligned#define PER_CPU_ALIGNED_SECTION .shared_aligned#endif#define PER_CPU_FIRST_SECTION .first#else#define PER_CPU_SHARED_ALIGNED_SECTION #define PER_CPU_ALIGNED_SECTION .shared_aligned#define PER_CPU_FIRST_SECTION #endif通常所有的 percpu 变量是一起存放在特定的 section 里的像上面头文件中的 .data.percpu 基础 section( 当然非 SMP 系统下就是 .data 了)、.shared_aligned、.first section。使用 objdump 可以看到编译 kernel 时的 vmlinux 文件的 section(结果没有完全显示)objdump -h vmlinuxvmlinux: file format elf64-x86-640 .text 0037a127 ffffffff81000000 0000000001000000 00200000 2**12CONTENTS, ALLOC, LOAD, READONLY, CODE3 .rodata 0013c8ec ffffffff8137f000 000000000137f000 0057f000 2**6CONTENTS, ALLOC, LOAD, READONLY, DATA11 .data 0004d920 ffffffff814ec000 00000000014ec000 006ec000 2**12CONTENTS, ALLOC, LOAD, DATA19 .data.percpu 00012880 0000000000000000 000000000153b000 00a00000 2**12CONTENTS, ALLOC, LOAD, DATA可以看到 vmlinux 文件中的 .data 和 .data.percpu section。percpu 变量的地址实际上就是其在上面说到的 section 里的偏移量这个偏移量还要加上特定处理器的偏移量(也就是上面头文件中的 per_cpu_offset、my_cpu_offset 等)得到最终的变量地址并最终以指针引用的方式得到值这样访问的效果就有点类似于访问全局变量了。percpu 变量通常用于更新非常频繁而访问机会又相对比较少的场合这样的处理方式可以避免多处理器环境下的频繁加锁等操作。从上面的注释也可以看到 per_cpu_offset 是在一个 percpu 变量上增加的偏移量大多数系统架构下使用 __per_cpu_offset 数组来作为偏移量而 x86_64 等架构下处理方式则不同。my_cpu_offset 是在调用 per_cpu_offset 时使用 smp_processor_id() 得到当前处理器 ID 作为参数__my_cpu_offset 则是用 raw_smp_processor_id() 的值作为 per_cpu_offset 的参数(smp_processor_id() 在抢占被关闭时是安全的)。SHIFT_PERCPU_PTR 宏用于给指针增加偏移量它使用的 RELOC_HIDE 宏在不同的编译器下实现不同在 include/linux/compiler.h 头文件中看看 gcc 编译下的处理#define RELOC_HIDE(ptr, off)\({ unsigned long __ptr;\__asm__ ( : r(__ptr) : 0(ptr));\(typeof(ptr)) (__ptr (off)); })可以看到 gcc 中使用内嵌汇编先将 ptr 值赋给 __ptr(unsigned long 类型)然后在 __ptr 基础上增加偏移量这样可以避免编译报错ptr 值不变而且最终以 ptr 指定的类型来返回。include/asm-generic/percpu.h 头文件中定义了 per_cpu、__get_cpu_var、__raw_get_cpu_var、this_cpu_ptr、__this_cpu_ptr 等几个常用的宏。per_cpu 就用于得到某个指定处理器的变量__get_cpu_var 用于得到当前处理器的 percpu 变量值。再来看看 DEFINE_PER_CPU 的实现它在 include/linux/percpu-defs.h 头文件中#define __PCPU_ATTRS(sec)\__percpu __attribute__((section(PER_CPU_BASE_SECTION sec)))\PER_CPU_ATTRIBUTES#define DEFINE_PER_CPU_SECTION(type, name, sec)\__PCPU_ATTRS(sec) PER_CPU_DEF_ATTRIBUTES\__typeof__(type) name#define DEFINE_PER_CPU(type, name)\DEFINE_PER_CPU_SECTION(type, name, )使用 DEFINE_PER_CPU 宏可以静态的定义 percpu 变量。__PCPU_ATTRS 指定输入的 section 类型DEFINE_PER_CPU_SECTION 用于在特定的 section 上定义特定类型的变量。__typeof__ 和 上面见到的 typeof 是一样的都用于获取 type 的数据类型。__attribute__((section(xxx))) 表示把定义的变量存储在指定的 section 上。DEFINE_PER_CPU 就用于定义在 PER_CPU_BASE_SECTION section 上(从最开始的代码中也可以看出非 SMP 时用 .data 段SMP 时用 .data.percpu 段)。然后是 get_cpu_var 宏的实现它在 include/linux/percpu.h 头文件中/** Must be an lvalue. Since var must be a simple identifier,* we force a syntax error here if it isnt.*/#define get_cpu_var(var) (*({\preempt_disable();\__get_cpu_var(var); }))/** The weird is necessary because sparse considers (void)(var) to be* a direct dereference of percpu variable (var).*/#define put_cpu_var(var) do {\(void)(var);\preempt_enable();\} while (0)#define alloc_percpu(type)\(typeof(type) __percpu *)__alloc_percpu(sizeof(type), __alignof__(type))get_cpu_var 会先禁止抢占然后调用 __get_cpu_var 得到 percpu 变量值。put_cpu_var 则重新启用抢占。另外在 include/linux/percpu.h 等文件中还定义了 alloc_percpu 和 free_percpu 宏来动态定义和释放 percpu 变量他们都是通过 percpu memory allocator 来实现的在 mm/percpu.c 中动态分配的 percpu 变量可以通过 per_cpu_ptr 宏来得到为此 kernel 还引入了 this_cpu_ptr、this_cpu_read 等一系列相关机制用寄存器替代内存提高对 percpu 变量的访问速度关于 percpu memory allocator 等信息以后再来详细分析了。以上为个人分析结果有任何问题欢迎指正咯 ^_^
http://www.pierceye.com/news/4575/

相关文章:

  • 西宁建设公司网站网站建设好如何开通
  • 工业电商做网站怎么样微信官网网站
  • .net 网站开发项目结构做网站怎么实现鼠标经过图像
  • 室内设计师经常用的网站qq网页版在线登录入口
  • 做网站制作网站管理登录
  • 如何介绍设计的网站模板哈尔滨网站建设流程
  • 中国建设银行青岛分行网站WordPress上传图片提示无效
  • 温州哪里可以做企业网站wordpress媒体库素材打不开
  • 做企业网站需要自己有公司吗wordpress 双会员系统
  • 宁夏建设厅招标网站seo网站推广全程实例
  • 网站备案查询网址正规电商培训学校排名
  • 苏州小程序开发公司长春做网站优化哪家好
  • 沈阳网站制作网页天元建设集团有限公司本科生待遇
  • 山西电商网站开发最新型建筑模板有哪些
  • 安徽网站建设外贸新浪网网站的建设费用预算
  • 用百度云做网站微信小程序开发难吗
  • 网站制作和网页制作是不是一样专门做外贸的的网站有哪些
  • 企业网站建设方案应该怎么做网站关键词多少个好
  • 手机网站设计需要学什么牛商网网站建设
  • 宝安网站建设阿里指数查询官网入口
  • 做爰网站下载地址百度导航下载安装手机导航
  • 设计师服务平台网站西安网吧
  • 上海网站策划网站根目录文件 seo
  • 基本信息型网站有哪些flask做网站工具
  • 国内做彩票网站违法么国家示范校建设专题网站
  • 青岛 html5flash设计开发|交互设计|网站建设建成网
  • 如何免费建立官方网站平面设计上班都干啥
  • 网站设计制作从哪里学起网页制作软件
  • 编辑网站用什么软件游戏开发小说
  • 蚌埠网站建设公司seo网络优化