当前位置: 首页 > news >正文

Linux编程——经典链表list_head

1. 关于list_head

struct list_head是Linux内核定义的双向链表,包含一个指向前驱节点和后继节点的指针的结构体。其定义如下:

struct list_head {struct list_head *next, *prev; //双向链表,指向节点的指针
};

1.1 链表的定义和初始化

有两种方式来定义和初始化链表头:

  • 方法一:利用宏LIST_HEAD定义并初始化
  • 方法二:先定义,再利用宏INIT_LIST_HEAD初始化
//方法1:利用LIST_HEAD定义并初始化链表
static LIST_HEAD(registered_llhw); //方法2:先定义再初始化链表
struct list_head registered_llhw;  //定义一个链表(注册链路层hardware)
INIT_LIST_HEAD(&registered_llhw);  //初始化链表//相关宏定义如下:
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)#define LIST_HEAD_INIT(name) { &(name), &(name)}//即初始化后链表的nexth和prev都指向自己。
#define INIT_LIST_HEAD(ptr) do { \(ptr)->next = (ptr); \(ptr)->prev = (ptr); \
}while(0)

1.2 链表节点增/删

使用list_add/list_add_tail来添加链表节点。

list_add(&entry, &ListHead);//在head之后添加
static inline void list_add(struct list_head *new, struct list_head *head)
{__list_add(new, head, head->next);
}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;
}//添加到head之前,即链表的尾部增加
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{__list_add(new, head->prev, head);
}#ifdef CONFIG_ILLEGAL_POINTER_VALUE
# define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)
#else
# define POISON_POINTER_DELTA 0
#endif// 定义两个特殊的宏,将已经释放的节点指向这个位置,避免重复删除一个已经被释放的节点,避免出现潜在的漏洞。
// 实际上还起到用于标记已经删除节点的意义。
#define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA)
#define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA)// 从双向链表中删除一个节点
static inline void list_del(struct list_head *entry)
{__list_del_entry(entry);entry->next = LIST_POISON1;entry->prev = LIST_POISON2;//为什么不直接指向空指针NULL?在正常环境下,这个非空指针将会引起页错误。//可被用来验证没有初始化的链表节点。可以区分是被list删除的还是本身没有初始化的,便于调试。
}static inline void __list_del(struct list_head *prev, struct list_head *next)
{next->prev = prev;WRITE_ONCE(prev->next, next);
}static inline __list_del_entry(struct list_head *entry)
{if(!__list_del_entry_valid(entry))return;__list_del(entry->prev, entry->next);
}

1.3 遍历链表中节点

list_for_each_entry宏实际上是一个for循环,利用传入的pos作为循环变量,从表头head开始,逐项向后(next)移动pos,直到又回到head。

/*** list_for_each_entry - iterate over list of given type* @pos: the type * to use as a loop cursor* @head: the head for your list.* @member: the name of the list_struct within the struct*/
#define list_for_each_entry(pos, head, member) \for(pos = list_entry((head)->next, typeof(*pos), member); \prefetch(pos->member.netx), &pos->member != (head); \pos = list_entry(pos->member.next, typeof(*pos), member))// prefetch是告诉CPU哪些元素有可能马上要用到,预取一下,可以提高速度,用于预期以提高遍历速度// 从指针ptr中获取所在结构体类型type,并返回结构体指针。
// member是结构体中双向链表节点的成员名。注意,不能用于空链表和未初始化的链表。
/*** list_entry - get the struct for this entry* @ptr:  the &struct list_head pointer* @type: the type of the struct this is embeded in* @member: the name of the list_struct within the struct */
#define list_entry(ptr, type, member) container_of(ptr, type, member)//container_of用于根据一个结构体变量中的一个域成员变量的指针来获取指向整个结构体变量的指针/*** container_of - cast a member of a structrue out to the containing structure* @ptr:    the pointer to the member* @type:   the type of the container struct this is embeded in* @member: the name of the member within the struct*/
#define container_of(ptr, type, member) ({ \const typeof(((type *)0)->member )*__mptr = (ptr);(type *)((char *)__mptr - offsetof(type, member));  //得到结构体的地址,得到结构体指针})//强制将整型常量转换为TYPE型指针,指针指向的地址为0,也就是从0开始的一块存储空间映射为TYPE对象
//然后对MEMBER进行取地址,由于起始地址为0,也就获得MEMBER成员在TYPE中的偏移量,强制无符号整型
#define offsetof(TYPE, MEMBER)  ((size_t)&((TYPE *)0)->MEMBER)

提示:对于container_ofoffsetof宏,是Linux中常用的两个宏,用来处理结构体与结构体成员之间的指针转化。可以多加熟练与使用,在很多场景都可以得到应用。需要包含头文件<stddef.h>

相关文章:

