Linux smp_setup_processor_id

阅读数:263 评论数:0

跳转到新版页面

分类

Linux

正文

一、概述

在Linux内核中,smp_setup_processor_id 函数是在系统引导期间,特别是在多处理器系统中用于设置当前处理器ID的函数。这个函数在早期的系统初始化代码中调用,其目的是确定当前运行的CPU,并设置全局变量 smp_processor_id,该变量在内核的其他部分用来识别当前的处理器。

简单来说,smp_setup_processor_id 的作用包括:

  • 确定当前CPU的ID。
  • 初始化与该CPU相关的数据结构。
  • 在多处理器系统中,可能还会检测其他处理器的存在和状态。

这个函数对于系统的多处理器支持(SMP,Symmetric MultiProcessing)是非常关键的。在启动过程中,内核需要知道哪个CPU正在执行代码,以便正确地初始化系统和管理不同的处理器。

在现代Linux内核中,这个函数的实现和具体作用可能随着架构(如x86、ARM等)和内核版本的不同而有所变化。它通常是架构特定代码的一部分,因为不同的处理器架构在启动和初始化处理器时有不同的要求和机制。

在内核启动的早期阶段,smp_setup_processor_id 通常是在架构特定的启动代码中调用的,这发生在执行架构无关初始化代码之前。这样做是为了确保当内核开始执行更高级别的初始化代码时,它已经知道了当前处理器的身份。

由于这部分代码是针对系统引导和低级处理器管理的,一般开发者在编写普通的内核模块或驱动时不会直接与之交互。这些细节通常由内核的底层架构代码处理,而不需要普通开发者关心

二、源码相关

smp模型指的是对称多处理模型(Symmetric Multi-Processor),与它对应的是NUMA非一致性存储访问结果(Non-Uniform Memory Access)MPP海量并行处理结构(Massive Parallel Processing)。它们的区别分别在于,SMP指的是多个CPU之间是平等关系,共享全部总线,内存和IO等。但是这个结构扩展性不好,往往CPU数量多了之后,很容易遇到抢占资源的问题。NUMA结构则是把CPU分模块,每个模块具有独立的内存,IO插槽等。各个模块之间通过互联模块进行数据交互。但是这样,就表示了有的内存数据在这个CPU模块中,那么处理这个数据当然最好是选择当前的CPU模块,这样每个CPU实际上地位就不一致了。所以叫做非一致性的存储访问结构。而MPP呢,则是由多个SMP服务器通过互联网连接起来,支持SMP模型的CPU有AMD/AMD64,而支持NUMA的的X86,而smp_setup_process_id在普通情况下是空实现,在不同的体系,比如arc/arm/kernel/setup.c就有对应的逻辑。

//.../arch/arm/kernel/setup.c
void __init smp_setup_processor_id(void)
{
int i;
//判断是否是smp系统,如果是则从arm协处理器读取当前cpuid,否则为0
u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0;
//根据level确定cpu号,即cpu=(mpidr>>0)&0xff
u32 cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);

//设置cpu的map数组
//#define cpu_logical_map(cpu) __cpu_logical_map[cpu]
cpu_logical_map(0) = cpu;
//nr_cpu_ids表示系统中cpu总数
for (i = 1; i < nr_cpu_ids; ++i)
cpu_logical_map(i) = i == cpu ? 0 : i;

set_my_cpu_offset(0);

pr_info("Booting Linux on physical CPU 0x%x\n", mpidr);
}


//检测是否为SMP架构
static inline bool is_smp(void)
{
#ifndef CONFIG_SMP
return false;
//CONFIG_SMP_ON_UP表示可以支援SMP Kernel运行在UniProcessor(單核心)的处理器上
#elif defined(CONFIG_SMP_ON_UP)
extern unsigned int smp_on_up;
return !!smp_on_up;
#else
return true;
#endif
}

//arch/arm/include/asm/cputype.h
static inline unsigned int __attribute_const__ read_cpuid_mpidr(void)
{
//从arm协处理器CP15的c0中读取当前cpu id
return read_cpuid(CPUID_MPIDR);
}

#define CPUID_MPIDR 5
#define read_cpuid(reg) \
({ \
unsigned int __val; \
asm("mrc p15, 0, %0, c0, c0, " __stringify(reg) \
: "=r" (__val) \
: \
: "cc"); \
__val; \
})

#define MPIDR_AFFINITY_LEVEL(mpidr, level) \
((mpidr >> (MPIDR_LEVEL_BITS * level)) & MPIDR_LEVEL_MASK)

static inline void set_my_cpu_offset(unsigned long off)
{
//Set TPIDRPRW
asm volatile("mcr p15, 0, %0, c13, c0, 4" : : "r" (off) : "memory");
}



相关推荐

一、概述 1、为什么Linus不使用GPLv3 在 PC 上,只要你得到了某个程序的源代码,就可以自行编译生成二进制程序,然后替换掉原有的二进制程序,你的程序自由很容易得到保证。然而 iPod、iPh

说明:这种方式只是用于方便阅读代码,因为可以在源代间快速索引跳跃。但是最后可能会有一些warning,可以不必关心,如果是强迫症,可以使用下面这种方式来去掉。

一、概述 在Linux系统中,/usr/bin和/usr/local/bin是两个常见的目录,用于存放可执行文件(二进制文件)。 很多应用都安装在/usr/local下面,先看一下automake工具

  一、概述 vmstat命令是最常见的Linux/Unix监控工具,可以监控给定时间间隔服务器的CPU使用率、内存使用、IO情况。相比top命令,可以查看到整个机器的CPU、内存、IO的使用情况,而

一、概述 sar,System Activity Reporter。是目前 Linux 上最为全面的系统性能分析工具之一,可以从多方面对系统的活动进行报告,包括:文件的读写情况、系统调用的使用情况、磁

一、简介 简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。 二、使用方法 1、基本语法  awk '条件类型1 {动作1} 条件类型2{动作2} ...

一、概述 列出目标目录中所有的子目录和文件。 二、 语法 ls [选项] [目录名] -a, –all 列出目录下的所有文件,包括以 . 开头的隐含文件 -A 同-a,但不列出“.”(表示当前目录)

一、概述 cd全称是change directory,用于切换当前工作目录。 注意的是,cd命令是一个内建命令,它是由 shell 提供的。因此,不同的 shell 可能会有一些差异,但基本的用法和功

一、概述 全称为print working directory,查看”当前工作目录“的完整路径,一般情况下不带任何参数 二、语法 pwd [选项] -L 即logical,逻辑路径 -P 即

一、概述 通过 mkdir 命令可以实现在指定位置创建以 DirName(指定的文件名)命名的文件夹或目录。要创建文件夹或目录的用户必须对所创建的文件夹的父文件夹具有写权限。并且,所创建的文件夹(目录