Linux 内核链表使用举例

链表数据结构的定义非常简洁:

struct list_head { 
    struct list_head *next, *prev;
}; 

list_head结构包括两个指向list_head结构的指针prev和next。该内核链表具备双链表功能。通常它都组织成双循环链表,这里的list_head没有数据域。在Linux内核链表中,不是在链表结构中包括数据,而是在数据结构中包括链表节点。以下是一个简单的内核模块的样例。包括了对链表进行插入、删除、遍历的一些函数:

list.c:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/list.h>

typedef struct list_test_struct {
        int num;
        struct list_head list;
}test;

struct list_head head_list;
rwlock_t list_lock = RW_LOCK_UNLOCKED;   //定义读写锁,操作前加锁,操作后解锁

void creat_list(void)
{
        test *s = NULL;
        int  i = 0;
        for (i = 0; i < 10; i++) 
        {
                s = (test *)kmalloc(sizeof(test), GFP_ATOMIC);
                if (!s) return ;
                s->num = i;
                write_lock(&list_lock);
                list_add_tail(&(s->list), &head_list);   //加入节点
                write_unlock(&list_lock);
        }
}

void del_data(void)
{
        test *s;
        struct list_head *p;

        write_lock(&list_lock);
        list_for_each(p, &head_list)          //遍历链表
        {
                s = list_entry(p, test, list);
                if (s->num == 4) 
                {
                        list_del(p);          //删除节点
                        write_unlock(&list_lock);
                        return ;
                }
        }
        write_unlock(&list_lock);
}

void print_list(void)
{
        test *s;
        struct list_head *p;
        read_lock(&list_lock);
        list_for_each(p, &head_list) 
        {
                s = list_entry(p, test, list);
                printk(KERN_INFO"%d
", s->num);
        }
        read_unlock(&list_lock);
}

int list_test_init(void)
{
        INIT_LIST_HEAD(&head_list);
        creat_list();
        print_list();
        del_data();
        print_list();
        return 0;
}

void list_test_exit(void)
{
	return;
}

MODULE_LICENSE("GPL");
module_init(list_test_init);
module_exit(list_test_exit);
Makefile:

obj-m	+= list.o

KERN_DIR = /usr/src/linux-headers-2.6.32-33-generic

all:
	make -C $(KERN_DIR) M=`pwd` modules 

clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order

make后生成module,获取超级用户权限后

insmod list.ko

然后输入命令:

cat var/log/messages

printk信息打印:

Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274551] 0
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274553] 1
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274555] 2
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274555] 3
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274556] 4
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274557] 5
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274558] 6
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274559] 7
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274559] 8
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274560] 9
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274561] 0
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274562] 1
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274563] 2
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274564] 3
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274564] 5
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274565] 6
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274566] 7
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274567] 8
Jun 20 16:26:01 wuwen-laptop kernel: [ 5490.274568] 9
第二次输出发现节点4被删除。在这里实现:

       list_for_each(p, &head_list)          //遍历链表
       {
                s = list_entry(p, test, list);
                if (s->num == 4) 
                {
                        list_del(p);          //删除节点
                        write_unlock(&list_lock);
                        return ;
                }
        }

原文地址:https://www.cnblogs.com/zhchoutai/p/7068840.html