Linux内核链表原理

Linux内核链表???
难道普通的链表不满足?,当然满足了 但是感觉缺少点对链表深刻了解的过程
普通链表结点 数据域 and 指针域
Lnux内核链表结点 指针域 只有指针域 那怎么放数据呢??
通过结构体定义 链表结点元素 数据1,数据2… 数据n-1 定义多少个数据都可以 ,但是最后一个必须 为Lnux内核链表结点 变量或者指向堆内存空间 的指针
首先分析一下 为啥使用Linux内核链表
生活当中的 汽车和客车和高铁 民用客机,他们有一个共同的 特征:座椅 所谓的座椅 就是这些民用汽车和客车 高铁 民用客机就是这些 数据 也就是普通链表 货车 运煤炭的火车车箱底部是空的 就可以载人 或许有一定的危险性 开快了会直接 哦呐呐呐+ 黑人抬棺BGM …脑补一下画面,
这些最好是拿来运一些煤炭,或者放一些集装箱 之类的 这有那个装箱子
, 这些就是底盘 数据放在另一个结构体里方便数据操作

  • 看看大概的样子
  • 大块的矩形 — 数据
  • 两个合成的矩形 — 结点
  • 这要包含这个小结点 就能访问 小结点 上面对的数据

Lnux内核链表结点变量

直接上C/C++ 代码

#include<iostream>
using namespace std;

//Linux 共享 双向链表结点
using LinkNode = struct __DoubleLinkNode;

//Linux 共享 双向链表结点
struct __DoubleLinkNode {

	LinkNode* prev;
	LinkNode* next;
};

//Linux 共享 双向链表
struct __DoubleLinkList {
	LinkNode *List;
	size_t size;	
};

struct Student{
	char name[14];
	int age;
};

struct LinkElem{

	
	Student s;
	LinkNode node;
	
};

using LinkList = __DoubleLinkList;


void  initLinkList(LinkList& List,  LinkNode * const initList=nullptr) {

	List.List = new LinkNode{ initList, initList };
		
	List.size = 0u;
}

void Link(LinkNode*& node, LinkNode*& newnode) {

	if (node->next) {

		node->next->prev = newnode;
		newnode->next = node->next;
	}
	newnode->prev = node;
	node->next = newnode;
}

void LinkListInsert_back(LinkList& List, LinkNode*& Newnode) {

	LinkNode* current = List.List;
	while (current->next) {

		current = current->next;
	}

	Link(current, Newnode);
	++List.size;
}

void LinkListDestroy(LinkList& List) {

	LinkNode* &iter = List.List;
	LinkNode*& iterNext = iter->next = iter->next->next = iter->next->prev = nullptr;
	
	delete iter;
	iter = iterNext=nullptr;

		
	List.size = (size_t)iter;
}


LinkElem* CreatorLinkElem(const size_t& size) {
	return  new LinkElem[size];
}

void LinkElemDestroy(LinkElem*&e) {

	
		delete[] e;
		e = nullptr;

}

int main(void) {
	
	
	LinkList List;
	
	initLinkList(List);

	size_t LinkElemArraySize = 26;
	LinkElem* e = nullptr;

	const char studentName[] = "ABCDEFGHIJKLMNOPQRTUVWXYZ\0";
	e = CreatorLinkElem(LinkElemArraySize);

	for (size_t i = 0; i < LinkElemArraySize; i++){
		
		strcpy_s(e[i].s.name, {"Student_"});

		strncat_s(e[i].s.name, &studentName[i], 1);

		const int age = LinkElemArraySize - 3;
		e[i].s.age = age % 18 + 13;
		e[i].node = LinkNode{nullptr};
		LinkNode*node =&e[i].node;

		LinkListInsert_back(List, node);
	}

	LinkNode* current = List.List->next;
	const size_t LinkElemNodeoffset = offsetof(LinkElem, node);

	while ((  current)->next){

		LinkElem*&& elemvalue = (LinkElem*)((size_t)current - (size_t)LinkElemNodeoffset);
		cout << " 学生姓名:" << elemvalue->s.name << "\t学生年龄:" << elemvalue->s.age << endl;

		current = (current)->next;
	}

	LinkElemDestroy(e);
	LinkListDestroy(List);

		
	return 0;
}

