转:container_of分析 研究内核的博客
源地址:http://blog.csdn.net/tigerjibo/article/details/8299589
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的值是不确定的。
- 上一篇:offset宏的讲解
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分析 研究内核的博客的更多相关文章
- Linux内核分析第一周学习博客 --- 通过反汇编方式学习计算机工作过程
Linux内核分析第一周学习博客 通过反汇编方式学习计算机工作过程 总结: 通过这次对一个简单C程序的反汇编学习,我了解到计算机在实际工作工程中要涉及大量的跳转指针操作.计算机通常是顺序执行一条一条的 ...
- Linux内核分析第二周学习博客——完成一个简单的时间片轮转多道程序内核代码
Linux内核分析第二周学习博客 本周,通过实现一个简单的操作系统内核,我大致了解了操作系统运行的过程. 实验主要步骤如下: 代码分析: void my_process(void) { int i = ...
- angular源码分析 摘抄 王大鹏 博客 directive指令及系列
链接地址:http://www.cnblogs.com/web2-developer/p/angular-14.html $compile的功能:将一个html字符串或者一个DOM进行编译,返回一个链 ...
- core dump + LINUX 内核系列博客
参考:http://www.cnblogs.com/ahuo/category/72819.html http://blog.csdn.net/tenfyguo/article/details/815 ...
- Linux内核总结博客 20135332武西垚
http://www.cnblogs.com/wuxiyao/p/5220677.htmlhttp://www.cnblogs.com/wuxiyao/p/5247571.htmlhttp://www ...
- LINUX 内核学习博客
http://www.cnblogs.com/yjf512/category/385367.html
- 我的Android进阶之旅------>经典的大牛博客推荐(排名不分先后)!!
本文来自:http://blog.csdn.net/ouyang_peng/article/details/11358405 今天看到一篇文章,收藏了很多大牛的博客,在这里分享一下 谦虚的天下 柳志超 ...
- 一步步开发自己的博客 .NET版(3、注册登录功能)
前言 这次开发的博客主要功能或特点: 第一:可以兼容各终端,特别是手机端. 第二:到时会用到大量html5,炫啊. 第三:导入博客园的精华文章,并做分类.(不要封我) 第四:做 ...
- hexo框架-next主题-github搭建个人博客
IT`huhui 的前言录 我在GITHUB的个人站点:http://ithuhui.cn 这里遇到的很多问题都是亲身解决后写的.还有遇到不懂可以邮件M我 在这里要感谢浮生志的博客教程,很多我一开始不 ...
随机推荐
- 区间dp(二维)——cf1199F
复杂度是O(N^5),枚举所有小矩形,转移时再按每列,每行进行转移 #include<bits/stdc++.h> using namespace std; #define N 55 in ...
- go解析markdown转成html
一.代码 package main import ( "fmt" "github.com/microcosm-cc/bluemonday" "gith ...
- PHP base64_decode+gzinflate压缩和解密代码图文教程
今天碰到的这个问题,是我在更换一个WP主题是遇到.目前的情况如下,我想要把如下的超链接去掉,后台代码找到了在sidebar1.php文件中. 打开此文件发现是一长串的字符: 经过百度.google后, ...
- word中怎样把文档里的中文以及中文字符全选?
word中怎样把文档里的中文以及中文字符全选? 参考: 百度 案例: 有个文档是中英文混杂的 现在需要把中文以及中文字符全部设置成别的颜色 应该怎样操作? 有80多页 别说让我一个一个的设置 以wor ...
- vc/atlmfc/include/afx.h(24) : fatal error C1189: #error : Building MFC application with /MD[d] (CRT
环境:win7,64位,vs2012 1> c:/program files/microsoft visual studio 8/vc/atlmfc/include/afx.h(24) : fa ...
- CSS:CSS Id 和 Class选择器
ylbtech-CSS:CSS Id 和 Class选择器 1.返回顶部 1. CSS Id 和 Class id 和 class 选择器 如果你要在HTML元素中设置CSS样式,你需要在元素中设置& ...
- 巧用Wget快速建立文件下载中心
Wget基本用法:1) 从网上下载单个文件 wget http://www.freehao123.com/file.iso 2) 下载一个文件,但以不同的名字存为本地文件 wget –output-d ...
- 1、什么是cookie?
什么是cookie? Cookie 定义 “Cookie”是小量信息,由网络服务器发送出来以存储在网络浏览器上,从而下次这位独一无二的访客又回到该网络服务器时,可从该浏览器读回此信息.这是很有用 ...
- 剑指offer——52第一个只出现一次的字符
题目描述 在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写). 题解: 想复杂了,从头遍历 ...
- Java各版本的含义
JavaSE(Java Standard Edition):标准版,定位在个人计算机上的应用.这个版本是Java平台的核心,它提供了非常丰富的API来开发一般个人计算机上的应用程序,包括用户界面接口A ...