Linux内核宏Container_Of的详细解释

yizhihongxing

Linux内核宏Container_Of的详细解释

Container_Of是一个在Linux内核源码中广泛使用的宏,它的作用是根据某个结构体成员的指针推导出该结构体的指针。该宏的定义如下:

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

宏定义解析

该宏有3个参数,分别是:

  1. ptr:结构体成员的指针;
  2. type:结构体的类型;
  3. member:结构体成员的名称。

首先,宏定义使用了GCC的特性——语句表达式(({ ... })),这使得可以在宏定义中使用代码块,从而使宏定义更加灵活。

接下来的第一行定义了一个指针__mptr,类型是指向member成员的指针,__mptr的值是ptr。因为typeof是GCC的一个扩展,所以可以使用__typeof__作为它的替代品。

最后一行使用了C语言的指针算术运算,将__mptr强制转换成了结构体type的指针。其中offsetof是C语言库函数中的一个宏,用于获取结构体成员相对于结构体首地址的偏移量。

示例说明一

下面是一个例子,展示如何使用Container_Of来获取某个结构体的指针:

struct my_struct {
    int a;
    int b;
    int c;
};

struct my_struct *p, *q;

/* p指向a成员,使用Container_Of宏获取my_struct结构体指针 */
p = (struct my_struct *)(&(q->a)); // q为我们要找的结构体指针
q = container_of(p, struct my_struct, a);

在上述示例中,我们首先声明了一个my_struct结构体和两个指向该结构体的指针pq。其中p指向my_struct结构体中的a成员,使用Container_Of宏获取my_struct结构体指针,最后将指针赋值给了q

示例说明二

下面是另一个例子,展示如何遍历链表。在链表中,每个节点都包含一个指向下一个节点的指针:

struct node {
    int val;
    struct list_head list;
};

struct node *p;
struct list_head *pos, *head;

/* 遍历链表的每个元素 */
list_for_each(pos, head) {
    /* pos指向当前元素的list_head结构体,
     * 使用Container_Of获取包含该结构体的node结构体指针*/
    p = container_of(pos, struct node, list);
    printf("%d\n", p->val);
}

在上述示例中,我们首先声明了一个node结构体和两个指针pheadnode结构体包含一个整数成员val和一个指向下一个节点的list_head结构体指针listhead指向链表的头节点。

使用list_for_each宏遍历链表的每个元素,pos指向当前元素的list_head结构体。使用Container_Of宏获取包含pos结构体的node结构体指针,最后输出该元素的val成员。

总体来说,Container_Of是一个非常有用的宏,在Linux内核源码中被广泛使用。通过理解它的实现和使用方法,我们可以更好地理解Linux内核的数据结构和算法。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Linux内核宏Container_Of的详细解释 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • jmeter+ant+jenkins自动化测试环境配置搭建过程

    题目要求讲解“jmeter+ant+jenkins自动化测试环境配置搭建过程”的完整攻略,下面是具体的步骤: 1. 安装JMeter JMeter 是一款常用的测试工具,我们需要先安装好。 下载安装包:Apache JMeter 下载 安装 JMeter。 2. 安装 Ant Ant 是一个 Java 应用程序构建系统,相信大家都已经熟悉它。Ant 需要使用…

    other 2023年6月27日
    00
  • Shell全局变量、局部变量与特殊变量的具体使用

    Shell全局变量、局部变量与特殊变量的具体使用 在Shell中,变量的使用非常重要,特别是各种变量的使用方式。本篇文章将详细讲解Shell中的全局变量、局部变量与特殊变量,并给出一些示例说明。 全局变量 全局变量在整个程序运行时都是可用的,可以被所有函数或命令使用。在Shell中,定义全局变量不需要显示声明,直接赋值即可。例如: #!/bin/bash g…

    other 2023年6月27日
    00
  • thinkPHP框架中layer.js的封装与使用方法示例

    下面是 “thinkPHP框架中layer.js的封装与使用方法示例” 的攻略: 1. layer.js的引入和初始化 1.1 引入layer.js 在HTML页面中通过script标签引入layer.js文件,代码示例如下: <script src="/path/to/layer.js"></script> 1.…

    other 2023年6月25日
    00
  • 用python操作浏览器的三种方式

    当今,Python已成为最受欢迎的编程语言之一,它可以用于各种用途,包括自动化浏览器操作。在本攻略中我们将详细讲如何使用Python操作浏览器的三种方式,并提供两个示例说明。 三种方式 方式1:使用selenium库 selenium是流行的Python库,它允许我们自动化浏览器操作。使用selenium,我们可以模拟用户在浏器中的行为,点击链接、填写表单等…

    other 2023年5月8日
    00
  • java调用FFmpeg实现视屏压缩功能的详细步骤

    让我们来一步步讲解如何使用Java调用FFmpeg实现视频压缩的功能。 前置条件 在开始之前,需要安装FFmpeg工具,并且配置好环境变量。可以通过以下命令检查FFmpeg是否安装成功: ffmpeg -version 步骤一:导入FFmpeg库 首先,需要在Java项目中导入FFmpeg库,以便后续调用相应的方法。可以使用以下Maven依赖: <de…

    other 2023年6月26日
    00
  • access怎么按照性别为某字段增补前置符号?

    为了实现按照性别字段为某字段增补前置符号,需要使用到access的查询功能。具体步骤如下: 点击创建,在下拉菜单中选择查询设计。在新建的查询设计视图中,添加需要操作的数据表,并在其中选择目标字段与需增补的前置符号。以增补前置符号的方式为例,可以选择计算字段,在该字段的表达式中使用&符号将目标字段与需要增补的符号连接起来。例如,若我们需要在Gender…

    other 2023年6月25日
    00
  • Android SurfaceView拍照录像实现方法

    Android SurfaceView拍照录像实现方法攻略 在Android开发中,使用SurfaceView可以实现拍照和录像功能。下面是详细的攻略,包含两个示例说明。 示例一:拍照功能实现 在布局文件中添加SurfaceView组件: <SurfaceView android:id=\"@+id/surfaceView\" an…

    other 2023年9月7日
    00
  • 苹果发布OS X 10.11.2 El Capitan第二个开发者测试版

    苹果发布OS X 10.11.2 El Capitan第二个开发者测试版 苹果发布了OS X 10.11.2 El Capitan的第二个开发者测试版,本文将为大家分享如何下载和安装该测试版。 下载 首先,你需要先加入Apple开发者计划。 进入苹果开发者中心,找到OS X 10.11.2 El Capitan第二个开发者测试版,点击下载。 下载完成后,你可…

    other 2023年6月26日
    00
合作推广
合作推广
分享本页
返回顶部