源码解析:
offsetof(LinkElem, node); 求node 在这个结构体偏移量
首先说明一下: 栈和堆 只要是顺序的内存空间都可以做链接成链表 ,不是顺序无法找到偏移量 栈是可以的找到偏移量 ,堆就不可行

根据偏移量 找到的node结点 访问数据

在这里插入图片描述
Lnux内核链表结点指针

#include<iostream>
using namespace std;

//Linux 共享 双向链表结点
using LinkNode = struct __DoubleLinkNode;

//Linux 共享 双向链表结点
struct __DoubleLinkNode {

	LinkNode* prev;
	LinkNode* next;
};

//Linux 共享 双向链表
struct __DoubleLinkList {
	LinkNode *List;
	size_t size;	
};

struct Student{
	char name[32];
	int age;

};
struct LinkElem{

	
	Student s;
	LinkNode *node;
	
};

using LinkList = __DoubleLinkList;


void  initLinkList(LinkList& List,  LinkNode * const initList=nullptr) {

	List.List = new LinkNode{ initList, initList };
		
	List.size = 0u;
}

void Link(LinkNode*& node, LinkNode*& newnode) {

	if (node->next) {

		node->next->prev = newnode;
		newnode->next = node->next;
	}
	newnode->prev = node;
	node->next = newnode;
}

void LinkListInsert_back(LinkList& List, LinkNode*& Newnode) {

	LinkNode* current = List.List;
	while (current->next) {

		current = current->next;
	}

	Link(current, Newnode);
	++List.size;
}

void LinkListDestroy(LinkList& List) {

	LinkNode* &iter = List.List;
	LinkNode* iterNext = iter->next;
	delete iter;
	iter = iterNext;
	while (iter){
		iterNext = iter->next;
		iter->prev = nullptr;
		iter->next = nullptr;
		iter = iterNext;
	}
	iter = nullptr;
	
	List.size = (size_t)iter;
}


LinkElem* CreatorLinkElem(const size_t& size) {
	return  new LinkElem[size];
}

void LinkElemDestroy(LinkElem*& e) {

	delete[] e;
	e = nullptr;
}

int main(void) {
	
	
	LinkList List;
	
	initLinkList(List);

	size_t LinkElemArraySize = 26;
	LinkElem* e = CreatorLinkElem(LinkElemArraySize);

	const char studentName[] = "ABCDEFGHIJKLMNOPQRTUVWXYZ";

	for (size_t i = 0; i < LinkElemArraySize; i++){
		
		strcpy_s(e[i].s.name, { "Student_" });

		strncat_s(e[i].s.name, &studentName[i], 1);

		const int age = LinkElemArraySize;
		e[i].s.age = age % 18+13;
		e[i].node = new LinkNode;
		cout << "node 分配的地址为 " << e[i].node << endl;
		e[i].node->prev = nullptr;
		e[i].node->next = nullptr;
	}
	
	for (size_t i = 0; i < LinkElemArraySize; i++) {
		LinkNode*node = (e + i)->node;
		LinkListInsert_back(List, node);
	}


	LinkNode* current = List.List->next;
	size_t i = 0;
	while (current-?next){
		const LinkElem* eptr = e + i;
		//获取node 偏移量
		const size_t LinkElemNodeoffset = ((size_t)current - (size_t)eptr);

		LinkElem* elemvalue = (LinkElem*)((size_t)current - LinkElemNodeoffset);
		cout << " 学生姓名:" << elemvalue->s.name << "\t学生年龄:" << elemvalue->s.age << endl;
		++i;
		current = current->next;
	}
	LinkListDestroy(List);
	LinkElemDestroy(e);
		
	return 0;
}

注意事项:栈和堆 只要是顺序的内存空间都可以做链接成链表 ,不是顺序无法找到偏移量 栈是可以的找到偏移量 ,
堆就不可行

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小森程序员

若能帮助到你,小费自愿付费

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值