Chinaunix首页 | 论坛 | 博客
  • 博客访问: 513027
  • 博文数量: 52
  • 博客积分: 1223
  • 博客等级: 少尉
  • 技术积分: 751
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-23 21:32
文章分类

全部博文(52)

文章存档

2016年(1)

2015年(5)

2013年(1)

2012年(45)

分类: LINUX

2013-01-04 17:46:52

CPU热插拔的FAQ

Q:如何使我的内核能够支持处理器热插拔?

A:     make defconfig时使能CPU热插拔的支持:

         "Processor type and Features" -> Support for Hotpluggable CPUs

         另外还需打开CONFIG_HOTPLUGCONFIG_SMP选项。如果需要支持SMP的挂起/恢复,也需要打开CONFIG_HOTPLUG_CPU选项。

Q:     如果测试一个新编译的内核是否支持热插拔?

A:     请注意/sys中的一个文件。

         首先使用mount命令确定sysfs是否已挂载。请注意输出中是否有如下的语句。

         ....

         none on /sys type sysfs (rw)

         ....

如果有这句话表明/sys已经挂载。

/sys如果没有挂载,可以通过如下方式挂载:

#mount -t sysfs sys /sys

         现在可以看到与所有系统中已存在的CPU对应的文件夹,下面是一个8路系统中的例子。

         #pwd

         #/sys/devices/system/cpu

         #ls -l

         total 0

         drwxr-xr-x  10 root root 0 Sep 19 07:44 .

         drwxr-xr-x  13 root root 0 Sep 19 07:45 ..

         drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu0

         drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu1

         drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu2

         drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu3

         drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu4

         drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu5

         drwxr-xr-x   3 root root 0 Sep 19 07:44 cpu6

         drwxr-xr-x   3 root root 0 Sep 19 07:48 cpu7

         在每个文件夹下,都有名为“online”的文件,这是一个控制文件[control file. I like the word.],可以用来使能/禁用[online/offline]一个处理器。

 

Q:热插/热拔是否对应物理上对处理器的添加/移除?

A:     这里对热插/热拔的使用并不是与其字面上的意义完全一致。CONFIG_HOTPLUG_CPU使得内核能够进行逻辑上的使能与禁用。为了支持物理上的添加/移除,需要一些BIOS回调函数,并且还需要平台具有一些类似于PCI热插拔按钮之类的机制。CONFIG_ACPI_HOTPLUG_CPU使得ACPI能够支持CPU在物理上的添加/移除。

Q:如何在逻辑上禁用一个CPU?

A:     执行如下操作。

                  #echo 0 > /sys/devices/system/cpu/cpuX/online

         如果逻辑上的禁用成功,检查

         #cat /proc/interrupts

         在此文件中,将看不到被移除的CPU对应的列了。当CPU被移除后,它的online文件为0,否则为1.

         #To display the current cpu state.

         #cat /sys/devices/system/cpu/cpuX/online

 

Q:     为什么在一些系统中无法移除CPU0

A:一些体系结构中,某些中断只能发送给特定的CPU,一般是CPU0。

         这种情况下,你会发现cpu0没有online文件。

 

Q:     如果一个特殊的CPU不能被移除,我如何找出它?

A  这个依赖于具体的实现方法,在一些体系结构上,我们找不到这些CPU的“online”文件。

         在某些情况下,可以在运行时进行检查,即,如果你希望移除最后一个CPU,这是不允许的。此时,“echo”命令会给出一个错误提示。

 

Q:当一个CPU在逻辑上被移除时,会发生什么?

A:将会发生下面的事情,排列是无序的 J

-          内核中的模块会接收到一个通知[notification],对应的事件是CPU_DOWN_PREPARE 或者CPU_DOWN_PREPARE_FROZEN,具体是哪个事件则依赖于CPU被移除时,是否有任务被“冷冻”,任务被冷冻的原因是正在执行挂起操作。

-          CPU上的所有进程都被迁移到新的CPU上。新CPU通过每个进程的当前处理器设置(cpuset)进行选择,这些设置可能是所有在用CPU的子集。

-          所有定向到此CPU上的中断都被迁移到新的CPU上。

-          定时器/BH/task lets也将被迁移到新的CPU上。

-          一旦所有的服务都被迁移了,内核便调用一个体系结构相关[arch specific]的例程__cpu_disable()来执行体系结构相关的清理工作。

