- --------------linux/init/main.c---------------------
- static void do_pre_smp_initcalls(void)
- {
- extern int spawn_ksoftirqd(void);
- #ifdef CONFIG_SMP
- extern int migration_init(void);
- migration_init();
- #endif
- spawn_ksoftirqd();
- }
----------------linux/kernel/softirq.c-----------------
/*
主cpu(即引导cpu)通过spawn_ksoftirqd()->cpu_callback()创建该cpu上的ksoftirqd
内核线程,并调用register_cpu_notifier()
将cpu_nfb注册到cpu通知链)
*/
- __init int spawn_ksoftirqd(void)
- {
- void *cpu = (void *)(long)smp_processor_id();
- cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
- cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
- register_cpu_notifier(&cpu_nfb);
- return 0;
- }
----------------linux/kernel/softirq.c---------------------
//cpu_callback()建立了ksoftirqd内核线程,并把task_struct指针存于per_cpu变量per_cpu(ksoftirqd, hotcpu)中
- static int __devinit cpu_callback(struct notifier_block *nfb,
- unsigned long action,
- void *hcpu)
- {
- int hotcpu = (unsigned long)hcpu;
- struct task_struct *p;
- switch (action) {
- case CPU_UP_PREPARE:
- BUG_ON(per_cpu(tasklet_vec, hotcpu).list);
- BUG_ON(per_cpu(tasklet_hi_vec, hotcpu).list);
- p = kthread_create(ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu);
- if (IS_ERR(p)) {
- printk("ksoftirqd for %i failed\n", hotcpu);
- return NOTIFY_BAD;
- }
- kthread_bind(p, hotcpu);
- per_cpu(ksoftirqd, hotcpu) = p;
- break;
- case CPU_ONLINE:
- wake_up_process(per_cpu(ksoftirqd, hotcpu));
- break;
- #ifdef CONFIG_HOTPLUG_CPU
- case CPU_UP_CANCELED:
- /* Unbind so it can run. Fall thru. */
- kthread_bind(per_cpu(ksoftirqd, hotcpu), smp_processor_id());
- case CPU_DEAD:
- p = per_cpu(ksoftirqd, hotcpu);
- per_cpu(ksoftirqd, hotcpu) = NULL;
- kthread_stop(p);
- takeover_tasklets(hotcpu);
- break;
- #endif /* CONFIG_HOTPLUG_CPU */
- }
- return NOTIFY_OK;
- }
2、从cpu的ksoftirqd线程的创建。从cpu调用start_kernel()->init()->smp_init()->cpu_up(),cpu_up()在各cpu上线前后分别调用notifier_call_chain()。
- static void __init smp_init(void)
- {
- unsigned int i;
- /* FIXME: This should be done in userspace --RR */
- for_each_present_cpu(i) {
- if (num_online_cpus() >= max_cpus)
- break;
- if (!cpu_online(i))
- cpu_up(i);
- }
- ……
- }
- int __devinit cpu_up(unsigned int cpu)
- {
- ……
- //上线前调用
- ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);
- ……
- //等cpu上线:cpu_isset(cpu, cpu_online_map)
- ret = __cpu_up(cpu);
- ……
- /* Now call notifier in preparation. */
- //上线后调用
- notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu);
- }
-
- //函数notifier_call_chain()以cpu标号为参数运行cpu通知链上的各函数,其中包含上述spawn_ksoftirqd()中注册的cpu_nfb。
- static struct notifier_block __devinitdata cpu_nfb = {
- .notifier_call = cpu_callback
- };
- //通知链元素cpu_nb上的函数cpu_callback即用来创建各非引导cpu上的ksoftirqd线程。
- int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v)
- {
- int ret=NOTIFY_DONE;
- struct notifier_block *nb = *n;
- while(nb)
- {
- ret=nb->notifier_call(nb,val,v);
- if(ret&NOTIFY_STOP_MASK)
- {
- return ret;
- }
- nb=nb->next;
- }
- return ret;
- }