Linux内核源码中的双链表结构(笔记)

news/2025/1/11 20:01:50/

双向链表是Linux中非常重要和基础的一个数据结构,它在Linux内核中是一个基本类型

Linux内核中的链表

一个常见的双向链表可以被定义为

struct my_list{void *mydata;struct my_list *next;Cstruct my_list *prev;
};

不同的使用方法会构造出不同的数据结构

  • 先进先出是队列
  • 只对后继操作是栈
  • 两个节点指向子树就是二叉树

链表基本功能的实现

定义

Linux中的链表定义为:

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

在linux/list.h中有链表的声明和初始化的宏

#define LIST_HEAD_INIT(name) { &(name), &(name) }#define LIST_HEAD(name) \struct list_head name = LIST_HEAD_INIT(name)

判空

/*** list_empty - tests whether a list is empty* @head: the list to test.*/
static inline int list_empty(const struct list_head *head)
{return head->next == head;
}

非常简单清晰,判断head的next是否指向head本身即可。

插入

/** Insert a new entry between two known consecutive entries.** This is only for internal list manipulation where we know* the prev/next entries already!*/
#ifndef CONFIG_DEBUG_LIST
static inline void __list_add(struct list_head *new,struct list_head *prev,struct list_head *next)
{next->prev = new;new->next = next;new->prev = prev;prev->next = new;
}
#else
extern void __list_add(struct list_head *new,struct list_head *prev,struct list_head *next);
#endif

这里主要是提供了一个默认的实现方式,或者通过extern实现也行。
默认的方式很简单清晰,就是分别将prev的后继指向new,next的前驱指向new,new的前驱和后继分别指向prev和next。

遍历

Linux中通过定义一个宏来实现遍历

/*** list_for_each	-	iterate over a list* @pos:	the &struct list_head to use as a loop cursor.* @head:	the head for your list.*/
#define list_for_each(pos, head) \for (pos = (head)->next; pos != (head); pos = pos->next)

定位

找到节点的位置如何定位到该节点呢?
linux提供了一个定位的宏

/*** list_entry - get the struct for this entry* @ptr:	the &struct list_head pointer.* @type:	the type of the struct this is embedded in.* @member:	the name of the list_struct within the struct.*/
#define list_entry(ptr, type, member) \container_of(ptr, type, member)

这里用container_of对宏进行了封装, 本体应该是这样的:

#define list_entry(ptr, tpye, member) \ ((type*)((char*)(ptr) - (unsigned long)(&((type*)0)->member)))

这个实现的功能就是,获得ptr的位置,然后减去member的偏移量,就可以得到该节点的起始地址了,就可以对节点进行操作,而不只单纯的对节点内部的某一成员进行操作。

删除

双向节点的删除操作

/** Delete a list entry by making the prev/next entries* point to each other.** This is only for internal list manipulation where we know* the prev/next entries already!*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{next->prev = prev;prev->next = next;
}/*** list_del - deletes entry from list.* @entry: the element to delete from the list.* Note: list_empty() on entry does not return true after this, the entry is* in an undefined state.*/
#ifndef CONFIG_DEBUG_LIST
static inline void __list_del_entry(struct list_head *entry)
{__list_del(entry->prev, entry->next);
}static inline void list_del(struct list_head *entry)
{__list_del(entry->prev, entry->next);entry->next = LIST_POISON1;entry->prev = LIST_POISON2;
}
#else
extern void __list_del_entry(struct list_head *entry);
extern void list_del(struct list_head *entry);
#endif

外部调用list_del函数,传入一个entry的指针,让该entry的前驱和后继相互指向,本身置空。

大道至简,linux中的双链表定义非常简单,无需畏难。之后的很多数据结构都需要基于双链表进行构造。

参考资料

  • 学堂在线-Linux内核分析与应用:https://next.xuetangx.com/course/XIYOU08091001441/14767915

http://www.ppmy.cn/news/83654.html

相关文章

不会写代码也能做自动化?推荐一款自动化测试神器

在软件测试这条道路上,大部分的职业技能发展道路都会是纯业务手工测试→自动化测试→性能测试→安全测试/测试开发。 但是却有着一部分人起初进入软件测试这一行看重的就是软件测试属于IT行业,门槛比较低,不需要代码基础。 这就导致了这一部…

从零搭建Jenkins并自动发布Java项目

公众号请关注"果酱桑", 一起学习,一起进步! 目录 准备工作 安装Jenkins 配置Jenkins 配置Maven 配置Git 配置Tomcat 创建Jenkins Job 构建并部署应用程序 总结 Jenkins是一款流行的开源CI/CD工具,它可以帮助我们自动化构建、测试和部署我们的应用…

技术干货 | 在 PostgreSQL 中设置查询超时

在 Navicat Monitor 3 监控工具中的查询分析器画面顶部,我们设置了一个图表,用以显示等待时间最长的查询: 能够标识出滞后的查询非常重要,因为它们可以让一切陷入瘫痪。 除了在标识出慢速查询并对其进行修复外,另一种…

湍流的数值模拟方法概述

湍流,又称紊流,是一种极其复杂、极不规则、极不稳定的三维流动。湍流场内充满着尺度大小不同的旋涡,大旋涡尺度可以与整个流畅区域相当,而小漩涡尺度往往只有流场尺度千分之一的数量级,最小尺度旋涡的尺度通过其耗散掉…

Matlab论文插图绘制模板第94期—带置信区间的折线散点图

在之前的文章中,分享了很多Matlab带置信区间的折线图的绘制模板: 进一步,再来分享一下带置信区间的折线散点图的绘制模板。 先来看一下成品效果: 特别提示:本期内容『数据代码』已上传资源群中,加群的朋友…

day06 Spring AOP

DI注解 **作用:**解决使用xml配置繁琐的问题 该注解和使用配置文件一样分成两类进行注入:字段注入或属性注入,注入bean(取代xml中的ref) 1.value注解 使用value注解给属性进行赋值,只能使用于八大基本类型和常量类型/String/Integer… value("小小") private St…

AI 图像编辑技术 DragGAN 问世,用户可以通过拖拽改变汽车大小或人物表情等

🚀 AI 图像编辑技术 DragGAN 问世,用户可以通过拖拽改变汽车大小或人物表情等 近日,马克斯・普朗克计算机科学研究所研究者们推出了一种控制GAN的新方法DragGAN,用户可以通过拖拽改变汽车大小或人物表情等。 DragGAN类似于Photo…

Android抖音游戏sdk激励视频广告接入问题

广告初始化报错:code-2 msgInvalid app id [] 在穿山甲申请的appid和codeid,需要在抖音游戏提交申请。具体请联系抖音技术或商务。