1、内核链表定义
在<Linux/list.h>中定义
- struct list_head{
- struct list_head *next, *prev;
- };
在list_head结构中包含两个指向list_head结构的指针next和prev,在实际使用中,它通常被组织成双向循环链表。
内核链表结构体不包含数据域,只包含维护链表的指针域。
内核链表被包含在其他数据结构体中使用。
![](https://img-blog.csdn.net/20131226154359437)
初始化链表头INIT_LIST_HEAD函数
void INIT_LIST_HEAD(struct list_head *list);
list:待初始化链表头
插入节点list_add函数
void list_add(struct list_head *new, struct list_head *head);
void list_add_tail(struct list_head *new, struct list_head *head);
new:待插入到链表的新节点
head:待插入到链表的链表头
删除节点list_del函数
void list_del(struct list_head *entry);
entry:待删除的节点
提取数据结构list_entry宏
#define list_entry(ptr, type, member) container_of(ptr, type, member)
ptr:当前链表节点指针
type:包含该链表的数据结构体类型
member:在数据结构体类型中的list_head成员名称
返回:获取的数据结构体指针
实际是通过已知数据结构体中链表节点指针ptr,获取包含该链表节点的数据结构体指针
遍历链表list_for_each宏
#define list_for_each(pos, head) for(pos = (head)->next; prefetch(pos->next), pos != (head); pos = pos->next)
#define list_for_each_safe(pos, n, head) for(pos = (head)->next, n= pos->next; pos !=(head); pos = n, n = pos->next)
pos:list_head指针类型的循环变量
n:list_head指针类型的循环变量
head:待遍历链表的链表头
2、实例代码:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/err.h>
- #include <linux/slab.h>
- #include <linux/list.h>
-
- MODULE_LICENSE("GPL");
-
- #define EMPLOYEE_NUM 10
-
- struct employee
- {
- char name[20];
- int id;
- int salary;
- int age;
- struct list_head list;
- };
-
-
- struct list_head employee_list;
- struct employee *employeep = NULL;
- struct list_head *pos = NULL;
- struct employee *employee_tmp = NULL;
- static int __init listtest_init(void)
- {
- int i = 0;
-
-
- INIT_LIST_HEAD(&employee_list);
-
-
- employeep = kmalloc(sizeof(struct employee)*EMPLOYEE_NUM, GFP_KERNEL);
- if(IS_ERR(employeep)){
- printk("kmalloc failed!\n");
- return -ENOMEM;
- }
- memset(employeep, 0, sizeof(struct employee)*EMPLOYEE_NUM);
-
- for(i=0; i<EMPLOYEE_NUM; i++){
- sprintf(employeep[i].name, "employee%d", i);
- sprintf((employeep+i)->name, "employee%d", i);
- employeep[i].id = 10000 + i;
- employeep[i].salary = 10000 + 1000*i;
-
- list_add(&(employeep[i].list), &employee_list);
- }
-
- list_for_each(pos, &employee_list){
- employee_tmp = list_entry(pos, struct employee, list);
- printk("employee name :T=%s\tID:%d\tSalary:%d!\n",
- employee_tmp->name,
- employee_tmp->id,
- employee_tmp->salary);
- }
-
- return 0;
- }
-
- static void __exit listtest_exit(void)
- {
- int i = 0;
- for(i=0; i<EMPLOYEE_NUM; i++){
- list_del(&(employeep[i].list));
- }
-
- kfree(employeep);
- }
-
- module_init(listtest_init);
- module_exit(listtest_exit);
- KERNELDIR ?=/root/Desktop/work/ldd3/linux-2.6.31_TX2440A
- PWD := $(shell pwd)
- obj-m += listtest.o
-
- default:
- $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
-
- clean:
- @rm -f *.o *.ord* *.sy* *.mod.* *.ko