Linux 内核中关于 CPU 编号和拓扑管理

news/2025/2/23 2:01:36

CPU 拓扑结构定义

// topology.h
struct cpu_topology {
    int thread_id;    // SMT ID
    int core_id;      // 核心 ID
    int package_id;   // 物理 CPU ID
    int die_id;       // Die ID
    cpumask_t thread_sibling; // SMT 线程掩码
    cpumask_t core_sibling;   // 核心掩码
};

CPU 在线/离线管理

//cpu.c
/* CPU 热插拔核心函数 */
int cpu_up(unsigned int cpu)
{
    int err = 0;
    struct device *dev;
    struct device *parent;

    if (!cpu_possible(cpu)) {
        pr_err("can't online cpu %d because it is not configured as may-hotadd at boot time\n",
               cpu);
        return -EINVAL;
    }

    dev = get_cpu_device(cpu);
    if (!dev) {
        pr_err("can't online cpu %d as device does not exist\n", cpu);
        return -ENODEV;
    }

    /* 确保 CPU 已经完全离线 */
    cpu_maps_update_begin();
    if (cpu_online(cpu)) {
        err = -EEXIST;
        goto out;
    }

    /* 执行架构相关的 CPU 上线操作 */
    err = _cpu_up(cpu, 0, CPUHP_ONLINE);

out:
    cpu_maps_update_done();
    return err;
}
EXPORT_SYMBOL_GPL(cpu_up);

CPU 设备注册

// cpu.c
static struct bus_type cpu_subsys = {
    .name = "cpu",
    .dev_name = "cpu",
};

static int __init cpu_dev_init(void)
{
    int err;

    err = subsys_system_register(&cpu_subsys, cpu_root_attr_groups);
    if (err)
        return err;

    /* 创建 /sys/devices/system/cpu 目录 */
    cpu_dev_root = kzalloc(sizeof(*cpu_dev_root), GFP_KERNEL);
    if (!cpu_dev_root)
        return -ENOMEM;

    /* 注册每个 CPU 的 sysfs 接口 */
    for_each_possible_cpu(cpu) {
        struct device *dev;
        dev = get_cpu_device(cpu);
        if (dev) {
            err = device_register(dev);
            if (err)
                return err;
        }
    }

    return 0;
}

CPU 掩码管理

//cpumask.c
/* CPU 掩码操作函数 */
void cpumask_set_cpu(unsigned int cpu, struct cpumask *dstp)
{
    set_bit(cpu, cpumask_bits(dstp));
}

void cpumask_clear_cpu(unsigned int cpu, struct cpumask *dstp)
{
    clear_bit(cpu, cpumask_bits(dstp));
}

int cpumask_test_cpu(int cpu, const struct cpumask *cpumask)
{
    return test_bit(cpu, cpumask_bits((struct cpumask *)cpumask));
}

CPU 拓扑信息初始化

//tepology.c
/* 初始化 CPU 拓扑信息 */
void detect_extended_topology(struct cpuinfo_x86 *c)
{
    unsigned int eax, ebx, ecx, edx;

    if (c->extended_cpuid_level < 0xb)
        return;

    cpuid_count(0xb, 0, &eax, &ebx, &ecx, &edx);
    /* 如果 CPUID.0BH 不支持,返回 */
    if (ebx == 0 || (ecx & 0xff00) == 0)
        return;

    /* 解析 SMT 级别 */
    c->x86_max_cores = (ecx & 0xff00) >> 8;
    c->cpu_core_id = edx;

    /* 解析 Core 级别 */
    cpuid_count(0xb, 1, &eax, &ebx, &ecx, &edx);
    if ((ecx & 0xff00) != 0) {
        c->x86_max_cores = c->x86_max_cores / ((ecx & 0xff00) >> 8);
        c->phys_proc_id = edx;
    }
}

sysfs CPU 接口

//cpu.c
/* CPU 设备属性 */
static DEVICE_ATTR(online, 0644, show_online, store_online);
static DEVICE_ATTR(offline, 0444, show_offline, NULL);
static DEVICE_ATTR(possible, 0444, show_possible, NULL);
static DEVICE_ATTR(present, 0444, show_present, NULL);

/* CPU 在线状态控制 */
static ssize_t store_online(struct device *dev,
                           struct device_attribute *attr,
                           const char *buf, size_t count)
{
    struct cpu *cpu = container_of(dev, struct cpu, dev);
    int ret;

    switch (buf[0]) {
    case '0':
        ret = cpu_down(cpu->dev.id);
        break;
    case '1':
        ret = cpu_up(cpu->dev.id);
        break;
    default:
        ret = -EINVAL;
    }

    return ret ? ret : count;
}

