linux 中断处理 tasklet workqueue

linux中注册中断历程用request_irq,isr原型为: irqreturn_t *(int irq, void* dev_id, struct pt_reg* regs)

为了使中断关闭的时间尽可能的短,linux提出了中断上半部和下半部。上半部为request_irq注册的ISR,要求时间尽可能的短,而将尽可能的工作推迟到下半部去做。下半部由上半部调度,并在安全的时间内执行,此时中断已经打开了。linux有两种机制可以实现下半部:tasket和workqueue。

 

tasklet为软中断的一种。linux内核有HI_SOFTIRQ, TIMER, NET_TX, NET_RX, BLOCK, TASKLET, SCHED, HRTIMER, RCU 等软中断, 在系统初始化时调用open_softirq注册。在isr中声明tasklet,然后函数tasklet_schedule()调用raise_softirq(TASKLET_IRQ),然后系统在合适的时间调度tasklet运行。

workqueue本质为内核线程。

create_workqueue -> create_workqueue_thread

||                                     |->kthread_create(worker_thread)            // worker_thread 检查work_list,如果非空则依次执行起func

||                                                |->设置kthread_create_list,然后唤醒kthreadd_task(负责检查kthread_create_list,如果非空则调用kernel_thread创建内核线程)

|| -> start_workqueue_thread

           ||-> wake_up_process(kthread_create返回的worker_thread)  //通过设置task->state=RUNNING使得下次可以调度到。

 

schedule_work = queue_work(eventd_wq, work)    // eventd_wq 为系统初始化时创建的workqueue。用户可以用create_workqueue创建自己的workqueue。

 

tasklet中不允许休眠,而workqueue允许。tasklet调用时为中断上下文,workque为进程上下文(仅有内核代码)。

 

linux 中的timer 即采用了中断和softirq的机制实现的。在时钟中断例程 timer_interrupt中调用do_timer_interrupt,更新jiffies,检查进程时间片,设置TIMER_SOFTIRQ并调用timer的软中断(在这里处理与timer有关的tvec_base),最后统计信息。

 

 

 

你可能感兴趣的:(linux 中断处理 tasklet workqueue)