昨天初步学习了linux内核链表,记录一下
首先要先知道结构体的一个很隐秘的知识点,如下:
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
typedef struct Worker
{
char name[30];
int nNumber;
};
int main()
{
struct Worker* pworker = NULL;
char* name;
char s;
int nNumber;
int pNum;
// 下面两行不会崩溃,因为->是取地址符,只是获取相对于结构体其实地点的偏移量,且pNum = 32;
// 多扯一点,为什么会是32二不是三十呢,因为c++编译器是四字节整体分配内存的,不满四字节按四字节分配,不信的可以自己试一下
name = pworker->name;
pNum = &(pworker->nNumber);
// 对于上面两行即使这样写也是可以的,根上面的效果一样的,
// Linux内核有个宏就是这样写的 #define offsetof(s,m) (size_t)&(((s *)0)->m),求取偏移地址
name = ((struct Worker*)0)->name;
pNum = &(((struct Worker*)0)->nNumber);
// 下面两行会崩溃,因为直接去读取非法内存值
s = name[0];
nNumber = pworker->nNumber;
return 0;
}
有了这个基础就可以理解Linux内核链表了
typedef struct _tag_LinkListNode
{
struct _tag_LinkListNode* next;
}LinkListNode;
typedef struct _Teacher
{
char name[32];
int age ;
// 可以通过上面介绍的方法求出node相对于结构体其实位置的偏移地址
// 相反的,是不是如果我知道node的地址后就可以根据偏移地址来求结构体的起始地址了
LinkListNode node;
}Teacher;
那么下面我们就可以创建一个node的链表,然后将
Teacher插入到链表内。
传统链表是将链表操作和业务混合到一块了,如下图
Linux链表则实现了分离,如下图
我们可以向pHead中添加Teacher节点
我们可以将创建的Teacher中的LinkListNode的首地址添加打pHead,然后在对链表操作的时候看一通过偏移地址来找到具体的结构体,当然有个比较方便的方法,那就是将LinkListNode node放在结构体的第一位,这样偏移量是0,他们的地址就重合和,会省去很多麻烦的操作。
感觉这种链表就好比给针穿线,链表相当于线,结构体相当于针,每个结构体都有一个针孔,用线把他们传串到一起