Linux CPU初始化流程+CPU状态监控和设置+进程绑核+进程独占+中断绑核

时间:2024-06-01 10:03:00

一.启动流程

Linux下CPU有4个状态:possible,present,online和active,分别对应__cpu_possible_mask,set_cpu_present,__cpu_online_mask和__cpu_active_mask 4个掩码

这4个状态的意义可以查看:https://blog.****.net/liuhangtiant/article/details/84933156

需要补充的是online状态和active的区别;某个核(这里的核指的是逻辑核,如果支持超线,比如8核16线程,此时就有16个逻辑核)在online状态下,只能说明这个核可以跑内核线程,但是不能不能跑用户线程,也就是说,此时SMP不会把用户线程调度到这个核上,通过taskset等绑核操作会报参数错误:

Linux CPU初始化流程+CPU状态监控和设置+进程绑核+进程独占+中断绑核

taskset实际上会调用sched_setaffinity函数,taskset会把要绑定的核序号转换成mask,而真正绑定前,sched_setaffinity会检查这个mask是否是__cpu_active_mask4的子集,不是就返回-EINVAL,最终导致上图错误

在online的基础上,如果核也处于active状态,此时SMP是可调度的,同时也可绑核。

二.进程绑核

1.绑核

可在命令行中通过taskset绑定,也可以在程序中通过sched_setaffinity函数绑定;通过这种方式将某个进程绑定到某些核后,其实是限定了SMP对这几个进程的调度范围;单纯绑核而言,可以减少SMP对线程的核间移植,通常可以显著提升单线程性能,但是绑核通常是为了从宏观上对平台做算力均衡;但是其他进程也能用这些核。

2.查看进程当前可以在哪些核上运行

taskset -p <pid>命令会返回该进程的cpus_allowed数值,是一个掩码

三.进程独占

进程独占是在进程绑定基础上不让SMP把其他进程调度到这些独占的核上,另外也不让中断打扰这些核;主要分为三个步骤,可以参考:https://blog.****.net/weixin_30439067/article/details/95622518

四.CPU状态监控

1.sys接口

在/sys目录下,eg.  tree /sys/bus/cpu/devices cpu0,可以看到比较详细的cpu信息

Linux CPU初始化流程+CPU状态监控和设置+进程绑核+进程独占+中断绑核

2.top命令

top主要是实时查看cpu负载和进程情况,top后按“1”,可以看到各个逻辑核占用情况,绑核和可以通过这种方式看效果:

Linux CPU初始化流程+CPU状态监控和设置+进程绑核+进程独占+中断绑核

3.ps命令

ps -ef可以查看父进程

4.cat /proc/cpuinfo

processor是逻辑核编号,core id是物理核编号

Linux CPU初始化流程+CPU状态监控和设置+进程绑核+进程独占+中断绑核

5.设备树

这是根文件系统下的设备树木描述文件,和真实设备树文件以及SOC 架构是对应的,可以看到有三个CPU集群,每个集群有两个物理核;这个信息主要是反映当前系统用到的物理核,实际上可能更多,比如下图只用到6个核,但实际有8个核

Linux CPU初始化流程+CPU状态监控和设置+进程绑核+进程独占+中断绑核

6.lscpu

主要显示CPU的固有信息,关键字段

Thread(s) per core:  2                     :支持超线程,每个核对应两个逻辑核

Byte Order:          Little Endian        :小端模式

CPU op-mode(s):      32-bit, 64-bit  :支持32位和64位

On-line CPU(s) list: 0-15                  :对应cpu_online_mask,说明16个逻辑核都是online状态

Linux CPU初始化流程+CPU状态监控和设置+进程绑核+进程独占+中断绑核

 

五.CPU状态配置

1.通过sys接口进行online状态使能

eg.  sudo echo "0" > /sys/bus/cpu/devices/cpu0/online ,这条命令让cpu0退出online状态;

默认都开启:

Linux CPU初始化流程+CPU状态监控和设置+进程绑核+进程独占+中断绑核

执行这条命令后:

Linux CPU初始化流程+CPU状态监控和设置+进程绑核+进程独占+中断绑核

2.设置内核启动参数

(1)CPU隔离

上文配置“进程独占”中,/ boot/grub/grub.conf的kernel列最末尾加上isolcpus=x,y,… (代表将CPUx CPUy隔离),这样,init进程及后续进程的cpus_allowed就不包含这些隔离的CPU了,但是这些CPU仍然是active状态,也就是可以绑核,只是默认不用

(2)中断隔离

被隔离的CPU虽然没有线程run在上面,但是仍会收到interrupt.

Interrupt request是硬件级别的服务请求.详情见附录,此处不表.我们需要知道的是IRQ有一个亲和度属性smp_affinity. smp_affinity决定允许哪些CPU核心处理IRQ.

在redhat(其它发行版未知)中,某一特定IRQ的亲和度值储存在/proc/irq/IRP_NUMBER/smp_affinity文件中.此文件仅ROOT用户可见.储存的值是一个十六进制位掩码(hexadecimal bit-mask),代表着系统的所有CPU核心.

命令cat /proc/interrupts可以看到所有设备的interrupts信息,第一列即为IRP_NUMBER.

命令cat /proc/irq/32/smp_affinity可以看到IRQ号为32的亲和度.默认值为f,代表这个IRP能被所有CPU接受处理.

命令echo 1 >/proc/irq/32/smp_affinity把IRQ号为32的亲和度值设为1,代表这个IRP仅能被CPU0接受处理

照此,我们可以据要求任意绑定IRQ到CPU

虽然我们已经做了很大努力,但是仍有一部分中断没有被绑定,例如: Single function call interrupts, Local timer interrupts等等

3.配置内核

比如在menuconfig中配置后从新编译内核