struct node{
int key;
int val;
node* prev;
node* next;
}
struct list_head {
struct list_head *next, *prev;
};
struct node{
int val;
int key;
struct list_head* head;
}
//初始化头指针
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
//遍历链表
#define __list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
//获取节点首地址(不是list_head地址,是数据层节点首地址)
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
//container_of在Linux内核中是一个常用的宏,用于从包含在某个
//结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变
//量中某个成员的首地址进而获得整个结构体变量的首地址
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define offsetof(s,m) (size_t)&(((s *)0)->m)
typedef struct node{
int val;
int key;
struct list_head* list;
}node;
//初始化头指针
LIST_HEAD(head);
//创建节点
node* a = malloc(sizeof(node));
node* b = malloc(sizeof(node));
//插入链表 方式一
list_add(&a->list,&head);
list_add(&b->list,&head);
//插入链表 方式二
list_add_tail(&a->list,&head);
list_add_tail(&b->list,&head);
//遍历链表
struct list_head* p;
struct node* n;
__list_for_each(p,head){
//返回list_head地址,然后再通过list_head地址反推
//节点结构体首地址.
n = list_entry(pos,struct node,list);
}
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/list.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Xie");
MODULE_DESCRIPTION("List Module");
MODULE_ALIAS("List module");
struct student //代表一个实际节点的结构
{
char name[100];
int num;
struct list_head list; //内核链表里的节点结构
};
struct student *pstudent;
struct student *tmp_student;
struct list_head student_list;
struct list_head *pos;
int mylist_init(void)
{
int i = 0;
//初始化一个链表,其实就是把student_list的prev和next指向自身
INIT_LIST_HEAD(&student_list);
pstudent = kmalloc(sizeof(struct student)*5,GFP_KERNEL);//向内核申请5个student结构空间
memset(pstudent,0,sizeof(struct student)*5); //清空,这两个函数可以由kzalloc单独做到
for(i=0;i<5;i++)
{ //为结构体属性赋值
sprintf(pstudent[i].name,"Student%d",i+1);
pstudent[i].num = i+1;
//加入链表节点,list_add的话是在表头插入,list_add_tail是在表尾插入
list_add( &(pstudent[i].list), &student_list);//参数1是要插入的节点地址,参数2是链表头地址
}
list_for_each(pos,&student_list) //list_for_each用来遍历链表,这是个宏定义
//pos在上面有定义
{
//list_entry用来提取出内核链表节点对应的实际结构节点,即根据struct list_head来提取struct student
//第三个参数list就是student结构定义里的属性list
//list_entry的原理有点复杂,也是linux内核的一个经典实现,这个在上面那篇链接文章里也有讲解
tmp_student = list_entry(pos,struct student,list);
//打印一些信息,以备验证结果
printk("<0>student %d name: %s/n",tmp_student->num,tmp_student->name);
}
return 0;
}
void mylist_exit(void)
{
int i ;
/* 实验:将for换成list_for_each来遍历删除结点,观察要发生的现象,并考虑解决办法 */
for(i=0;i<5;i++)
{
//额,删除节点,只要传个内核链表节点就行了
list_del(&(pstudent[i].list));
}
//释放空间
kfree(pstudent);
}
module_init(mylist_init);
module_exit(mylist_exit);
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有