Linux编程——经典链表list_head

1. 关于list_head struct list_head是Linux内核定义的双向链表&#xff0c;包含一个指向前驱节点和后继节点的指针的结构体。其定义如下&#xff1a; struct list_head {struct list_head *next, *prev; //双向链表&#xff0c;指向节点的指针 };1.1 链表的定义和初始化 有两…...

基于51单片机NEC协议红外遥控发送接收仿真设计( proteus仿真+程序+原理图+报告+讲解视频)

基于51单片机NEC协议红外遥控发送接收仿真设计 讲解视频1.主要功能&#xff1a;2.仿真3. 程序代码4. 原理图5. 设计报告6. 设计资料内容清单&&下载链接 基于51单片机NEC协议红外遥控发送接收仿真设计 51单片机红外发送接收仿真设计( proteus仿真程序原理图报告讲解视频…...

Jmeter分布式压力测试

目录 1、场景 2、原理 3、注意事项 4、slave配置 5、master配置 6、脚本执行 1、场景 在做性能测试时&#xff0c;单台机器进行压测可能达不到预期结果。主要原因是单台机器压到一定程度会出现瓶颈。也有可能单机网卡跟不上造成结果偏差较大。 例如4C8G的window server机…...

Rust :mod.rs和lib.rs中use的作用

一、mod.rs和lib.rs mod.rs往往是把同一目录下的n个rs文件综合在一起的有效方式&#xff1b; lib.rs是一个库或子库层次综合在一起的有效方式&#xff1b; 下面举个实例来说明。生成一个rusttoc本地库&#xff08;由cargo new rusttoc --lib所生成&#xff09;&#xff0c;目录…...

ISP图像信号处理——平场校正介绍以及C++实现

参考文章1&#xff1a;http://t.csdn.cn/h8TBy 参考文章2&#xff1a;http://t.csdn.cn/6nmsT 参考网址3&#xff1a;opencv平场定标 - CSDN文库 平场校正一般先用FPN(Fixed Pattern Noise)固定图像噪声校正,即暗场校正&#xff1b;再用PRNU(Photo Response Non Uniformity)…...

【深入了解Java String类】

目录 String类 常用方法 字符串的不可变性 String的内存分析 StringBuilder类 解释可变和不可变字符串 常用方法 面试题&#xff1a;String&#xff0c;StringBuilder&#xff0c;StringBuffer之间的区别和联系 String类的OJ练习 String类 【1】直接使用&#xff0c…...

基于SpringBoot的知识管理系统

目录 前言 一、技术栈 二、系统功能介绍 用户管理 文章分类 资料分类 文章信息 论坛交流 资料下载 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息互联网信息的飞速发展&#xff0c;无纸化作业变成了一种趋势&#xff0c;针对这个问题开发一个…...

Pytorch基础:Tensor的reshape方法

在Pytorch中&#xff0c;reshape是Tensor的一个重要方法&#xff0c;它与Numpy中的reshape类似&#xff0c;用于返回一个改变了形状但数据和数据顺序和原来一致的新Tensor对象。注意&#xff1a;此时返回的数据对象并不一定是新的&#xff0c;这取决于应用此方法的Tensor是否是…...

【数据库——MySQL】(13)过程式对象程序设计——存储函数、错误处理以及事务管理

目录 1. 存储函数2. 存储函数的应用3. 错误处理4. 抛出异常5. 事务处理6. 事务隔离级7. 应用实例参考书籍 1. 存储函数 要 创建 存储函数&#xff0c;需要用到 CREATE 语句&#xff1a; CREATE FUNCTION 存储函数名([参数名 类型, ...])RETURNS 类型[存储函数体]注意&#xff1…...

Spring Boot的魔法:构建高性能Java应用

文章目录 Spring Boot&#xff1a;简化Java开发Spring Boot的性能优势1. 内嵌服务器2. 自动配置3. 起步依赖4. 缓存和优化5. 异步处理 实际示例&#xff1a;构建高性能的RESTful API总结 &#x1f389;欢迎来到架构设计专栏~Spring Boot的魔法&#xff1a;构建高性能Java应用 ☆…...

如何做好测试?(七)兼容性测试 (Compatibility Testing, CT)

1. 兼容性测试介绍 兼容性测试 (Compatibility Testing, CT)是一种软件测试方法&#xff0c;旨在验证应用程序在不同操作系统、浏览器、设备和网络环境下的正确运行和一致性。对于网上购物系统来说&#xff0c;兼容性测试非常重要&#xff0c;因为用户可能使用各种不同的设备和…...

经典循环神经网络(一)RNN及其在歌词数据集上的应用

