linux内核怎么变化,Linux内核中CPU状态变化机制简介

1. CPU状态

在Linux内核include/linux/notifier.h文件中,定义了几种CPU状态,如下所示:

#define CPU_ONLINE                          0x0002    /* CPU (unsigned)v is up */

#define CPU_UP_PREPARE                0x0003   /* CPU (unsigned)v coming up */

#define CPU_UP_CANCELED             0x0004   /* CPU (unsigned)v NOT coming up */

#define CPU_DOWN_PREPARE         0x0005   /* CPU (unsigned)v going down */

#define CPU_DOWN_FAILED             0x0006    /* CPU (unsigned)v NOT going down */

#define CPU_DEAD            0x0007 /* CPU (unsigned)v dead */

#define CPU_DYING          0x0008 /* CPU (unsigned)v not running any task,

* not handling interrupts, soon dead.

* Called on the dying cpu, interrupts

* are already disabled. Must not

* sleep, must not fail */

#define CPU_POST_DEAD                  0x0009  /* CPU (unsigned)v dead, cpu_hotplug lock is dropped */

#define CPU_STARTING             0x000A /* CPU (unsigned)v soon running.

* Called on the new cpu, just before

* enabling interrupts. Must not sleep,

* must not fail */

2.  状态变化通知链

为了让内核中其他模块能觉察到CPU状态的变化,在内核中定义了一个全局链表cpu_chain。需要觉察CPU状态变化的模块,会调用函数register_cpu_notifier,此函数会将模块提供的struct notifier_block结构体变量加入到全局链表cpu_chain中。

具体代码如下所示:

在kernel/cpu.c文件中,定义了全局链表cpu_chain。如下所示:

static RAW_NOTIFIER_HEAD(cpu_chain);

函数register_cpu_notifier实现如下所示:

int __ref register_cpu_notifier(struct notifier_block *nb)

{

int ret;

……;

ret = raw_notifier_chain_register(&cpu_chain, nb);

……;

return ret;

}

在内核其他模块kernel/watchdog.c文件中对函数register_cpu_notifier的调用如下所示:

static int __cpuinit

cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)

{

int hotcpu = (unsigned long)hcpu;

switch (action) {

case CPU_UP_PREPARE:

case CPU_UP_PREPARE_FROZEN:

if (watchdog_prepare_cpu(hotcpu))

return NOTIFY_BAD;

break;

case CPU_ONLINE:

case CPU_ONLINE_FROZEN:

if (watchdog_enable(hotcpu))

return NOTIFY_BAD;

break;

……

}

return NOTIFY_OK;

}

static struct notifier_block __cpuinitdata cpu_nfb = {

.notifier_call = cpu_callback

};

static int __init spawn_watchdog_task(void)

{

……

register_cpu_notifier(&cpu_nfb);

……

return 0;

}

early_initcall(spawn_watchdog_task);

Linux内核中相关模块为了觉察CPU状态变化注册了相关函数,那么CPU状态变化又是如何通知到这些模块的呢?在kernel/cpu.c文件中,定义了两个函数cpu_notify和__cpu_notify,它们会通过调用其他功能函数来遍历全局链表cpu_chain,遍历过程中会调用其他模块注册的结构体变量notifier_block中的notifier_call函数。

3. CPU状态变化

通过在内核文件中查找cpu_notify函数和此函数调用的__cpu_notify函数,可以得到CPU状态变化的代码段,如下所示:

在kernel/cpu.c文件中,_cpu_up函数如下所示:

static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)

{

……

ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls);

……

/* Now call notifier in preparation. */

cpu_notify(CPU_ONLINE | mod, hcpu);

out_notify:

if (ret != 0)

__cpu_notify(CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL);

……;

}

_cpu_down函数如下所示:

static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)

{

……

err = __cpu_notify(CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls);

if (err) {

__cpu_notify(CPU_DOWN_FAILED | mod, hcpu, nr_calls, NULL);

}

……

/* CPU is completely dead: tell everyone.  Too late to complain. */

cpu_notify_nofail(CPU_DEAD | mod, hcpu);

out_release:

if (!err)

cpu_notify_nofail(CPU_POST_DEAD | mod, hcpu);

return err;

}

notify_cpu_starting函数如下所示:

void __cpuinit notify_cpu_starting(unsigned int cpu)

{

unsigned long val = CPU_STARTING;

cpu_notify(val, (void *)(long)cpu);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值