Linux container_of() 宏定义

container_of 宏

今天遇到了一段这样的代码,大致意思是 通过该struct结构体变量的成员的地址来反推该struct结构体变量的地址

并且用到了内核的宏,container_of()

static inline struct nova_inode_info *NOVA_I(struct inode *inode)
{return container_of(inode, struct nova_inode_info, vfs_inode);
}

查了查该宏位于include/linux/kernel.h文件

功能:由结构体变量的某个成员变量的内存地址来得到该结构体变量的内存地址

参数:

  1. 该结构体成员变量的地址(指针)

    2. 该结构体的定义类型(type)
    3. 该结构体成员的变量名()
    

具体实现:

#define container_of(ptr, type, member) ({                      \const typeof( ((type *)0)->member ) *__mptr = (ptr);    \(type *)( (char *)__mptr - offsetof(type,member) );})

原理:

  1. 用到GCC的typeof预处理语句,typeof(x),返回参数x的类型
  2. 用到了offsetof(type,member),由一个结构成员member,得到相对于结构开头的字节偏移量 .在<stddef.h>

container_of()做了两步.

  1. 模拟该结构体变量指针指向成员然后通过typeof()反推成员的数据类型,const typeof( ((type *)0)->member),然后定义一个该成员变量类型的指针(就是ptr的数据类型)const typeof( ((type *)0)->member) *__mptr = (ptr)
  2. __mptr转换为char *,按照1个字节计算,__mptr减去成员偏移量就是结构体变量的基地址了。再将该地址(指针)转换为type指针
  3. 最后表达式返回的是 (type *) (结构体变量基地址) 指针
1. const typeof( ((type *)0)->member) *__mptr = (ptr)
2. (char *)__mptr - offsetof(type,member)

测试:

#include <stdio.h>
#include <stddef.h>#define everything_to_string(x) #x 
/*
#define container_of(ptr,type,member) ({ \const typeof( ((type *)0)->member ) *__mptr = (ptr); \(type *)( (char *)__mptr - offsetof(type,member) );})
*/
//const struct member *__mptr=ptr;
//(struct Student *)( (char *)__mptr - offsetof(type,member) ) 
#define container_of(ptr,type,member) ({ \const typeof( ((type *)0)->member ) *__mptr = (ptr); \(type *)((char *)__mptr - offsetof(type,member)); })struct info {int a;int b;
};
struct Student {char name[4]; // 0int age;      // 4int grade;    // 8int sex;      // 12struct info last;
};int main()
{struct Student student={"123",22,100,1,{10,20}};struct info *ptr=&student.last;struct Student *pstudent = container_of(ptr,struct Student,last);printf("[%p]\n",pstudent);printf("[%p]\n",ptr);return 0;
}

参考资料

  1. https://stackoverflow.com/questions/15832301/understanding-container-of-macro-in-the-linux-kernel
  2. https://gaomf.cn/2017/10/07/C_typeof/
  3. https://www.runoob.com/cprogramming/c-macro-offsetof.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/70788.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode 655. 输出二叉树(java)

输出二叉树 题目描述代码演示 题目描述 难度 - 中等 leetcode 655. 输出二叉树 给你一棵二叉树的根节点 root &#xff0c;请你构造一个下标从 0 开始、大小为 m x n 的字符串矩阵 res &#xff0c;用以表示树的 格式化布局 。构造此格式化布局矩阵需要遵循以下规则&#xff1a…

Python接口自动化封装导出excel方法和读写excel数据

一、首先需要思考&#xff0c;我们在页面导出excel&#xff0c;用python导出如何写入文件的 封装前需要确认python导出excel接口返回的是一个什么样的数据类型 如下&#xff1a;我们先看下不对返回结果做处理&#xff0c;直接接收数据类型是一个对象&#xff0c;无法获取返回值…

IOC和注解

想要学好spring&#xff0c;必须时时刻刻想着&#xff0c;spring的本质就是一个容器&#xff0c;放java对象的容器&#xff0c;java对象在spring容器中也叫做bean对象。 文章目录 一、spring介绍1、什么是框架2、框架的作用![在这里插入图片描述](https://img-blog.csdnimg.cn…

MongoDB的数据恢复与备份

MongoDB的数据恢复与备份 在MongoDB中&#xff0c;备份和恢复数据是一项关键任务&#xff0c;可以确保数据的安全性并防止意外数据丢失。本文将介绍MongoDB的数据恢复与备份原理并提供相关的编程代码和配置。 1. 数据备份原理 MongoDB提供了多种备份数据…

数字图像基础

数字图像基础 人眼感知视觉 锥状体&#xff08;亮视觉&#xff09; 杆状体&#xff08;暗视觉&#xff09;人的视觉系统感知的亮度是进入人眼光强的对数函数亮度适应现象&#xff1a; 视觉系统不能同时在一个范围内工作&#xff0c;而通过改变其整个灵敏度来实现 光与电磁波谱…

这几招真管用!找回丢失的iPhone的好方法!

你昂贵的iPhone不见了。它丢了吗?它被偷了吗?如果你把iPhone弄丢了,你可以从各种其他来源找到它,包括iPad、Mac、iCloud和Apple Watch。 你可以使用iCloud网站上的苹果“查找我的”应用程序、你的任何其他苹果设备或你家人注册的设备来追踪它。或者从“查找我的”应用程序…

