源地址: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. 帝国CMS数据库数据表详细说明

    表名                                             解释 phome_ecms_infoclass_news 新闻采集规则记录表 phome_ecms_inf ...

  2. curl查看index以及settings

    1.查看mapping curl -u elastic:elastic -XGET "127.0.0.1:9200/index_name/_mapping" 2.查看setting ...

  3. Sophus安装时Eigen库更新版本的问题

    原文链接:https://blog.csdn.net/m0_38055352/article/details/102900516

  4. 随机生成一串字符串(java)

    该随笔为开发笔记 今天在公司接手了一个项目,在看该项目老代码时,发现上一位大佬写的随机取一串字符串还不错,在此做一次开发笔记 在他的基础上我做了点改动,但是原理一样 /** * 随机取一段字符串方法1 ...

  5. JS 变量 相关内容

    JS变量按存储方式区分为哪些类型?: js变量按照存储方式分为两种类型:值类型 和 引用类型 1.值类型(基本类型): 布尔值(boolean) . null .undefined .数值(numbe ...

  6. postgresql修改自增序列

    ----删除前先解除 id 对该序列的依赖ALTER TABLE tablename ALTER COLUMN id SET DEFAULT null;DROP SEQUENCE IF EXISTS ...

  7. 4. Jmeter主界面的介绍

    上篇文章我们已经介绍过如何安装Jmeter.那么在本篇文章我们将要介绍Jmeter主界面有哪些功能.我们双击jmeter.bat,如下图所示(注意我这是jmeter5.0版本): 我们将Jmter主界 ...

  8. STL unique

    1: template <class ForwardIterator> 2: ForwardIterator unique (ForwardIterator first, ForwardI ...

  9. Vue 学习笔记之 —— 表单输入绑定

    Vue 中文文档 https://cn.vuejs.org/ 不多说,直接上干货. v-model 指定,用来在input textarea 等表单元素上创建双向数据绑定,负责监听用户的输入事件,以及 ...

  10. 调用API接口,查询手机号码归属地(2)

    使用pymysql pip install pymysql 创建mysql测试表 CREATE TABLE `userinfo` ( `id` int(20) NOT NULL AUTO_INCREM ...