linux中的list.h(1)

Linux内核源码list.h解读 #list.h源码阅读 此文章是我阅读list.h后的一些见解,有问题且理解不到位的地方希望大家批评指正。 本次我们阅读的内核版本为4.18.7 在Linux内核中,list.h是内核为了方便使用链表而自己建立的链表头文件。 以__开头的是指内核函数。 ##链表 ##宏定义 除了调用其它头文件外,首先看到的是两个宏定义。 #define LIST_HEAD_INIT(name) { &... 阅读详情

相关博文:
linux中的list.h(2) ——>内核链表的创建、LIST_HEAD()方法
linux中的list.h(3) ——>内核链表的增加、删除、遍历

linux内核中的链表

在之前我接触的数据结构中的链表,通常的做法是在结构体的内部添加一个指向数据next节点的指针,才能串在链表中。
比如,现有一个fox数据结构:

struct fox{
    unsigned long weight;
    bool is_cute;
}

存储这个结构到链表里的通常做法是在数据结构中嵌入一个链表指针。

struct fox{
    unsigned long weight;
    bool is_cute;
    struct fox *next; /* 指向下一个狐狸 */
}

但是linux内核中,它不是将数据结构塞入链表,而是将链表节点塞入数据结构。
linux内核中的链表数据结构。链表代码在< linux/list.h>中声明,其数据结构为:

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

list_head本身没有意义,它需要被嵌入到我们自己的结构体中才会生效。
list_head结构的使用:

struct fox{
    unsigned long weight;
    bool is_cute;
    struct list_head list;  /* 所有的fox结构体形成链表 */
}

这样将linux的链表结构体嵌入到使用链表的对象中(链表宿主)的组合方式,实现了链表和宿主的解耦。于是所有链表的操作都是针对struct list_head这个链表数据结构,而链表的设计者不会知道链表宿主的任何情况。因此,必须在指向链表结构体的指针和指向宿主的指针之间进行转换。

宏list_entry详解

宏list_entry用于返回包含list_head的宿主结构体。实现在指向链表结构体的指针和指向宿主的指针之间进行转换。

这里写图片描述

container_of

/usr/src/kernels/include/linux/kernel.h
这里写图片描述

container_of的用法,是在已知结构体的某个成员的指针(首地址)时,求出整个结构体的首指针地址。
ptr是成员的指针(首地址),type是结构体类型,member是成员。

struct list_head *ptr;
...
/* list_entry(ptr, type, member) */
struct fox *pnode=list_entry(ptr, struct fox, list);

ptr为指向当前fox宿主对象中内嵌list成员的指针。
struct fox为宿主类型名。
list为linux链表结构体在宿主中的成员变量名。

  • ((type*)0)将0转型为type类型指针,即fox类型。
  • ((type*)0)->member访问结构体中的数据成员member,即fox中的list成员。
  • typeof(((type*)0)->member),typeof的作用是根据变量名获取变量的类型。在这里获取的类型为struct list_head。即为const struct list_head *__mptr。将fox结构体变量中的成员list的地址赋给临时变量__mptr。
  • offsetof(type,member)是求成员在结构体中的偏移量。这里成员list在fox中的偏移量。
  • (char*)__mptr减去member在结构体中的偏移量,得到的值就是整个结构体变量的首地址。

简单的来说,就是先定义一个临时的数据类型与ptr相同的指针变量__mptr,用它来保存ptr的值。再用(char*)__mptr减去member在结构体中的偏移量,即可得到整个结构体的首地址。

offsetof(type,member)

offsetof(type,member)求成员在结构体中的偏移量。
/usr/src/kernels/include/linux/stddef.h
这里写图片描述

#include <stdio.h>
#include <linux/stddef.h>

#ifdef __compiler_offsetof
#define offsetof(TYPE, MEMBER)  __compiler_offsetof(TYPE, MEMBER)
#else
#define offsetof(TYPE, MEMBER)  ((size_t)&((TYPE *)0)->MEMBER)
#endif

