当前位置: 首页 > 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.zqtcl.cn/news/4575/

相关文章:

  • 做网站用小型机或服务器网页设计图片的代码
  • 仁怀网站建设网站建设实训总结及体会
  • 如何替换网站wordpress主题ux themes
  • 7免费网站建站坪地网站建设价位
  • 企业网站模板专业网wordpress 管理插件
  • 大数据精准营销案例优化手机访问网站速度
  • 备案网站首页地址iis7网站建设
  • 柳州市建设中心网站十大正规平台
  • 个人网站赚钱wordpress ueditor
  • 有一个网站是做釆购的是什么网免费做手机网站建设
  • 广东网站备案 时间赤峰做网站哪家好
  • 新手如何做英文网站赚美元一个app下载免费下载安装
  • 深圳宝安做网站公司企业网站seo诊断
  • 外贸网站如何做seo云推荐 wordpress
  • 万州区建设局官方网站阿里巴巴网官网首页
  • 合肥网站建设哪个公司做得比较好红色网站建设
  • 亦庄网站建设价格河北石家庄天气
  • .net美食网站开发源代码软件设计师报考条件
  • 网站建设任务书怎么直接做免费网站吗
  • 河北网站建设seo优化盐城市亭湖区城乡建设网站
  • 网站搭建图片做简单网站用什么软件有哪些
  • 山西中宇建设集团网站湘潭做网站 搜搜磐石网络
  • 网站加载进度条表白网站制作代码
  • 域名对网站的好处dw制作网页入门
  • 网站原型的交互怎么做如何做网站小编
  • 建设银行衡阳市分行网站网站虚拟主机过期
  • 网站设置仅某浏览器为什么网站权重会掉
  • 容桂免费网站建设公司网站建设礻金手指下拉十一
  • 镇江做网站多少钱网站配色案例分析
  • 建设一个功能简单的网站用php做网站不用框架