1、内核链表定义
在<linux/list.h>中定义
struct list_head{
struct list_head *next, *prev;
};
在list_head结构中包含两个指向list_head结构的指针next和prev,在实际使用中,它通常被组织成双向循环链表。
内核链表结构体不包含数据域,只包含维护链表的指针域。
内核链表被包含在其他数据结构体中使用。
初始化链表头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、实例代码:
/**
*Copyright (c) 2013.TianYuan
*All rights reserved.
*
*文件名称: listtest.c
*文件标识: 内核链表的使用
*
*当前版本:1.0
*作者:wuyq
*
*取代版本:xxx
*原作者:xxx
*完成日期:2013-11-18
*/
#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;/*list_for_each*/
struct employee *employee_tmp = NULL;
static int __init listtest_init(void)
{
int i = 0;
/*初始化链表头节点*/
INIT_LIST_HEAD(&employee_list);
/*申请employee空间*/
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);
/*初始化每个struct*/
for(i=0; i<EMPLOYEE_NUM; i++){
sprintf(employeep[i].name, "employee%d", i);
/*true*/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