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

 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线程进行唤醒。

--------------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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值