linux kernel2.6中软中断运行线程ksoftirqd的创建

linux kernel2.6中软中断运行线程ksoftirqd的创建 2013-01-03 10:31:32

分类:

原文地址:linux kernel2.6中软中断运行线程ksoftirqd的创建 作者:aweii


1、软中断由内核线程ksoftirqd处理,下面说一下它的创建过程。 start_kernel()创建init线程,init()调用do_pre_smp_initcalls()->spawn_ksoftirqd( ),spawn_ksoftirqd()分两次调用cpu_callback(),分别使用参数CPU_UP_PREPARE和CPU_ONLINE。使用CPU_UP_PREPARE调用cpu_callback()
时,创建了ksoftirqd线程,并把task_struct指针存于per_cpu变量per_cpu(ksoftirqd,
hotcpu)中;使用CPU_ONLINE调用该函数对ksoftirqd线程进行唤醒。

点击(此处)折叠或打开

  1. --------------linux/init/main.c---------------------

  2. static void do_pre_smp_initcalls(void)

  3. {

  4. extern int spawn_ksoftirqd(void);

  5. #ifdef CONFIG_SMP

  6. extern int migration_init(void);

  7. migration_init();

  8. #endif

  9. spawn_ksoftirqd();

  10. }



----------------linux/kernel/softirq.c----------------- /* 主cpu(即引导cpu)通过spawn_ksoftirqd()->cpu_callback()创建该cpu上的ksoftirqd 内核线程,并调用register_cpu_notifier() 将cpu_nfb注册到cpu通知链) */

点击(此处)折叠或打开

  1. __init int spawn_ksoftirqd(void)

  2. {

  3. void *cpu =(void *)(long)smp_processor_id();

  4. cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);

  5. cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);

  6. register_cpu_notifier(&cpu_nfb);

  7. return 0;

  8. }


----------------linux/kernel/softirq.c--------------------- //cpu_callback()建立了ksoftirqd内核线程,并把task_struct指针存于per_cpu变量per_cpu(ksoftirqd, hotcpu)中

点击(此处)折叠或打开

  1. static int __devinit cpu_callback(struct notifier_block *nfb,

  2.      unsigned long action,

  3.      void *hcpu)

  4. {

  5. int hotcpu =(unsigned long)hcpu;

  6. struct task_struct *p;

  7. switch (action){

  8. case CPU_UP_PREPARE:

  9.  BUG_ON(per_cpu(tasklet_vec, hotcpu).list);

  10.  BUG_ON(per_cpu(tasklet_hi_vec, hotcpu).list);

  11.  p = kthread_create(ksoftirqd, hcpu,"ksoftirqd/%d", hotcpu);

  12. if(IS_ERR(p)){

  13.   printk("ksoftirqd for %i failed\n", hotcpu);

  14.   return NOTIFY_BAD;

  15. }

  16.  kthread_bind(p, hotcpu);

  17.    per_cpu(ksoftirqd, hotcpu)= p;

  18.   break;

  19. case CPU_ONLINE:

  20.  wake_up_process(per_cpu(ksoftirqd, hotcpu));

  21.  break;

  22. #ifdef CONFIG_HOTPLUG_CPU

  23. case CPU_UP_CANCELED:

  24. /* Unbind so it can run. Fall thru.*/

  25.  kthread_bind(per_cpu(ksoftirqd, hotcpu), smp_processor_id());

  26. case CPU_DEAD:

  27.  p = per_cpu(ksoftirqd, hotcpu);

  28.  per_cpu(ksoftirqd, hotcpu)=NULL;

  29.  kthread_stop(p);

  30.  takeover_tasklets(hotcpu);

  31.  break;

  32. #endif /* CONFIG_HOTPLUG_CPU */

  33. }

  34. return NOTIFY_OK;

  35. }



2、从cpu的ksoftirqd线程的创建。从cpu调用start_kernel()->init()->smp_init()->cpu_up(),cpu_up()在各cpu上线前后分别调用notifier_call_chain()。


点击(此处)折叠或打开

  1. static void __init smp_init(void)

  2. {

  3. unsigned int i;

  4. /* FIXME: This should be done in userspace --RR */

  5. for_each_present_cpu(i){

  6. if(num_online_cpus()>= max_cpus)

  7.   break;

  8. if(!cpu_online(i))

  9.   cpu_up(i);

  10. }

  11. ……

  12. }

  13. int __devinit cpu_up(unsigned int cpu)

  14. {

  15. ……

  16. //上线前调用

  17. ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu);

  18. ……

  19. //等cpu上线:cpu_isset(cpu, cpu_online_map)

  20. ret = __cpu_up(cpu);

  21. ……

  22. /*Nowcall notifier in preparation.*/

  23. //上线后调用

  24. notifier_call_chain(&cpu_chain, CPU_ONLINE, hcpu);

  25. }


  26. //函数notifier_call_chain()以cpu标号为参数运行cpu通知链上的各函数,其中包含上述spawn_ksoftirqd()中注册的cpu_nfb。

  27. static struct notifier_block __devinitdata cpu_nfb ={

  28. .notifier_call = cpu_callback

  29. };


  30. //通知链元素cpu_nb上的函数cpu_callback即用来创建各非引导cpu上的ksoftirqd线程。

  31. int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v)

  32. {

  33. int ret=NOTIFY_DONE;

  34. struct notifier_block *nb =*n;

  35. while(nb)

  36. {

  37.  ret=nb->notifier_call(nb,val,v);

  38. if(ret&NOTIFY_STOP_MASK)

  39. {

  40.   return ret;

  41. }

  42.  nb=nb->next;

  43. }

  44. return ret;

  45. }


你可能感兴趣的:(linux)