linux内核链表应用--笔记

Windows 应用linux内核链表

一、从网上现在linux kernel代码

linux内核版本有2种: 稳定版(次版本为偶数),开发版(次版本为奇数)
版本号: 主版本.次版本.释出版本-修改版本

内核下载连接网站:https://www.kernel.org/

下载内核版本:4.19.144
压缩文件大小:98.64MB

内核代码查看使用软件:Source Insight 4.0
Winddow软件平台:VS2019

二、关键文件

要进行移植的文件路径:

/linux-4.19.144/include/list.h

list.h文件里面定义了几个头文件,虽然这些定义的文件于list.h什么关系还不清楚,但可以一个一个清除跟他们之间的关系。换句话说,要从这些定义头文件里面复制相关代码出来,并加以修改。

#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/poison.h>
#include <linux/const.h>
#include <linux/kernel.h>

三、修改list.h头文件

1、/include/linux/types.h文件中找到有关链表的相关定义,代码拷贝下来

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

struct hlist_head {
    struct hlist_node* first;
};

struct hlist_node {
    struct hlist_node* next, ** pprev;
};

2、list.h中不需要调试链表,所以删除了预编译定义 #ifdef CONFIG_DEBUG_LIST#else 里面相关代码,只保留了 #else#endif 里面代码。

3、如果用C++语言编写,new会成为关键字,修改成newStruct

4、list.h中的宏定义WRITE_ONCE它的定义路径在

/tool/virtio/linux/compiler.h

5、进行第一次编译。。。发生了未定义NULL,在此出引用Windows.h头文件,用这个头文件的原因是我在Windows10平台下写的代码,应当遵循这个平台下的文件代码(有兼容作用)。

它里面是这样定义,当然也可以自己手动这样定义NULL,也可以添加头文件stdio.h这样不用声明这个NULL

#define NULL 0

6、第二次编译还是出现了大量的报错问题,一共三种报错,如下。


| 严重性| 代码|说明| 项目| 文件|行|禁止显示状态
| 错误 | C3861 |“typeof”: 找不到标识符 | list | E:\VS\list\list.h | 53 |
| 警告 | C4197| “volatile int”: 忽略强制转换中的顶级 volatile 变量 | list |E:\VS\list\list.h| 53|
| 错误(活动) | E0260 | 缺少显式类型(假定“int”) | list |E:\VS\list\list.h| 53|


主要还是复制过来的代码出现问题,慢慢分解这个代码修改前

#define WRITE_ONCE(var, val) \
	(*((volatile typeof(val) *)(&(var))) = (val))

#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var))))

C++不支持typeof() 这个东西,没办法获取获取变量类型,比如typeof(val),如果传入是无符号字节,那么它就会等效成unsigned char,为了解决不兼容这个问题,我们使用C11标准的 delctype() 来获取就可以了。

代码修改后

#define WRITE_ONCE(var, val) \
	(*((volatile decltype(val) *)(&(var))) = (val))

#define READ_ONCE(var) (*((volatile decltype(var) *)(&(var))))

7、C++编译器不支持 ({ }) 形式 ,这个要修改 , 然后为防止重复offsetof重复用宏定义,offsetof改为offsetof2;
代码修改后:

#define offsetof2(TYPE, MEMBER)	((size_t)&((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) \
	(type *)( (char *)(ptr) - offsetof2(type,member))

四、移植完成后应用测试代码验证

#include "list.h" //移植后头文件名称
#include <iostream>

using namespace std;

struct student
{
	char name[60]; //学生名字
	int id;	//学生id号
	struct list_head list;//链表
};

int main(void)
{
	struct student *q;
	struct student *p;
	
	struct student A = { "Jack" ,1, LIST_HEAD_INIT(A.list) };//初始化变量
	struct student B = { "Pink" ,2, LIST_HEAD_INIT(B.list) };//初始化变量

	list_add(&B.list, &A.list);//添加到链表中

	//通过子变量获取父变量的地址
	q = container_of(&A.list, struct student , list);

	//查看q指向的下一个成员变量获取父变量的地址
	p = container_of(q->list.next, struct student , list);
	cout<<"name: "<<p->name<<endl;
	cout <<"id :"<< p->id << endl;

	//查看q指向的下一个的下一个成员变量获取父变量的地址
	p = container_of(q->list.next->next, struct student, list);
	cout << "name: " << p->name << endl;
	cout << "id :" << p->id << endl;

	//查看q指向的下一个的下一个的下一个成员变量获取父变量的地址
	p = container_of(q->list.next->next->next, struct student, list);
	cout << "name: " << p->name << endl;
	cout << "id :" << p->id << endl;

	return 0;
}

上面代码运行效果如下图所示。
在这里插入图片描述

Linux平台上应用linux内核链表

一、代码示例

下面代码也是在内核中参考应用得的

#include "list.hpp" //移植后头文件名称
#include <stdlib.h>
#include <stdio.h>

struct student
{
	int id;	//学生id号
	struct list_head list;//链表
};

int main(void)
{
	struct student *p,*t;
	struct student list_test;

	list_test.id = 333;
	t = &list_test;

	//初始化首个数据
	INIT_LIST_HEAD(&t->list);
	//列表是否为空?
	printf("队列是否为空?:%u\n",list_empty(&t->list));
	//生成10个学生ID
	for (int i = 0; i < 10; i++)
    {
        p = (struct student *)malloc(sizeof(struct student));
        INIT_LIST_HEAD(&p->list);
		//赋值一个ID
        p->id = i;
		//将数据添加到列表后面
        list_add_tail(&p->list, &list_test.list);
    }
    
	//列表是否为空?
	printf("队列是否为空?:%u\n",list_empty(&t->list));
	//遍历所有数据
	printf("list_for_each_entry :\n");
    list_for_each_entry(p, &t->list, list) {
        printf("%d\n",p->id);
    }

	//倒序遍历所有数据
	printf("list_for_each_entry_reverse :\n");
    list_for_each_entry_reverse(p, &t->list, list)
    {
        printf("%d\n",p->id);
    }

	struct student *a,*n;
	//删除所有数据,并释放内存空间
	list_for_each_entry_safe(a, n, &t->list, list) {
		printf("a:%d\n",a->id);
		printf("n:%d\n",n->id);
		list_del(&a->list);
		free(a);
	}

    return 0;
}

运行效果如下:
在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值