源地址:http://blog.csdn.net/tigerjibo/article/details/8299589

2012-12-15 19:23 1636人阅读 评论(2) 收藏 举报
 
 

1.container_of宏

1> Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址。 2>接口: container_of(ptr, type, member)  ptr:表示结构体中member的地址 type:表示结构体类型 member:表示结构体中的成员 通过ptr的地址可以返回结构体的首地址 3> container_of的实现:  #define container_of(ptr, type, member) ({      \     const typeof( ((type *)0)->member ) *__mptr = (ptr);    \     (type *)( (char *)__mptr - offsetof(type,member) );})   其实它的语法很简单,只是一些指针的灵活应用,它分两步: 第一步,首先定义一个临时的数据类型(通过typeof( ((type *)0)->member )获得)与ptr相同的指针变量__mptr,然后用它来保存ptr的值。 说明:typeof是GNU C对标准C的扩展,它的作用是根据变量获取变量的类型《typeof关键字在linux 内核中很常见》 第二步,用(char *)__mptr减去member在结构体中的偏移量,得到的值就是整个结构体变量的首地址(整个宏的返回值就是这个首地址)。 关于offsetof的用法可参见offsetof宏的使用。

2. 举例来说明container_of的使用

1>正确示例:

#include <stdio.h> #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #define  container_of(ptr, type, member) ({                      \                       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \                        (type *)( (char *)__mptr - offsetof(type,member) );}) struct test_struct {            int num;           char ch;           float f1;   };  int main(void)   {           struct test_struct *test_struct;           struct test_struct init_struct ={12,'a',12.3};           char *ptr_ch = &init_struct.ch;           test_struct = container_of(ptr_ch,struct test_struct,ch);           printf("test_struct->num =%d\n",test_struct->num);           printf("test_struct->ch =%c\n",test_struct->ch);           printf("test_struct->ch =%f\n",test_struct->f1);           return 0;   } 执行结果: jibo@jibo-VirtualBox:~/cv_work/work/list/container_of $ ./main test_struct->num =12 test_struct->ch =a test_struct->ch =12.300000

2>错误示例:

#include <stdio.h>    #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)   #define  container_of(ptr, type, member) ({                      \                            const typeof( ((type *)0)->member ) *__mptr = (ptr);    \                           (type *)( (char *)__mptr - offsetof(type,member) );})     struct test_struct {            int num;           char ch;           float f1;   };    int main(void)   {           struct test_struct *test_struct;           char real_ch = 'A';           char *ptr_ch = &real_ch;           test_struct = container_of(ptr_ch,struct test_struct,ch);           printf("test_struct->num =%d\n",test_struct->num);           printf("test_struct->ch =%c\n",test_struct->ch);           printf("test_struct->ch =%f\n",test_struct->f1);           return 0;   } 执行结果为: jibo@jibo-VirtualBox:~/cv_work/work/list/container_of1 $ ./main test_struct->num =0 test_struct->ch =A test_struct->ch =0.000000 注意,由于这里并没有使用一个具体的结构体变量,所以成员num和f1的值是不确定的。

更多0

1.offset宏讲解

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)

对这个宏的讲解我们大致可以分为以下4步进行讲解:

地址强制 "转换" 为 TYPE结构类型的指针;

>((TYPE *)0)->MEMBER   访问TYPE结构中的MEMBER数据成员;

>&( ( (TYPE *)0 )->MEMBER)取出TYPE结构中的数据成员MEMBER的地址;

>(size_t)(&(((TYPE*)0)->MEMBER))结果转换为size_t类型。

呢?当然不是,我们仅仅是为了计算的简便。也可以使用是他的值,只是算出来的结果还要再减去该数值才是偏移地址。来看看如下的代码:

#include<stdio.h>

#defineoffsetof(TYPE, MEMBER) ((size_t) &((TYPE *)4)->MEMBER)

struct test_struct {

int num;

char ch;

float f1;

};

int main(void)

{

printf("offsetof (struct test_struct,num)=%d\n",offsetof(struct test_struct,num)-4);

printf("offsetof (structtest_struct,ch) =%d\n",offsetof(struct test_struct,ch)-4);

printf("offsetof (struct test_struct,f1)=%d\n",offsetof(struct test_struct,f1)-4);

return 0;

}

运行结果为:

jibo@jibo-VirtualBox:~/cv_work/work/list/offset $ ./main

offsetof (struct test_struct,num) =0

offsetof (struct test_struct,ch) =4

offsetof (struct test_struct,f1) =8

。

二.举例体会offsetof宏的使用:

#include<stdio.h>

#defineoffsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

struct test_struct {

int num;

char ch;

float f1;

};

int main(void)

{

printf("offsetof(struct test_struct,num) =%d\n",offsetof(struct test_struct,num));

printf("offsetof (structtest_struct,ch) =%d\n",offsetof(struct test_struct,ch));

printf("offsetof (struct test_struct,f1)=%d\n",offsetof(struct test_struct,f1));

return 0;

}

执行结果为:

jibo@jibo-VirtualBox:~/cv_work/work/list/offset $ ./main

offsetof (struct test_struct,num) =0

offsetof (struct test_struct,ch) =4

