linux 系统中将中断的处理程序分成
上下半部, top half 下半部bottom half
紧急的任务作为上半部, 非紧急的事情放在下半部
这样其实是省力不省功, 因为中断处理的程序时间一样, 但是好处就是, 系统的响应性好.
中断的下半部关键就是
#define DECLARE_TASKLET(name, func, data) \
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }
这是一个宏定义
其实就是定义了一个结构体变量
name 就是中断下半部的名字
func, 中断下半部处理函数名字
data 给func 传递的参数
定义好之后
使用
在中断的上半部调用
tasklet_schedule(&name);
进行注册即可
还有另外一种方式
就是
#define DECLARE_WORK(n, f) \
struct work_struct n = __WORK_INITIALIZER(n, f)
n就是名字
f 就是 void (*work_func_t)(struct work_struct *work) 类型的一个函数
然后在中断上半部调用
schedule_work(&n); 进行注册
中断上下半部使用的原则
(1) 非常紧急,的极少量任务放在中断的top half 里面, 此时,是屏蔽了自己同类型的中断, 因此可以迅速且不受打扰的处理紧急任务
(2) 需要少量的时间中等数据量任务使用tasklet 中, 此时不会屏蔽中断(包括与自己的上半部同类型的中断), 所以不影响顶半部对紧急事务的处理, 同事又不会进行用户调度, 从而保证自己任务迅速完成. 意思tasklet 处理的函数, 可能会被自己同类型的中断上半部打断. 先执行别人紧急的中断上半部,然后在执行自己的中断下半部.
(3) 需要较多的时间,不算迫切(允许被操作系统剥夺运行权)的大量任务放在workqueue中, 此时操作系统尽快完成这些事情, 但是任务量如果太大, 期间操作系统也会用用户之间的调度运行, 从而保证不会因为这些任务运行时间太大,导致别的用户进程无法进行.
(4) 可能引起睡眠的任务可以放在workqueue中, 在workqueue中睡眠是安全的, 在活得大量内存时, 或者在获取信号量, 在执行阻塞的I/O操作时, 用workqueue是很合适的.