linux 的内核任务队列

linux 的内核任务队列

ID:40749601

大小:75.00 KB

页数:22页

时间:2019-08-07

linux 的内核任务队列_第1页
linux 的内核任务队列_第2页
linux 的内核任务队列_第3页
linux 的内核任务队列_第4页
linux 的内核任务队列_第5页
资源描述:

《linux 的内核任务队列》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库

1、驱动程序需要将任务延迟到以后处理,但又不想借助中断。Linux为此提供了三种方法:任务队列、tasklet(从内核2.3.43开始)和内核定时器。任务队列和tasklet的使用很灵活,可以或长或短地延迟任务到以后处理,在编写中断处理程序时非常有用,我们还将在第9章“Tasklet和底半部处理”一节中继续讨论。内核定时器则用来调度任务在未来某个指定时间执行,将在本章的“内核定时器”一节中讨论。      使用任务队列或tasklet的一个典型情形是,硬件不产生中断,但仍希望提供阻塞型的读取。此时需要对设备进

2、行轮询,同时要小心地不使CPU负担过多无谓的操作。将读进程以固定的时间间隔唤醒(例如,使用current->timeout变量)并不是个很好的方法,因为每次轮询需要两次上下文切换(一次是切换到读进程中运行轮询代码,另一次是返回执行实际工作的某个进程),而且通常来讲,恰当的轮询机制应该在进程上下文之外实现。    类似的情形还有象不时地给简单的硬件设备提供输入。例如,有一个直接连接到并口的步进马达,要求该马达能一步步地移动,但马达每次只能移动一步。在这种情况下,由控制进程通知设备驱动程序进行移动,但实际上,

3、移动是在write返回后,才在周期性的时间间隔内一步一步进行的。    快速完成这类不定操作的恰当方法是注册任务在未来执行。内核提供了对“任务队列”的支持,任务可以累积,而在运行队列时被“消耗”。我们可以声明自己的任务队列,并且在任意时刻触发它,或者也可以将任务注册到预定义的任务队列中去,由内核来运行(触发)它。任务队列的本质任务队列其实是一个任务链表,每个任务用一个函数指针和一个参数表示。任务运行时,它接受一个void*类型的参数,返回值类型为void,而指针参数可用来将一个数据结构传入函数,或者可以被

4、忽略。队列本身是一个结构(即任务)链表,并由声明和操纵它们的内核模块所拥有。模块要全权负责这些数据结构的分配和释放,为此一般使用静态的数据结构。队列元素由下面这个结构来描述,这段代码是直接从头文件拷贝下来的:structtq_struct{structtq_struct*next;/*linkedlistofactivebh's*/intsync;/*mustbeinitializedtozero*/void(*routine)(void*);/*functiontocal

5、l*/void*data;/*argumenttofunction*/};第一个注释中的bh指的是底半部(bottom-half)。底半部是“中断处理程序的一半部”,我们将在第9章的“tasklet和底半部”一节中介绍中断时详细讨论。现在,我们只要知道底半部是驱动程序实现的一种机制就可以了,它用于处理异步任务,这些任务通常比较大,不适于在处理硬件中断时完成。本章并不要求你理解底半部处理,但必要时也会偶尔提及。译注:在2.4版本的内核中,tq_struct的第一个成员变量已经有所不同,改为structlis

6、t_headlist;/*linkedlistofactivebh's*/这是因为通用的双向链表list_head在内核中大量采用,在很多情况下替代了数据结构中自行维护的链表。相应的task_queue的定义也改为typedefstructlist_headtask_queue;      上面的数据结构中最重要的成员是routine和data。为了将随后执行的任务排队,必须先设置好结构的这些成员,并把next和sync两个字段清零。结构中的sync标志位由内核使用,以避免同一任务被插入多次,因为这会破坏

7、next指针。一旦任务被排队,该数据结构就被认为由内核“拥有”了,不能再被修改,直到任务开始运行。      与任务队列有关的其他数据结构还有task_queue,目前它实现为指向tq_struct结构的指针,之所以将这个指针(structtq_struct*)定义成另一个数据结构(structtask_queue)是为了扩展的需要,在需要的时候,task_queue结构中可以增加别的内容。在使用之前,必须将task_queue指针初始化为NULL。下面汇总了所有可以在任务队列和tq_struct结构上执

8、行的操作。DECLARE_TASK_QUEUE(name);这个宏用给定的名称name声明了一个任务队列,并把它初始化为空。intqueue_task(structtq_struct*task,task_queue*list);正如该函数的名字,它用于将任务排进队列中。如果队列中已有该任务,返回0,否则返回非0。voidrun_task_queue(task_queue*list);run_task_queue函数用于运行累积

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。