CPU 热插拔状态机

//cpu.c
/* CPU 热插拔状态定义 */
enum cpuhp_state {
    CPUHP_OFFLINE = 0,
    CPUHP_CREATE_THREADS,
    CPUHP_PERF_PREPARE,
    CPUHP_WORKQUEUE_PREP,
    /* ... 更多状态 ... */
    CPUHP_ONLINE,
};

/* CPU 热插拔回调注册 */
int __cpuhp_setup_state(enum cpuhp_state state,
                        const char *name,
                        bool invoke,
                        int (*startup)(unsigned int cpu),
                        int (*teardown)(unsigned int cpu),
                        bool multi_instance)
{
    int ret = 0;
    /* ... 实现代码 ... */
    return ret;
}';

这些源码展示了 Linux 内核如何管理 CPU 编号和拓扑结构。主要涉及:
CPU 拓扑管理
CPU 热插拔
sysfs 接口
CPU 状态控制
设备注册


http://www.niftyadmin.cn/n/5862907.html

相关文章

php session数据存储位置选择

PHP session 数据的存储位置可以通过配置文件或者代码来进行设置。默认情况下&#xff0c;session 数据是存储在服务器的文件系统中的。你可以将 session 数据存储在其他地方&#xff0c;例如数据库、缓存等。 基础概念 PHP session默认情况下将数据存储在服务器端的临时文件中…

DEMF模型赋能多模态图像融合,助力肺癌高效分类

目录 论文创新点 实验设计 1. 可视化的研究设计 2. 样本选取和数据处理 3. 集成分类模型 4. 实验结果 5. 可视化结果 图表总结 可视化知识图谱 在肺癌早期筛查中,计算机断层扫描(CT)和正电子发射断层扫描(PET)作为两种关键的影像学手段,分别提供了丰富的解剖结构…

细分数字货币钱包的不同种类

文章目录 一、中心化钱包1.1 中心化钱包架构1.2 中心化钱包业务细节流程 二、去中心化钱包(HD 钱包)2.1 去中心化钱包架构2.2 去中心化钱包细节业务流程 三、硬件钱包3.1 硬件钱包架构3.2 硬件钱包细节业务流程 四、MPC 托管钱包五、多签钱包 中心化钱包 &#xff1a;钱包私钥一…

contes服务器配置IP地址

第一步&#xff1a; nmcli device status插入和拔出网线执行上面的命令&#xff0c;找出插入网线的网口&#xff08;enp26s0f0&#xff09; 第二步&#xff1a; 比如配置的操作如下&#xff1a; IP&#xff1a;10.218.231.84 子网掩码&#xff1a;255.255.255.0 网关&#xff…

一些时间方法

1.禁用之前的时间 <el-date-picker:picker-options"disableBeforePicker"disableBeforePicker: {disabledDate(time) {return time.getTime() < Date.now() - 8.64e7;}, }, 2.选择开始时间之后&#xff0c;结束时间为开始时间之后的120分钟&#xff0c;他们的…

(网络安全)渗透测试

1、渗透测试种类 2、网络安全渗透测试分类 1&#xff09;网络安全渗透测试&#xff0c; 根据事先对测试目标系统信息的了解程度&#xff0c;可以分为 a.黑盒测试&#xff1a; 只知道要测试的目标系统&#xff0c;但系统内部的任何信息&#xff0c;都不清楚。这种测试最真实&am…

我的世界1.20.1forge开发教程(6)——自定义燃料,熔炼规则、配方

配方篇 在Minecraft中,配方代码是用于定义合成配方的一种数据格式。在开发者的角度,配方代码通常以JSON格式编写,包含了合成所需的原料、合成产物以及合成方式等信息。 在1.12版本之前,开发者需要通过修改游戏的源代码来添加自定义配方。这通常需要对游戏的Java代码进行修…

【.NET全栈】.NET包含的所有技术

文章目录 前言一、基础框架与语言1、.NET Framework2、编程语言 二、Web开发技术1、ASP.NET2、Blazor3、SignalR 三、桌面与移动开发技术1、Windows Forms&#xff08;WinForms&#xff09;2、Windows Presentation Foundation&#xff08;WPF&#xff09;3、Xamarin4、.NET MA…