Linux内核链表详细分析

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)链表删除操作

扫描二维码关注公众号,回复: 1690007 查看本文章

/**
 * 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


猜你喜欢

转载自blog.csdn.net/xiezhi123456/article/details/80755194