Java基础知识点汇总

一、Java基础知识点整体框架 详细知识点见链接资源&#xff0c;注&#xff1a;框架是用Xmind App完成&#xff0c;查看需下载。 二、基础知识各部分概况 2.1 认识Java 2.2 数据类型和变量 2.3 运算符 2.4 程序逻辑控制 2.5 方法的使用 2.6 数组的定义和使用 2.7 类和对象 2.8 …

移植STM32官方加密库STM32Cryptographic

感谢这位博主&#xff0c;文章具有很高的参考价值&#xff1a; STM32F1做RSA&#xff0c;AES数据加解密&#xff0c;MD5信息摘要处理_我以为我爱了的博客-CSDN博客 概述 ST官方在很多年前就推出了自己的加密库&#xff0c;配合ST芯片用起来非常方便&#xff0c;支持ST的所有…

借助CIFAR10模型结构理解卷积神经网络及Sequential的使用

CIFAR10模型搭建 CIFAR10模型结构 0. input : 332x32&#xff0c;3通道32x32的图片 --> 特征图(Feature maps) : 3232x32即经过32个35x5的卷积层&#xff0c;输出尺寸没有变化&#xff08;有x个特征图即有x个卷积核。卷积核的通道数与输入的通道数相等&#xff0c;即35x5&am…

使用U盘同步WSL2中的git项目

1、将U盘挂载到WSL2中 假设U盘在windows资源管理器中被识别为F盘&#xff0c;需要在WSL2中创建一个目录挂载U盘 sudo mkdir /mnt/f sudo mount -t drvfs F: /mnt/f后续所有的操作都完成后&#xff0c;拔掉U盘前&#xff0c;可以使用下面的命令从WSL2中安全的移除U盘 umount …

SpringCloud(十)——ElasticSearch简单了解(一)初识ElasticSearch和RestClient

文章目录 1. 初始ElasticSearch1.1 ElasticSearch介绍1.2 安装并运行ElasticSearch1.3 运行kibana1.4 安装IK分词器 2. 操作索引库和文档2.1 mapping属性2.2 创建索引库2.3 对索引库的查、删、改2.4 操作文档 3. RestClient3.1 初始化RestClient3.2 操作索引库3.3 操作文档 1. …

网络技术二十二:NATPPP

NAT 转换流程 产生背景 定义 分类 常用命令 PPP PPP会话建立过程 认证 PPP会话流程

第 3 章 栈和队列(循环队列的顺序存储结构实现)

1. 背景说明 和顺序栈相类似&#xff0c;在队列的顺序存储结构中&#xff0c;除了用一组地址连续的存储单元依次存放从队列头到队列尾的元素之外&#xff0c; 尚需附设两个指针 front 和 rear 分别指示队列头元素及队列尾元素的位置。约定&#xff1a;初始化建空队列时&#x…

qt nodeeditor编译安装

目录 1. 下载源码 2. Qt creator编译源码 2.1 编译debug模式 &#xff08;MinGW&#xff09; 2.2 编译release模式 &#xff08;MinGW&#xff09; 1. 下载源码 https://github.com/paceholder/nodeeditor/archive/refs/tags/3.0.10.zip 2. Qt creator编译源码 解压文件…

error:0308010C:digital envelope routines::unsupported

Vue 报错error:0308010C:digital envelope routines::unsupported 出现这个错误是因为 node.js V17版本中最近发布的OpenSSL3.0, 而OpenSSL3.0对允许算法和密钥大小增加了严格的限制&#xff0c;可能会对生态系统造成一些影响. 方法1 打开终端&#xff08;按健winR弹出窗口&a…

Java 数据库改了一个字段, 前端传值后端接收为null问题解决

前端传值后端为null的原因可能有很多种&#xff0c;我遇到一个问题是&#xff0c;数据库修改了一个字段&#xff0c;前端传值了&#xff0c;但是后台一直接收为null值&#xff0c; 原因排查&#xff1a; 1、字段没有匹配上&#xff0c;数据库字段和前端字段传值不一致 2、大…

c语言 4.0

&#x1f482; 个人主页: 程序员爱摸鱼&#x1f91f; 版权: 本文由【程序员爱摸鱼】原创、在CSDN首发、需要转载请联系博主&#x1f4ac; 如果文章对你有帮助、欢迎关注点赞收藏(一键三连)哦&#x1f485; 想寻找共同成长的小伙伴&#xff0c;可以互粉哦 &#x1f4ac;文章目录…

软件架构设计(六) 软件架构风格-MDA(模型驱动架构)

概念 模型驱动架构MDA, 全称叫做Model Driven Architecture。 Model:表示客观事物的抽象表示Architecture:表示构成系统的部件,连接件及其约束的规约Model Driven: 使用模型完成软件的分析,设计,构建,部署和维护等 开发活动MDA起源于分离系统规约和平台实现的思想。之前…

stable diffusion实践操作-复制-清空-保存提示词

系列文章目录 stable diffusion实践操作 stable diffusion实践操作-webUI教程 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、右上生成图标附近按钮介绍1. 箭头介绍&#xff08;复现别人的…

视频汇聚/视频云存储/视频监控管理平台EasyCVR启动时打印starting server:listen tcp,该如何解决?

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;可实现视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、H.265自动转码H.264、平台级联等。为了便于用户二次开发、调用与集成&#xff0c;…