zoukankan      html  css  js  c++  java
  • per cpu variable

    per cpu variable

    per cpu变量可以export出来给其它模块使用

    方法:

    1.define per cpu variable

    DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}}; EXPORT_PER_CPU_SYMBOL(vm_event_states);

    2.declare per cpu variable

    在你需要使用这个per cpu变量的模块里declare它后即可在这个模块里使用它了

    DECLARE_PER_CPU(struct vm_event_state, vm_event_states);

    对struct类型per cpu变量里的field进行per cpu操作

    4.19/mm/vmstat.c

    #ifdef CONFIG_VM_EVENT_COUNTERS
    DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}};
    EXPORT_PER_CPU_SYMBOL(vm_event_states);

    include/linux/vmstat.h

    struct vm_event_state {
        unsigned long event[NR_VM_EVENT_ITEMS];
    };
    
    DECLARE_PER_CPU(struct vm_event_state, vm_event_states);
    
    /*
     * vm counters are allowed to be racy. Use raw_cpu_ops to avoid the
     * local_irq_disable overhead.
     */
    static inline void __count_vm_event(enum vm_event_item item)
    {
        raw_cpu_inc(vm_event_states.event[item]);
    }
    
    static inline void count_vm_event(enum vm_event_item item)
    {
        this_cpu_inc(vm_event_states.event[item]);
    }
    
    static inline void __count_vm_events(enum vm_event_item item, long delta)
    {
        raw_cpu_add(vm_event_states.event[item], delta);
    }
    
    static inline void count_vm_events(enum vm_event_item item, long delta)
    {
        this_cpu_add(vm_event_states.event[item], delta);
    }
    以上面raw_cpu_inc()为例,它是基于vm_event_states.event[item]的地址加上__my_cpu_offset得到(this cpu)的地址,然后将这个地址上的数据(unsigned long型)加1。
    所以可以看到per cpu变量是vm_event_states,这个per cpu变量是struct类型的,但是还是可以对这个struct里的field进行per cpu操作:
    #ifndef arch_raw_cpu_ptr
    #define arch_raw_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, __my_cpu_offset)
    #endif

    per cpu变量地址

    per_cpu_ptr(ptr, cpu)

    这个macro是根据定义的per cpu变量的地址加上指定cpu的offset,这个相加结果再转化为ptr的类型就是这个macro的结果。

    比如我要访问per cpu变量,可以采用下面的方式进行,kernel_cpustat是struct kernel_cpustat类型per cpu变量:

        struct kernel_cpustat *data;
    
        for(; i < 4; i++)
        {
            data = per_cpu_ptr(&kernel_cpustat, i);
            pr_emerg("cpu%d kernel_cpustat addr is %#px.\n", i, data);
        }

    如果per cpu变量本身就是指针类型,则可以使用如下方式进行,cpufreq_update_util_data是struct update_util_data *指针类型per cpu变量:

        struct update_util_data *data;
    
        data = rcu_dereference_sched(*per_cpu_ptr(&cpufreq_update_util_data,
                              cpu_of(rq)));

    定义的per cpu变量地址是在.data或者bss段的,和普通的全局变量一样,但是通过上述方式获取的per cpu变量地址却不是在data、bss段了,如下kernel_cpustat per cpu变量本身的地址是0xffffff80097cf8c8,应该是位于bss段,但是每个cpu变量的地址是在线性影射区,可以看到实际per cpu变量的地址等于定义的per cpu变量地址加上对应的offset:

    [ 6628.336247] cpu0 kernel_cpustat addr is 0xffffffc0579648c8.
    [ 6628.336264] cpu1 kernel_cpustat addr is 0xffffffc05797b8c8.
    [ 6628.336278] cpu2 kernel_cpustat addr is 0xffffffc0579928c8.
    [ 6628.336291] cpu3 kernel_cpustat addr is 0xffffffc0579a98c8.
    [ 6628.336305] per cpu var addr is 0xffffff80097cf8c8.
    [ 6628.336318] __per_cpu_offset[0]: 0x404e195000.
    [ 6628.336331] __per_cpu_offset[1]: 0x404e1ac000.
    [ 6628.336344] __per_cpu_offset[2]: 0x404e1c3000.
    [ 6628.336358] __per_cpu_offset[3]: 0x404e1da000.
  • 相关阅读:
    调试脚本
    if [ $? -eq 0 ]的含义
    主键和索引的区别
    Docker守护式容器
    Docker容器的基本操作
    Linux下Docker的安装
    Linux下查看占用CPU资源最多的几个进程
    报错:pymysql.err.InternalError: (1054, "Unknown column 'AType' in 'field list'")
    在webpack中使用postcss-px2rem的
    vue环境配置脚手架环境搭建vue工程目录
  • 原文地址:https://www.cnblogs.com/aspirs/p/15714732.html
Copyright © 2011-2022 走看看