linux驱动开发--内核链表

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值