linux之内核源码中for_each_possible_cpu/for_each_online_cpu/for_each_present_cpu

本文详细解析了Linux内核源码中for_each_online_cpu,for_each_possible_cpu和for_each_present_cpu的区别,以及per_cpu接口和per_cpu_ptr的作用,特别关注了如何在多CPU环境中处理worker_pool变量的副本。
摘要由CSDN通过智能技术生成

一、看内核源码时,有很多在访问per_cpu变量时,会有很多for_each_online_cpu ,下面介绍一下区别

假设一太机器上有8个CPU:

1.1 for_each_possible_cpu

        机器上最多有多少个CPU,包括本机的CPU,以及可以热插拔的CPU。
        1. 假设最多可以插CPU为10,本机CPU个数为8个,则最多可以再添加2个可插拔CPU。

1.2 for_each_present_cpu

        当前有多少个CPU。
        1. 本机CPU个数为8个,都是online的,则cpu_present_map为8;

        2. 再插入1个可插拔CPU,则cpu_present_map为9。

1.3 for_each_online_cpu

        在当前的CPU中,有多少个可用的CPU。
        1. 本机CPU个数为8个,都是online的,则for_each_online_cpu 为8;

        2. 将其中一个设置为offline,则for_each_online_cpu变为7

内核源码:include/linux/cpumask.h

#define for_each_possible_cpu(cpu) for_each_cpu((cpu), cpu_possible_mask)
#define for_each_online_cpu(cpu)   for_each_cpu((cpu), cpu_online_mask)
#define for_each_present_cpu(cpu)  for_each_cpu((cpu), cpu_present_mask)

 for_each_cpu

/**
 * for_each_cpu - iterate over every cpu in a mask
 * @cpu: the (optionally unsigned) integer iterator
 * @mask: the cpumask pointer
 *
 * After the loop, cpu is >= nr_cpu_ids.
 */
#define for_each_cpu(cpu, mask)                         \
        for ((cpu) = -1;                                \
                (cpu) = cpumask_next((cpu), (mask)),    \
                (cpu) < nr_cpu_ids;)

二、介绍per_cpu() 接口

 

for_each_possible_cpu(cpu) {
                for_each_cpu_worker_pool(pool, cpu) {
                        pool->node = cpu_to_node(cpu);
                }
        }

for_each_cpu_worker_pool(pool, cpu)

#define for_each_cpu_worker_pool(pool, cpu)                             \
        for ((pool) = &per_cpu(cpu_worker_pools, cpu)[0];               \
             (pool) < &per_cpu(cpu_worker_pools, cpu)[NR_STD_WORKER_POOLS]; \
             (pool)++)
 

per_cpu()

 #define per_cpu(var, cpu)       (*per_cpu_ptr(&(var), cpu))

 per_cpu_ptr

 

#define per_cpu_ptr(ptr, cpu)                                           \
({                                                                      \
        __verify_pcpu_ptr(ptr);                                         \
        SHIFT_PERCPU_PTR((ptr), per_cpu_offset((cpu)));                 \
})

 cpu_worker_pools 是定义的每cpu上工作者池组的变量名。

 

/* the per-cpu worker pools */
static DEFINE_PER_CPU_SHARED_ALIGNED(struct worker_pool [NR_STD_WORKER_POOLS], cpu_worker_pools);

从上面的代码看出, per_cpu(cpu_worker_pools, cpu),per_cpu 是获取指定的cpu per_cpu副本cpu_worker_pools变量的地址;(pool) = &per_cpu(cpu_worker_pools, cpu)[0],工作者池数组的第一个地址,再把地址付给pool 变量。

在解释深一层, cpu_worker_pools 这称之为源变量,DEFINE_PER_CPU_SHARED_ALIGNED 之后,为每个CPU声明一个源变量副本。在之后,通过per_cpu 获取每cpu 的变量副本,进行操作。

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值