struct Test{
    int a;
    char b;
    float c;
};
int main()
{
    printf("%d\n",offsetof(struct Test,a));
    printf("%d\n",offsetof(struct Test,b));
    printf("%d\n",offsetof(struct Test,c));
    return 0;
}

红色代表int所占用的,绿色是char所占用的,灰色是float所占用的。
这里写图片描述

这里写图片描述

linux内核中的list.h文件中哈希表的分析 一、背景     本篇文章将先从对哈希表的基本介绍开始,然后分析linux内核(3.10.0版)中的list.h文件中的哈希表。 二、简述哈希表     根据设定的哈希函数H(key)和处理冲突的方法将一组关键字映像到一个有限的连续的地址集上,并以关键字在地址集中的“像”作为记录在表中的存储位置,这种表便称为哈希表。     上面这一段是从一本教材中摘抄出来的对哈希表的一段描述。     阅读详情

相关推荐

linux内核list.h完整源代码

本文档是从GiHup上linux/include/linux/list.h复制过来的,有完整版的list.h,但其中含包含Linux的其它头文件的函数,但基本不影响阅读

Linux 中list.h使用实例和坑

​ list.h是Linux内核中,为了提供统一的链表操作,减少结构体的额外开支提供的链表操作。list.h中定义的链表了一个双向循环链表,和一个哈希表。内含实际例子 ​

monkeyzh123的专栏 3244

list.h的源文件

list.h的源文件,如果可以和自己的c代码放在一个文件夹,然后#include “list.h”就可以把使用内部的函数

linux——list.h

*linux中的头文件list.h 在Linux的源码中有一个自己为建立链表而写的链表头文件,以后可以直接调用里面的函数来使用链表。 list.h在linux中的路径为/usr/src/kernels/include/linux。不同的版本可能不一样。 list.h中有两个宏定义:#define LIST_HEAD_INIT(name) {&(name),&(name)} #define LI

sinat_34467747的博客 7516

Zynq7000双核裸机开发实战:如何安全实现共享内存与乒乓RAM设计

本文深入探讨了Zynq7000双核裸机开发中的共享内存与乒乓RAM设计,重点解析了核间通信的Cache一致性处理机制和硬件级实现方案。通过实战代码示例和性能优化技巧,帮助开发者解决双核运行中的访问冲突问题,提升嵌入式系统开发效率。

weixin_29191669的博客 375

ArcGIS新手必看:HWSD2土壤数据从下载到批量提取TIFF的完整流程

本文详细介绍了ArcGIS中HWSD2土壤数据的完整处理流程,从数据下载、预处理到批量提取TIFF文件。涵盖栅格属性表构建、属性数据连接及性能优化等关键步骤,帮助新手高效掌握HWSD2数据提取技术,提升地理信息数据处理效率。

ll5678的博客 1035

内核链表<linux/list.h>

链表在内核中无处不在设计精巧灵活高效,几乎被应用于所有的内核数据结构中巧妙的借用结构体内成员偏移思想获取宿主结构体指针(container_of 宏的实现),从而间接可以获取到主体中的其他数据即使你是app开发者,可以模仿内核链表的实现撰写出适用于自己需求的数据结构,点击查看demoint data;<linux/list.h> 提供了 Linux 内核中双向链表的通用实现,通过 list_head 结构体和一系列操作宏/函数,内核能够高效地管理链表数据。

weixin_45302098的博客 334

旋转变压器软件解码simulink仿真

旋转变压器软件解码simulink仿真、电机转速位置测量

qq_31446727的博客 2580

Linux 内核的 list.h

内核 list.h 的源码+一个例子+简要解析

yong1585855343的博客 491

【Segment Anything Model】十(1):利用SAM做分类任务,方法二,不放过SAM强大特征提取能力,将SAM提取到的ImageEmbedding插入到其他cnn网络中