offsetof (struct test_struct,f1) =8

转:container_of分析 研究内核的博客的更多相关文章

  1. Linux内核分析第一周学习博客 --- 通过反汇编方式学习计算机工作过程

    Linux内核分析第一周学习博客 通过反汇编方式学习计算机工作过程 总结: 通过这次对一个简单C程序的反汇编学习,我了解到计算机在实际工作工程中要涉及大量的跳转指针操作.计算机通常是顺序执行一条一条的 ...

  2. Linux内核分析第二周学习博客——完成一个简单的时间片轮转多道程序内核代码

    Linux内核分析第二周学习博客 本周,通过实现一个简单的操作系统内核,我大致了解了操作系统运行的过程. 实验主要步骤如下: 代码分析: void my_process(void) { int i = ...

  3. angular源码分析 摘抄 王大鹏 博客 directive指令及系列

    链接地址:http://www.cnblogs.com/web2-developer/p/angular-14.html $compile的功能:将一个html字符串或者一个DOM进行编译,返回一个链 ...

  4. core dump + LINUX 内核系列博客

    参考:http://www.cnblogs.com/ahuo/category/72819.html http://blog.csdn.net/tenfyguo/article/details/815 ...

  5. Linux内核总结博客 20135332武西垚

    http://www.cnblogs.com/wuxiyao/p/5220677.htmlhttp://www.cnblogs.com/wuxiyao/p/5247571.htmlhttp://www ...

  6. LINUX 内核学习博客

    http://www.cnblogs.com/yjf512/category/385367.html

  7. 我的Android进阶之旅------>经典的大牛博客推荐(排名不分先后)!!

    本文来自:http://blog.csdn.net/ouyang_peng/article/details/11358405 今天看到一篇文章,收藏了很多大牛的博客,在这里分享一下 谦虚的天下 柳志超 ...

  8. 一步步开发自己的博客 .NET版(3、注册登录功能)

    前言 这次开发的博客主要功能或特点:    第一:可以兼容各终端,特别是手机端.    第二:到时会用到大量html5,炫啊.    第三:导入博客园的精华文章,并做分类.(不要封我)    第四:做 ...

  9. hexo框架-next主题-github搭建个人博客

    IT`huhui 的前言录 我在GITHUB的个人站点:http://ithuhui.cn 这里遇到的很多问题都是亲身解决后写的.还有遇到不懂可以邮件M我 在这里要感谢浮生志的博客教程,很多我一开始不 ...

随机推荐

  1. 概率——17icpc西安

    不知道为什么是这样子的.. #include<bits/stdc++.h> using namespace std; int m,n; int main(){ while(scanf(&q ...

  2. Dubbo 如何成为连接异构微服务体系的最佳服务开发框架

    从编程开发的角度来说,Apache Dubbo (以下简称 Dubbo)首先是一款 RPC 服务框架,它最大的优势在于提供了面向接口代理的服务编程模型,对开发者屏蔽了底层的远程通信细节.同时 Dubb ...

  3. Delphi 实现简易语音发音(基于TTS方式)

    uses Comobj; procedure TForm1.Button1Click(Sender: TObject); var voice: OLEVariant; begin voice := C ...

  4. C语言新手写扫雷源代码

    今天发布源代码,由于写在一个文件里非常乱,所以分三个文件写 绘图和鼠标函数graph.h /*绘图与鼠标相关函数*/ #include<graphics.h> #include <e ...

  5. hdu2089数位DP

    旁听途说这个名字很久了,了解了一下. 改题目的意思是给你若干区间,让你找寻区间内不含62或4的数. 首先暴力必然T...那么实际上就是说,想办法做一种预处理,在每次输入的时候取值运算就可以了. 既然是 ...

  6. 访问者模式和 ASM

    文章目录 一. 概述 & 定义 二. 示例 2.1 创建抽象元素 2.2 创建具体元素 2.3 创建抽象访问者 2.4 创建具体访问者 2.5 访问者代码调用 三. ASM 中的访问者模式 3 ...

  7. HDU 6697 Closest Pair of Segments (计算几何 暴力)

    2019 杭电多校 10 1007 题目链接:HDU 6697 比赛链接:2019 Multi-University Training Contest 10 Problem Description T ...

  8. 数据挖掘Aprior算法详解及c++源码

    [算法大致描述] Aprior算法主要有两个操作,扫描数据库+统计.计算每一阶频繁项集都要扫描一次数据库并且统计出满足支持度的n阶项集. [算法主要步骤] 一.频繁一项集 算法开始第一步,通过扫描数据 ...

  9. MySQL数据库(一)—— 数据库介绍、MySQL安装、基础SQL语句

    数据库介绍.MySQL安装.基础SQL语句 一.数据库介绍 1.什么是数据库 数据库即存储数据的仓库 2.为什么要用数据库 (1)用文件存储是和硬盘打交道,是IO操作,所以有效率问题 (2)管理不方便 ...

  10. Spark中的多线程并发处理

    Spark中的多任务处理 Spark的一个非常常见的用例是并行运行许多作业. 构建作业DAG后,Spark将这些任务分配到多个Executor上并行处理.但这并不能帮助我们在同一个Spark应用程序中 ...