2.8. 任务队列
任务队列可以看作是以前的下半部机制的动态扩展。在源代码里面,有时以新下半部机制来称呼他们。以前的下半部机制有一下的限制:
1) 他们仅有一个固定的数目;
2) 每个下半部仅仅能够关联一个处理函数;
3) 下半部可以被旋转锁结束,所以他们不能阻塞;
所以,对于任务队列,任意数目的函数可以被关联并前后连续的处理。通过DECLARE_TASK_QUEUE宏可以创建一个新的任务队列,采用queue_task函数可以向其中增加一个任务而调用run_task_queue函数则会执行一个任务队列。作为创建你自己的任务队列,你可以使用Linux系统提前定义的任务队列,如下所述:
1) tq_timer:定时器任务队列,在每个定时器中断或者释放tty设备时执行。当定时器处理函数在中断环境下运行时,tq_timer还运行于中断环境,并不能阻塞。
2) tq_scheduler:调度任务队列,由调度程序触发,同样关闭tty设备时也会运行。一旦调度程序运行于进程重设定的上下文后,tq_scheduler任务可以做任何想作的事情,比如阻塞,处理上下文数据等等。
3) tq_disk:用于底层阻塞设备启动真实的请求。这个任务队列为模块设计,除了设计本身的目的以外不能作为他用。
如果一个驱动使用它自身的任务队列,它就不需要调用run_tasks_queues函数去处理这个队列,除非是以下说明的情况。
tq_timer/tq_scheduler 任务队列不仅普通场合会被触发,而且其他场合(如关闭tty设备时)也会触发。如果我们记得驱动能够调度队列中的任务,并且这些任务仅仅在驱动的细节实例有效时做判断,,其原因非常简单的。这通常意味着应用关闭它。所以,驱动可能需要调用run_task_queue来激活它添加到队列中的任务,因为允许这些任务稍后执行是没有意义的,也就是说相关的数据结构可能被另一个实例释放或者重用。这就是run_task_queue在tq_timer 和tq_scheduler中多处使用而不是定时器中断和schedule分别调用。