1、头文件
include/linux/list.h
1)初始化链表头
static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
list->prev = list;
}
2)链表插入操作
#ifndef CONFIG_DEBUG_LIST
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;
}
#else
extern void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next);
#endif
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
}
3)链表删除操作
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
#ifndef CONFIG_DEBUG_LIST
static inline void __list_del_entry(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
}
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
#else
extern void __list_del_entry(struct list_head *entry);
extern void list_del(struct list_head *entry);
#endif
4)提取数据结构
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
4)遍历链表操作
/**
* list_for_each -iterate over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head:the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
2、实验
编写内核模块
1)完成节点的插入
2)完成链表的遍历
3)完成节点的删除(遍历时访问节点中的数据)
3、源代码文件
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/list.h>
#define PERSON_COUNT (5)
struct person {
char name[100];
int age;
struct list_head list;
};
struct list_head person_list;
struct person *p_person;
struct list_head *pos;
struct person *temp_person;
static int __init list_demo_init(void)
{
int ret;
int i;
INIT_LIST_HEAD(&person_list); // 初始化链表
p_person = (struct person *)kmalloc(sizeof(struct person) * PERSON_COUNT, GFP_KERNEL);
if(!p_person) {
ret = -ENOMEM;
pr_err("kmalloc failed for person!\n");
return ret;
}
memset(p_person, 0, sizeof(struct person) * PERSON_COUNT);
for(i = 0; i < PERSON_COUNT; i++){
sprintf(p_person[i].name, "Person%d", i + 1);
p_person[i].age = (i + 1) * 10;
list_add_tail(&(p_person[i].list), &person_list);
}
//遍历链表
list_for_each(pos, &person_list) {
temp_person = list_entry(pos, struct person, list); //提取数据结构
printk(KERN_INFO "name is %s, age is %d.\n", temp_person->name, temp_person->age);
}
printk(KERN_INFO "list_demo_init\n");
return 0;
}
static void __init list_demo_exit(void)
{
int i ;
if(p_person) {
for(i = 0; i < PERSON_COUNT; i++) {
list_del(&(p_person[i].list));
}
kfree(p_person);
p_person = NULL;
}
printk(KERN_INFO "list_demo_exit\n");
}
MODULE_LICENSE("GPL v2");
MODULE_VERSION("v1.0");
MODULE_DESCRIPTION("List Module");
MODULE_AUTHOR("XieZhi");
MODULE_ALIAS("List Module");
module_init(list_demo_init);
module_exit(list_demo_exit);
4、Makefile
ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
else
obj-m := list_demo.o
endif