经典循环神经网络(一)RNN及其在歌词数据集上的应用 1 RNN概述 在深度学习兴起之前&#xff0c;NLP领域一直是统计模型的天下&#xff0c;例如词对齐算法GIZA&#xff0c;统计机器翻译开源框架MOSES等等。在语言模型方向&#xff0c;n-gram是当时最为流行的语言模型方法。n-gr…...

docker+mysql+flask+redis+vue3+uwsgi+docker部署

首先拉取mysql的镜像&#xff0c;这里用的mysql5.7.6 docker pull mysql:5.7.6 镜像拉取完成后启动&#xff1a; docker run --name my-mysql -d -p 3306:3306 -v /usr/local/my-mysql/conf:/etc/mysql/conf.d -v /usr/local/my-mysql/data:/var/lib/mysql -e MYSQL_ROOT_PA…...

Spring boot接收zip包并获取其中excel文件的方法

1、问题 工作中遇到一个需求&#xff0c;接收一个zip包&#xff0c;读取其中的excel文件并处理&#xff0c;减少用户多次选择目录和文件的痛点&#xff0c;该zip包包含多级目录 2、依赖 需要用到apache的Workbook类来操作Excel&#xff0c;引入以下依赖 <dependency>&l…...

Ubuntu镜像源cn.arichinve.ubuntu.com不可用原因分析和解决

文章目录 Ubuntu查看系统版本Ubuntu更新系统不能更新Ubuntu查看APT更新源配置cn.archive.ubuntu.com已经自动跳转到清华镜像站Ubuntu变更镜像源地址备份原文件批量在VIM中变更 Ubuntu国内镜像站推荐推荐阅读 今天想要在Ubuntu环境下搭建一个测试环境&#xff0c;进入Ubuntu系统…...

Java基础面试,String,StringBuffer,StringBuilder区别以及使用场景

简单的几句 String是final修饰的&#xff0c;不可变&#xff0c;每次操作都会产生新的对象。StringBuffer和StringBuilder都是在原对象上进行操作StringBuffer是线程安全的&#xff0c;StringBuilder是线程不安全的。StringBuffer方法是被synchronized修饰的 所以在性能方面大…...

基于SpringBoot的高校学科竞赛平台

目录 前言 一、技术栈 二、系统功能介绍 竞赛题库管理 竞赛信息管理 晋级名单管理 往年成绩管理 参赛申请管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步…...

excel如何让线条消失,直接设置网格即可,碰到不方便的地方优先百度,再采取蛮干

怎么将excel表格中的隐形线条去掉...

抖音短视频seo矩阵系统源代码开发系统架构及功能解析

短视频seo源码&#xff0c;短视频seo矩阵系统底层框架上支持了从ai视频混剪&#xff0c;视频批量原创产出&#xff0c;云存储批量视频制作&#xff0c;账号矩阵&#xff0c;视频一键分发&#xff0c;站内实现关键词、短视频批量搜索排名&#xff0c;数据统计分类多功能细节深度…...

在pycharm中弹出图后,需要关闭才会显示Process finished with exit code 0

在pycharm中弹出图后&#xff0c;需要关闭才会显示Process finished with exit code 0 在PyCharm中&#xff0c;当你运行一个Python程序并弹出一个图形窗口时&#xff0c;程序会等到图形窗口关闭后才会显示 “Process finished with exit code 0” 的消息。 这是 由于代码执行…...

【计算机网络笔记六】应用层(三)HTTP 的 Cookie、缓存控制、代理服务、短连接和长连接

HTTP 的 Cookie HTTP 的 Cookie 机制要用到两个字段&#xff1a;响应头字段 Set-Cookie 和请求头字段 Cookie。 Cookie 可以设置多个 key-value 对&#xff0c; 响应头中可以设置多个 Set-Cookie 字段&#xff0c;请求头Cookie后面可以设置多个键值对&#xff0c;用分号隔开&a…...

Vue中的数据分页与分页组件设计

Vue中的数据分页与分页组件设计 在前端开发中&#xff0c;数据分页是一个常见的需求&#xff0c;特别是当处理大量数据时。Vue作为一款流行的JavaScript框架&#xff0c;提供了强大的工具和生态系统来实现数据分页。本文将介绍如何在Vue中进行数据分页&#xff0c;以及如何设计…...

TCP串流场景剖析

在TCP&#xff08;传输控制协议&#xff09;中&#xff0c;串流场景指的是数据通过TCP连接以流&#xff08;stream&#xff09;的方式传输。TCP是一种可靠的、面向连接的传输协议&#xff0c;它将数据切分为多个报文段&#xff0c;通过网络传输&#xff0c;并在接收端进行重组&…...

Windows历史版本下载

1、微PE工具箱&#xff08;非广告本人常用&#xff09; 常用安装Windows系统的微PE工具 地址&#xff1a;https://www.wepe.com.cn/download.html 2、Windows系统下载地址&#xff08;非微软官方&#xff09; 地址&#xff1a;MSDN, 我告诉你 - 做一个安静的工具站 下载&…...