-          如果上面的工作也完成了,一个代表清理成功的事件将被发送,此事件为CPU_DEAD。(如果存在冰冻任务,相应的事件则为CPU_DEAD_FROZEN。也就是说在移除CPU时,系统正在执行挂起操作。)

CPU_DOWN_PREPARE通知链被调用时,所有服务都应该被清除。当CPU_DEAD被调用时,不应在有任何东西运行于被移除的CPU上。

 

Q  如果我的内核代码需要能够感知CPU的到达和离开,我如何正确地安排通知链?

A  下面的代码给出了你的内核代码在收到一个通知时应做的工作。

         #include

         static int __cpuinit foobar_cpu_callback(struct notifier_block *nfb,

                                                   unsigned long action, void *hcpu)

         {

                   unsigned int cpu = (unsigned long)hcpu;

 

                   switch (action) {

                   case CPU_ONLINE:

                   case CPU_ONLINE_FROZEN:

                            foobar_online_action(cpu);

                            break;

                   case CPU_DEAD:

                   case CPU_DEAD_FROZEN:

                            foobar_dead_action(cpu);

                            break;

                   }

                   return NOTIFY_OK;

         }

 

         static struct notifier_block __cpuinitdata foobar_cpu_notifer =

         {

            .notifier_call = foobar_cpu_callback,

         };

         你需要在初始化函数中调用函数register_cpu_notifier()。初始化函数可能具有2种类型:

1.       Early init: 仅在启动处理器在用时才调用的初始化函数。

2.       Late init: 在所有的处理器都在用后才调用的初始化函数。

对第一种情况,你应该在初始化函数中加入下面的代码。

register_cpu_notifier(&foobar_cpu_notifier);

         对第二种情况,你应该将下面的代码加在初始化函数中。

                   register_hotcpu_notifier(&foobar_cpu_notifier);

         如果在准备资源时出了任何错误,你的PREPARE通知链都将出错。这将终止活动,并随后发送一个CANCELED事件。

         CPU_DEAD不应该失败,它仅仅是在通知一个好消息。当某个通知链在执行时发出了一个BAD通知时,则意味着可能会发生坏事情。

 

Q:     我的代码被调用的次数貌似并不等于所有被使能或正在运行的CPU的个数?

A  是的,CPU通知链仅在新的CPU被使能或禁用时才会被调用。如果你需要为系统中的每个CPU都执行一段程序,请参考下面的代码。

         for_each_online_cpu(i) {

                   foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i);

                   foobar_cpu_callback(&foobar_cpu_notifier, CPU_ONLINE, i);

         }

 

Q:如果我想为一种新的体系结构开发CPU热插拔的支持,如何做才能使工作量最小?

A  要使CPU热插拔的基础框架能够正确工作,需要做以下工作。

-          确定在Kconfig中添加了使能CONFIG_HOTPLUG_CPU的选项。

-          __cpu_up(): 使能一个CPU时,面向体系结构的接口。

-          __cpu_disable(): 关闭一个CPU时,面向体系结构的接口,在此函数返回时,不在有中断会被内核处理。局部APIC定时器等设备也被关掉了。

-          __cpu_die():      此函数用来确认某个CPU是否真的被关掉了。最好还是去仔细看一下为其它体系结构而编写的热插拔代码。尤其是在这种体系结构上,如何将CPUidle()循环中关掉。__cpu_die()通常是在等待某些每CPU状态被设置,以确保处理器关闭例程被正确地调用。

 

Q  当一些与某个特殊的CPU相关的工作正在执行时,我需要确保这个特殊的CPU不会被移除。

A:     2种方式,可以使一个CPU不会被移除。如果你的代码可以在中断上下文中执行,那么就使用函数smp_call_function_single(),否则就使用work_on_cpu()。需要注意的是,work_on_cpu()执行的很慢,而且可能由于内存不够而失败。

         int my_func_on_cpu(int cpu)

         {

                   int err;

                   get_online_cpus();

                   if (!cpu_online(cpu))

                            err = -EINVAL;

                   else

#if NEEDS_BLOCKING

                            err = work_on_cpu(cpu, __my_func_on_cpu, NULL);

#else

                            smp_call_function_single(cpu, __my_func_on_cpu, &err,

                                                         true);

#endif

                   put_online_cpus();

                   return err;

         }



阅读(3319) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~