linux 软中断的使用
软中断保留给系统中对时间要求最严格以及最重要的下半部使用。目前只有两个子系统直接使用了软中断
(网络和SCSI)内核定时器和tasklet也是建立在软中断上的
编译期间在<linux/interrupt.h>定义一个枚举类型来静态的申明一个软中断
注册你的处理程序
open_softirq();//注册中断处理函数
例如:
open_softirq(NET_TX_SOFTIRQ,net_tx_action);
open_softirq(NET_RX_SOFTIRQ,net_rx_action);
这里会有共享数据的问题,要有严格的锁保护,甚至是处理程序内部的变量。
在中断处理函数当中触发软中断是最常见的形式。
中断挂起函数:
raise_softirq();
软中断与中断处理程序一起完成中断的上半部与下半部
tasklet的实现:
其本身也是软中断,有两类中断代表 HI_SOFTIRQ和TASKLET_SOFTIRQ
结构体的定义在<linux/interrupt.h>当中
struct tasklet_struct{
struct tasklet_struct *next;
unsigned long state;
atomic_t counjt; //引用计数器(什么鬼)
void (*func)(unsigned long); //tasklet处理函数
unsigned long data ;//给tasklet处理函数的参数
};
这里要注意的是count成员是tasklet的引用计数器,如果不为0,则tasklet禁止,不允许执行
为零是被激活,,并且被设置为挂起状态时,tasklet才能够执行
tasklet 由tasklet_schdule()和task_hi_schedule()进行调度。
tasklet是实现寻常设备下半部的最佳选择。tasklet可以动态创建,使用方便。
使用tasklet
如果进行静态的创建,使用<linux/interrupt.h>中定义的两个宏当中的一个
DECLEAR_TASKLET(name,func,data);
DECLEAR_TASKLET_DISABLE(name,func,data);
//参数由data变量给出,区别在于计数器的初始值不同。DECLEAR_TASKLET()默认激活,DECLEAR_TASKLET_DISABLE()默认未激活。
DECLEAR_TASKLET(my_tasklet,my_tasklet_handler,dev);
等价于:
struct struct_tasklet my_tasklet{
NULL,
0,
ATOMIC_INIT(0),
my_tasklet_handler,
dev;
};
编写自己的tasklet处理函数;
void tasklet_handler(unsigned long data); //规定的函数类型
由于使用软中断实现,所以tasklet不能睡眠,所以不能在tasklet中使用信号量或者其他阻塞式的函数。tasklet运行时允许相应
中断,所以要做好预防工作,如果tasklet和中断处理程序之间共享了某些数据的话,两个相同的tasklet不会同时运行。
今天的记录先到这里。爱你YZ。