链表是一种常用的数据结构,它通过指针 将一系列数据节点连接成一条数据链。相对于数组,链表具有更好的动态性,建立
链表时无需预先知道数据总量,可以随机分配空间,可以高效地在链表中的任意位
置实时插入或删除数据。链表的开销主要是访问的顺序性和组织链的空间损失。
通常链表数据结构至少包含两个域:数据 域和指针域,数据域用于存储数据,指针域用于建立与下一个节点的联系。按照指针域的组织以及各个节点之间的联系形式,链表又可以分为单链表、双链表、循环链表等多种类型。
在Linux内核中使用了大量的链表结 构来组织数据。这些链表大多采用了[include/linux/list.h]中实现的一套精彩的链表数据结构。
内核链表数据结构的定义:
struct list_head
{
struct list_head *next, *prev;
};
list_head结构包含两个指向list_head结构的指针 prev和next,由此可见,内核的链表具备双链表功能
初始化链表头 INIT_LIST_HEAD(list_head *head)
插入节点
list_add(struct list_head *new, struct list_head *head) 插入头指针后面
list_add_tail(struct list_head *new, struct list_head *head) 插入尾部
删除节点 list_del(struct list_head *entry)
提取数据结构 list_entry(ptr, type, member)
遍历 list_for_each(struc list_head *pos, struc list_head *head)
时钟中断由系统的定时硬件以周期性的时间间隔产生,这个间隔(即频率)由内核根据HZ来确定,HZ是一个与体系结构无关
的常数,可配置(50-1200),在X86平台,默认值为1000。
每当时钟中断发生时,全局变量jiffies(unsigned long)就加1,因此jiffies记录了自linux启动后时钟中断发生的次数。驱动程序常利用jiffies来计算不同事件间的时间间隔。
如果对延迟的精度要求不高,最简单的实现方法如下--忙等待:
unsigned long j=jiffies + jit_delay*HZ;
while (jiffies {
/* do nothing */
}延时jit_delay秒
内核定时器用于控制某个函数(定时器处理函数)在未来的某个特定时间执行。内核定时器注册的处理函数只执行一次--不是循环执行的。
内核定时器被组织成双向链表,并使用struct timer_list结构描述。
struct timer_list{
struct list_head entry /*内核使用*/;
unsigned long expires; /*超时的jiffies值*/
void (*function)(unsigned long); /*超时处理函数*/
unsigned long data; /*超时处理函数参数*/
struct tvec_base *base; /*内核使用*/
};
void init_timer(struct timer_list *timer); 初始化定时器队列结构。
void add_timer(struct timer_list * timer); 启动定时器。
int del_timer(struct timer_list *timer); 在定时器超时前将它删除。当定时器超时后,系统会自动地将它删除。