直接黏贴复制就好'''该类定义了VGG-16的基本结构。features: 代表VGG网络的主体部分,即所有的卷积层和池化层。avgpool: 是自适应平均池化层,将特征图大小调整为7x7。classifier: 是VGG网络的分类部分,由全连接层组成。_initialize_weights(): 初始化权重的方法。

cvxiayixiao的博客 3561

Python 爬虫实战:爬取 B 站 UP 主的全部视频数据

本文详细介绍了基于Python开发B站UP主视频数据爬虫的技术方案。通过分析B站API接口,使用requests库发送HTTP请求并处理JSON数据,结合pandas进行结构化存储。文章重点解决了接口鉴权、分页爬取、反爬策略等核心难点,实现获取视频标题、播放量、点赞数等关键指标。同时强调数据爬取需遵守平台规范,仅限技术研究使用。该方案为B站视频内容分析提供了可靠的数据采集基础,具有实际应用价值。

2503_91057718的博客 2492

linux 内核链表操作头文件list.h

#ifndef _LINUX_LIST_H #define _LINUX_LIST_H #define inline __inline #define LIST_POISON1 (void *) 0x00100100 #define LIST_POISON2 (void *) 0x00200200 #define prefetch(x) x #define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER) #define con...

zz460833359的博客 814

自动识别象棋棋子的OpenCV应用

在计算机视觉领域,OpenCV是一个广泛应用的开源计算机视觉库,它提供了丰富的图像处理和分析工具。本文将介绍如何使用OpenCV实现自动识别象棋棋子的功能,并提供相应的源代码。通过以上代码,我们可以实现对棋盘图像中棋子的自动识别。需要注意的是,以上代码只是一个简单的示例,实际应用中可能需要根据具体情况进行参数调整和算法优化,以获得更好的识别效果。函数利用预处理后的图像,寻找图像中的轮廓,并根据轮廓的面积筛选出可能的棋子轮廓,最后在原图像中提取棋子区域。在主程序中,我们读取输入图像,并调用。

WzisTypescript的博客 906

浅谈linux内核中的list.h[1]

 1#ifndef _LINUX_LIST_H2#define _LINUX_LIST_H34#include linux/stddef.h>5#include linux/poison.h>6#include linux/prefetch.h>7#include asm/system.h>  链表的初始化19struct list_head {20

tedious的专栏 675

华为OD机试真题 新系统 2026-04-26 Python&JS 实现【项目模块依赖构建顺序规划】

某公司正在开发一个大型软件系统,系统包含 N 个模块,每个模块之间存在构建依赖关系。例如,模块 A 可能依赖于模块 B,这意味着必须先构建模块 B,才能构建模块 A。 请根据依赖关系,输出所有可能的模块构建顺序(按照构建顺序排列模块名称),要求:

MISAYAONE的博客 404

CTR-GCN 论文解读

提出了一种信道拓扑优化图卷积,该卷积可以动态有效地对信道拓扑进行建模。共享拓扑是一个参数化的邻接矩阵,作为所有通道的拓扑先验,并提供顶点之间的一般相关性。通过使用特定于通道的相关性细化共享拓扑,CTR-GC 获得了通道拓扑。

一杯水果茶!足矣~ 3088

Linux内核list.h整体分析1

对链表常用的操作     对链表常用的操作无非就是增加、删除、遍历等。当然内核还提供很多其他的操作,如替换某个结点、将某个结点移动到链表尾端等等,这些操作都是通过调用基本的增加、删除等操作完成的。 ① 增加:list_add和list_add_tail        调用list_add 可以将一个新链表结点插入到一个已知结点的后面;(头插)     调用list_add_tail 可以将...

世间所有的相遇都是久别重逢 460

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

第三学 linux内核中最基本的数据组织方式——list.h分析(1)

如果说内核态helloworid是我们进入linux内核世界的第一步,那么双链表操作算是我们学习linux内核数据组织方式的敲门砖。               在这里,我们首先要搞清一个概念,我们为什么要用链表来组织数据? 这我们可以从我们如何操作链表和存储链表这个角度来理解:链表操作无外乎插入节点、删除节点、查找节点、遍历节点等等等等,而它的存储并不像我们的数组一样占据一段连续的存储空间,它

bcs_01的专栏 951

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

linux 双向链表

下面代码摘自 linux 内核代码 v6.7.1 LXR linux/include/linux/list.h #ifndef _LINUX_LIST_H #define _LINUX_LIST_H #include <linux/container_of.h> #include <linux/types.h> #include <linux/stddef.h> #include <linux/poison.h> #include <linux/con

long_steve的博客 816

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Linux---->链表(1)---->分析list.h 之 函数部分

Linux学习------分析list.h 之 函数部分 在Linux中,最常见也是最经典的数据结构就是其中的双向链表,而对双向链表的各种操作都存储在list.h头文件中,最近仔细看了一下这个头文件,把我对它的理解记录下来,算是一个学习笔记吧。我看的是2.6.35.4版本的内核源代码,list.h在include/linux下存放,相对于一些其他的内核原文件来说,list.h算是比较小的

baidu_23041907的专栏 293

Linux循环链表删除节点,list.h双循环链表的实现,拷贝自Linux内核(2.6.20.1)

/** 描述:双循环链表的实现,拷贝自Linux内核(2.6.20.1)。*/#ifndef _LINUX_LIST_H#define _LINUX_LIST_H#ifdef __cplusplus /* 使C++程序也能用。 */extern "C" {#endif#if !defined(__cplusplus) && defined(WIN32)...

weixin_39705065的博客 234

YOLOv5/v7模型调优:手把手教你为自定义数据集添加解耦头(附PyTorch代码)

本文详细介绍了如何为YOLOv5/v7模型添加解耦头(de-coupled head)以提升自定义数据集的检测性能。通过分离分类和回归任务的处理路径,解耦头设计有效解决了传统耦合头的任务干扰问题,显著提高mAP指标。文章提供完整的PyTorch代码实现,包括模型结构修改、损失函数适配和训练调整,并分享工业场景下的优化技巧和性能对比数据。

weixin_33672400的博客 450

【Linux内核源码分析】内核数据结构

该函数从链表中删除entry()元素,该操作并不会释放entry 或释放包含entry的数据结构体所占用的内存,只是仅仅将entry元素从链表中移走。依靠list_entry()方法,内核提供了创建、操作以及其他链表管理的各种方法,所有这些方法都不需要知道list_head锁嵌入对象的数据结构。这里的pos是一个包含list_head节点对象的指针,可将它看作是list_entry宏的返回值,head是一个指向头节点的指针。使用list_for_each()宏,该宏使用两个list_head类型的参数。

分享C/C++/Linux/网络/数据库/数据结构 527

使用linux内核的list解决约瑟夫环问题

1、约瑟夫环问题:N个人围成一圈,从第一个开始报数,第M个将被淘汰,下一个重新从1开始报数,继续淘汰第M个,直到最后剩下一个。例如N=5,M=2,淘汰的顺序是:2,4,1, 5,最后获胜的是3 2、linux内核list.h:linux-5.12/drivers/gpu/drm/nouveau/include/nvif/list.h 3、代码清单: . ├── include │ └── list.h ├── log │ ├── log_level_time.c │ └── log_le...

daokebaba_lc的博客 347

Linux内核中的list.h浅谈

[十月往昔]——Linux内核中的list.h浅谈 为什么要叫做“十月往昔”呢,是为了纪念我的原博客。 不知道为什么,突然想来一个新的开始——而那个博客存活至今刚好十个月,也有十个月里的文档。 十月往昔,总有一些觉得珍贵的,所以搬迁到这里来。 而这篇文章是在09.04.10里写的。 Jason Lee   ————————————–cut-line /*------------

JasonLee的专栏 5828
上一篇: 守护进程
下一篇: linux中的list.h(2)
_IanXiao
博客等级 码龄12年 84粉丝 241原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值