软中断实现下半部

内核编译和嵌入式产品的设计与开发
回复
头像
zongzw
帖子: 94
注册时间: 2008-03-31 16:12

软中断实现下半部

#1

帖子 zongzw » 2009-08-22 11:57

内核版本2.5以后用于实现下半部的方式有三种:软中断、tasklet、工作队列。
个人在试验软中断的时候碰到一个编译问题,而明明知道这个问题是为什么,却不知道如何解决,所以请大家指点。

以下代码中是想通过软中断的使用步骤(分配索引、注册处理程序、触发软中断)触发并执行一个软中断。
(当然了,这只是一个试验,正常的软中断的使用场合多是在中断程序返回前)。

代码: 全选

 1 #include <linux/module.h>
 2 #include <linux/kernel.h>
 3 #include <linux/interrupt.h>
 4 
 5 void softirq_func(struct softirq_action *sa)
 6 {
 7     printk("%s, %d\n", __FUNCTION__, __LINE__);
 8 }
 9 
 10 static int mod_init(void)
 11 {
 12     unsigned long flags;
 13 
 14     printk("%s ...\n", __FUNCTION__);
 15     //MY_OWN_SOFTIRQ定义,我已在<linux/interrupt.h>的enum位置添加。 -----分配索引
 16     //open_softirq(MY_OWN_SOFTIRQ, softirq_func, NULL);                -----注册处理程序
 17     //softirq_vec[MY_OWN_SOFTIRQ].action = softirq_func;//open_softirq没有导出,直接将open_softirq实现在这里。
 18     //softirq_vec[MY_OWN_SOFTIRQ].data = NULL;
 19      
 20     //raise_softirq(MY_OWN_SOFTIRQ);                                              -----触发软中断
 21     local_irq_save(flags);//raise_softirq函数没有导出,改用raise_softirq_irqoff的方式
 22     printk("flags is %d\n", flags);
 23     //raise_softirq_irqoff(MY_OWN_SOFTIRQ);
 24     local_irq_restore(flags);
 25         
 26     return 0;
 27 }    
 28 static void mod_exit(void)
 29 {   
 30     printk("%s ...\n", __FUNCTION__);
 31 }   
 32 module_init(mod_init);
 33 module_exit(mod_exit);
结果出现了以下编译错误。

代码: 全选

make -C /lib/modules/2.6.23.1ubuntu810/build M=/root/Bottom_half modules 
make[1]: 正在进入目录 `/usr/src/linux-2.6.23.1'
  CC [M]  /root/Bottom_half/mod.o
/root/Bottom_half/mod.c: 在函数‘mod_init’中:
/root/Bottom_half/mod.c:30: 错误: ‘softirq_vec’未声明(在此函数内第一次使用)
/root/Bottom_half/mod.c:30: 错误: (即使在一个函数内多次出现,每个未声明的标识符在其
/root/Bottom_half/mod.c:30: 错误: 所在的函数内也只报告一次。)
/root/Bottom_half/mod.c:35: 警告: 格式‘%d’需要类型‘int’,但实参 2 的类型为‘long unsigned int’
make[2]: *** [/root/Bottom_half/mod.o] 错误 1
make[1]: *** [_module_/root/Bottom_half] 错误 2
make[1]:正在离开目录 `/usr/src/linux-2.6.23.1'
make: *** [all] 错误 2
也就是说softirq_vec没有找到声明,实际上它的声明在<源码目录>/kernel/softirq.c文件中声明。
该如何是好?
月光林地的猫
帖子: 37
注册时间: 2009-06-27 23:33

Re: 软中断实现下半部

#2

帖子 月光林地的猫 » 2009-08-23 13:05

我是新手,下面是从linux kernel development里翻来的.
1:raise_softirq()这个函数,已经把local_irq_save()和local_irq_restore()都包办了。书里原话是:
this function disables interrupts prior to actually raising the softirq,and then restores them to their previous state.
如果在raise_softirq()之前已经关闭了中断,就用raise_softirq_irqoff();
2:向linux/interrupt.h中的enum里添加新的softirq后,好像需要重新编译内核。(自己理解的,不知大对不对。)
Sottirqs are statically allocated at compile-time.Unlike tasklet,you cannot dynamically register and destroy softirqs.
头像
zongzw
帖子: 94
注册时间: 2008-03-31 16:12

Re: 软中断实现下半部

#3

帖子 zongzw » 2009-08-25 10:12

谢谢,虽然没有解决问题。
你说的1,是正确的,我看过raise_softirq的源码,在kernel/softirq.c文件中,如下

代码: 全选

337 void fastcall raise_softirq(unsigned int nr)
338 {
339     unsigned long flags;
340 
341     local_irq_save(flags);
342     raise_softirq_irqoff(nr);
343     local_irq_restore(flags);
344 }
确实,是你说的那样,“raise_softirq()这个函数,已经把local_irq_save()和local_irq_restore()都包办了”

第2点,我也觉得,是这样,如果添加了新的软中断号。
但我总觉得,内核软中断机制是会提供对外编程接口的,要不然驱动程序怎么写,是吧?
月光林地的猫
帖子: 37
注册时间: 2009-06-27 23:33

Re: 软中断实现下半部

#4

帖子 月光林地的猫 » 2009-08-25 17:53

我又重新看了bottom half那一部分,确实softirq是要静态编译进内核的。
深入理解第三版里:
软中断的分配是静态的(即在编译时定义),而tasklet的分配和初始化可以在运行时进行(例如:安装一个内核模块)。
用tasklet或者work queue吧。
头像
zongzw
帖子: 94
注册时间: 2008-03-31 16:12

Re: 软中断实现下半部

#5

帖子 zongzw » 2009-09-11 17:20

如果是静态的,不可用的,那网卡驱动中处理数据报的下半部是怎么实现的呢??
回复