
一、开篇
上一节我们说了链表的初始化、增删查,那么怎么用呢?这里刨个坑,我们先给出示例之后再来说变态的container_of,因为我们要获取链表节点对应的数据域就是通过它获取的。
二、示例
/*** @file test_list.c* @brief 内核链表测试* @author zshare* @version v1.0* @date 2022-02-16* @history*/#include <linux/module.h>//对应内核源码中include/linux/module.h#include <linux/moduleparam.h>#include <linux/kernel.h>#include <linux/init.h> 包含了module_init和module_exit的声明#include <linux/cdev.h> 包含字符设备操作函数#include <linux/fs.h> 包含文件接口操作函数#include <linux/uaccess.h>#include <asm/atomic.h>#include <linux/slab.h>#define _log_#ifdef _log_#define kernel_print(format, arg...) printk(format,## arg)#else#define kernel_print(format, arg...) do{}while(0)#endif#define VERSION "V1.0"typedef unsigned char u8;typedef unsigned short u16;typedef unsigned int u32;#define nil NULL#define FALSE 1#define TRUE 0#define pcalloc(x,size,type) do{ if((x = (type *)kcalloc(1,size,GFP_KERNEL)) == nil){ return FALSE; } }while(0)#define pfree(ptr) do{ if(ptr != nil) { kfree(ptr); } ptr = nil; }while(0)//一个身份节点typedef struct {u32 id;//成员idu8 name[16];//成员名字u8 text[32];//成员hash标识struct list_head node;//定义一个链表节点}id_st;u32 init_id_node(u8 *name, u8 *text, id_st **pid){static u32 id = 0;id_st *ptmp = nil;申请一个身份节点pcalloc(ptmp, sizeof(id_st), id_st);给节点赋值ptmp->id = ++id;memcpy(ptmp->name, name, 16);memcpy(ptmp->text, text, 31);初始化链表节点INIT_LIST_HEAD(&ptmp->node);(*pid) = ptmp;return 0;}//打印链表void print_list(const struct list_head *plist){id_st *pos = nil;do{if(list_empty(plist)){ kernel_print("\t链表为空!\n"); break; }//对链表进行遍历操作并打印数据域list_for_each_entry(pos, plist, node){kernel_print("\t[%d]:%s,%s.\n", pos->id, pos->name, pos->text);}}while(0);}static int __init tlist_init(void){int ret = -1;id_st *a = nil;id_st *b = nil;id_st *c = nil;//定义一个身份链表struct list_head id_list;//初始化3个身份节点,分别是A,B,Cret = init_id_node("AAAAAAAAAAAAAAA", "a hash value", &a);ret = init_id_node("BBBBBBBBBBBBBBB", "b hash value", &b);ret = init_id_node("CCCCCCCCCCCCCCC", "c hash value", &c);/*==========链表测试开始==========*///初始化链表INIT_LIST_HEAD(&id_list);//将三个节点采用头插插入链表list_add(&a->node, &id_list);list_add(&b->node, &id_list);list_add(&c->node, &id_list);//打印kernel_print("插入三个成员后:\n");print_list(&id_list);//删除b节点再打印list_del(&b->node);//再打印kernel_print("删除b成员后:\n");print_list(&id_list);//注意需要释放掉删除的节点pfree(b);//删除a节点再打印list_del(&a->node);//再打印kernel_print("删除a成员后:\n");print_list(&id_list);//注意需要释放掉删除的节点pfree(a);//删除c节点再打印list_del(&c->node);//再打印kernel_print("删除c成员后:\n");print_list(&id_list);//注意需要释放掉删除的节点pfree(c);return ret;}static void __exit tlist_exit(void){}module_init(tlist_init);module_exit(tlist_exit);MODULE_LICENSE("GPL");//软件代码接受的许可协议General Public LicenseMODULE_AUTHOR("Share");//声明作者MODULE_DESCRIPTION("A test list module");//模块简单的描述MODULE_VERSION(VERSION);//模块版本MODULE_ALIAS("tlist");//模块在用户空间的别名

我们来通过dmesg来查看结果是否和我们程序设计的结果一样。

文章转载自囧囧妹,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