企业级磁盘阵列存储系统由硬到软全析

企业级磁盘阵列是由一组设备构成的存储系统,主要包括两种类型的设备,分别是控制器和扩展柜,其中控制器只有一台,扩展柜可以没有,也可以有多台。在EMC的Unity中分别称为DPE(Disk Processor Enclosure)和DAE(Disk Array Enclosure),在华为的OceanStor里面称为控制框和硬…...

V4L2 驱动架构介绍

V4L2 简介 Video for Linux two(Video4Linux2)简称 V4L2&#xff0c;是 V4L 的改进版。V4L2 是 linux操作系统下用于视频和音频数据采集设备的驱动框架&#xff0c;为驱动和应用程序提供了一套统一的接口规范。 在 Linux 下&#xff0c;所有外设都被看成一种特殊的文件&#xf…...

掌握这些技巧,让Excel批量数据清洗变得简单高效!

什么是数据清洗 数据清洗是指在数据处理过程中对原始数据进行筛选、转换和修正&#xff0c;以确保数据的准确性、一致性和完整性的过程。它是数据预处理的一部分&#xff0c;旨在处理和纠正可能存在的错误、缺失值、异常值和不一致性等数据质量问题。 为什么要数据清洗 Exce…...

成都瀚网科技:抖音上线地方方言自动翻译功能

为了让很多方言的地域历史、文化、习俗能够以短视频的形式生产、传播和保存&#xff0c;解决方言难以被更多用户阅读和理解的问题&#xff0c;平台正式上线推出当地方言自动翻译功能。创作者可以利用该功能&#xff0c;将多个方言视频“一键”转换为普通话字幕供大众观看。 具体…...

【k8s】【docker】web项目的部署

yaml配置文件 后端&#xff1a;springboot项目 前端&#xff1a;vue项目&#xff0c;之前镜像封装的nginx.conf反向代理配置直接使用了docker-compose.yml中services的名称&#xff0c;无法代理成功&#xff0c;可修改为127.0.0.1 # 后端 apiVersion: apps/v1 kind: Deployment…...

【视频去噪】基于全变异正则化最小二乘反卷积是最标准的图像处理、视频去噪研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

网站域名建设/seo按天计费系统

遇到的问题&#xff1a; 1、ionic打包完成项目在别人那里编译后可以运行&#xff0c;在我这里不行。2、其他内容显示都正常&#xff0c;只有从数据库中取出的内容不对&#xff0c;或者说没有数据显示。3、数据库是本地文件&#xff0c;文件格式正常。4、编译时警告找不到sqllit…...

案例中优衣库所采用的网络营销方式/关键词搜索优化公司

一个线程简单地被表示为可能呼叫程序中其它函数的函数。程序从其主线程开始执行&#xff0c;这个主执行绪是在传统的C程序中叫做main的函数&#xff0c;而在Windows中是WinMain。一旦执行起来&#xff0c;程序可以通过在系统呼叫CreateThread中指定初始线程函数的名称来建立新的…...

小语种企业网站建设/sem优化是什么意思

shiro是我目前用的项目的一个鉴权框架&#xff0c;也是apache基金会的&#xff0c;用来处理登录&#xff0c;鉴权这部分。下面是官网的介绍页&#xff1a; Shro 官网网站&#xff0c;不管是了解还是学习&#xff0c;都是第一手资料 网上一个用XML文件配置的&#xff0c;这里我…...

无锡公司网站建设电话/杭州关键词排名系统

chatGPT已经爆火一段时间了&#xff0c;我想大多数的开发者都在默默的在开发和测试当中&#xff0c;可能也是因为这个原因所以现在很难找到关于开发中遇到的一些坑或者方法和技巧。为什么别人的机器人能联想之前的语料&#xff0c;而你的却像个每次都只如初见的高冷机器人&…...

专业的外贸网站建设/seo工具网站

一、位运算 位即二进制位或bit位 所有运算到计算中底层中都会变成位运算&#xff0c;位运算可以提高程序的效率,而且我们在研究JDK或者某个框架的源码时&#xff0c;会发现很多地方都用到了位运算&#xff01; 例如我们在对数组进行排序时会大量用到交换两个数的值&#xff…...

新疆建设兵团发改委网站/长沙网站托管优化

中断处理不能睡眠和切换&#xff1a;原因随处可以找到&#xff0c;总结起来就是&#xff1a;1.增加了当前任务的不确定性&#xff0c;实时性能得不到保障&#xff0c;毕竟中断上下文是任意进程上下文&#xff0c;这样对那个被中断的进程不公平&#xff0c;我在邮件列表中的原话…...