做网站前端程序员,在一呼百应上做网站行吗,南京500元做网站,wordpress主题分类链表(循环双向链表)是Linux内核中最简单、最常用的一种数据结构。1、链表的定义struct list_head {struct list_head *next, *prev;}这个不含数据域的链表,可以嵌入到任何数据结构中,例如可按如下方式定义含有数据域的链表#xff1a;struct my_list {void * mydata;struct l…链表(循环双向链表)是Linux内核中最简单、最常用的一种数据结构。1、链表的定义struct list_head {struct list_head *next, *prev;}这个不含数据域的链表,可以嵌入到任何数据结构中,例如可按如下方式定义含有数据域的链表struct my_list {void * mydata;struct list_head list;} ;2、链表的声明和初始化宏struct list_head 只定义了链表结点,并没有专门定义链表头.那么一个链表结点是如何建立起来的内核代码 list.h 中定义了两个宏#defind LIST_HEAD_INIT(name) { (name), (name) } //仅初始化#defind LIST_HEAD(name) struct list_head name LIST_HEAD_INIT(name) //声明并初始化如果要声明并初始化链表头mylist_head则直接调用LIST_HEAD(mylist_head)之后mylist_head的next、prev指针都初始化为指向自己。这样就有了一个带头结点的空链表。判断链表是否为空的函数static inline int list_empty(const struct list_head * head) {return head-next head;} //返回1表示链表为空0表示不空3、在链表中增加一个结点(内核代码中函数名前加两个下划线表示内部函数)static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next){next - prev new ;new - next next ;new - prev prev ;prev - next new ;}list.h 中增加结点的两个函数为(链表是循环的可以将任何结点传递给head调用这个内部函数以分别在链表头和尾增加结点)static inline void list_add(struct list_head *new, struct llist_head *head){__list_add(new, head, head - next) ;}static inline void list_add_tail(struct list_head 8new, struct list_head *head){__list_add(new, head - prev, head) ;}附给head传递第一个结点可以用来实现一个队列传递最后一个结点可以实现一个栈。static 加在函数前表示这个函数是静态函数其实际上是对作用域的限制指该函数作用域仅局限于本文件。所以说static 具有信息隐蔽的作用。而函数前加 inline 关键字的函数叫内联函数表示编译程序在调用这个函数时立即将该函数展开。4、 遍历链表list.h 中定义了如下遍历链表的宏#define list_for_each(pos, head) for(pos (head)- next ; pos ! (head) ; pos pos - next)这种遍历仅仅是找到一个个结点的当前位置那如何通过pos获得起始结点的地址从而可以引用结点的域list.h 中定义了 list_entry 宏#define list_entry( ptr, type, member ) \( (type *) ( (char *) (ptr) - (unsigned long) ( ( (type *)0 ) - member ) ) )分析(unsigned long) ( ( (type *)0 ) - member ) 把 0 地址转化为 type 结构的指针然后获取该结构中 member 域的指针也就是获得了 member 在type 结构中的偏移量。其中 (char *) (ptr) 求出的是 ptr 的绝对地址二者相减于是得到 type 类型结构体的起始地址即起始结点的地址。5、链表的应用一个用以创建、增加、删除和遍历一个双向链表的Linux内核模块点击(此处)折叠或打开#include #include #include #include MODULE_LICENCE(GPL);MODULE_AUTHOR(LUOTAIJIA);#define N 10struct numlist {int num;struct list_head list;};struct numlist numhead;static int __init doublelist_init(void){//初始化头结点struct numlist * listnode; //每次申请链表结点时所用的指针struct list_head * pos;struct numlist * p;int i;printk(doublelist is starting...\n);INIT_LIST_HEAD(numhead.list);/** static inline void INIT_LIST_HEAD(struct list_head *list)* {* list-next list;* list-prev list;* }*///建立N个结点依次加入到链表当中for (i0; ilistnode (struct numlist *)kmalloc(sizeof(struct numlist), GFP_KERNEL);//void *kmalloc(size_t size, int flages)//分配内存size 要分配内存大小flags 内存类型listnode-num i1;list_add_tail(listnode-list, numhead.list);printk(Node %d has added to the doublelist...\n, i1);}//遍历链表i 1;list_for_each(pos, numhead.list) {p list_entry(pos, struct numlist, list);printk(Node %ds data: %d\n, i, p-num);i;}return 0;}static void __exit doublelist_exit(void){struct list_head *pos, *n;struct numlist *p;int i;//依次删除N个结点i 1;list_for_each_safe(pos, n, numhead.list) {//为了安全删除结点而进行的遍历list_del(pos); //从链表中删除当前结点p list_entry(pos, struct numlist, llist);//得到当前数据结点的首地址即指针kfree(p); //释放该数据结点所占空间printk(Node %d has removed from the doublelist...\n, i);}printk(doublelist is exiting...\n);}module_init(doublelist_init);module_exit(doublelist_exit);参考资料Linux操作系统原理与应用(第2版) 陈莉君、康华 编著