list_for_each_entry()函数分析
#define list_for_each(pos, head) \
for (pos = (head)->next, prefetch(pos->next); pos != (head); \
pos = pos->next, prefetch(pos->next))
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
假设只有两个结点,则第一个member代表head,list_for_each_entry的作用就是循环遍历每一个pos中的member子项。
list_entry((head)->next, typeof(*pos), member)返回(head)->next物理指针所处位置向前减去offsetof()个字节数据之后, 其父变量pos的物理地址,父变量的类型在编译时由typeof(*pos)自动返回.所以list_for_each_entry遍历head 下面挂接的类型为typeof(*pos)的childs结构体们,当然每个child结构体包含struct list_head node之类相似的双向链表list_head类型项,就这样通过循环pos将依次指向双向链表上的各个child.(member就是child类型中 被定义的变量名)
其中用到了函数list_entry():
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
这个函数的作用在图1中表示就是可以通过已知的指向member子项的指针,获得整个结构体的指针(地址)
#define container_of(ptr, type, member) ({ \
const typeof( ((type *))->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
其中又用到了offsetof()函数:
#define offset_of(type, memb) \
((unsigned long)(&((type *))->memb))
offsetof(TYPE, MEMBER):
该宏在Linux内核代码(版本2.6.22)中定义如下:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER);
分析:
(TYPE *)0,将 0 强制转换为 TYPE 型指针,记 p = (TYPE *)0,p是指向TYPE的指针,它的值是0。那么 p->MEMBER 就是 MEMBER 这个元素了,而&(p->MEMBER)就是MENBER的地址,而基地址为0,这样就巧妙的转化为了TYPE中的偏移量。再把结果强制转 换为size_t型的就OK了,size_t其实也就是int。
typedef __kernel_size_t size_t;
typedef unsigned int __kernel_size_t;
可见,该宏的作用就是求出MEMBER在TYPE中的偏移量。
和函数prefetch:
#define prefetch(x) __builtin_prefetch(x)
其中用到了builtin_prefetch:
#ifndef ARCH_HAS_PREFETCH
#define prefetch(x) __builtin_prefetch(x)
#endif static inline void prefetch_range(void *addr, size_t len)
{
#ifdef ARCH_HAS_PREFETCH
char *cp;
char *end = addr + len; for (cp = addr; cp < end; cp += PREFETCH_STRIDE)
prefetch(cp);
#endif
}
prefetch的含义是告诉cpu那些元素有可能马上就要用到,告诉cpu预取一下,这样可以提高速度。
list_for_each_entry应用:
在程序中的使用如下:
list_for_each_entry(pos , head,member)
{
………………
addr = pos; //对返回值pos的操作,这样更容易去理解list_for_each_entry,可以把它看作for()循环
………………
}
list_for_each_entry()函数分析的更多相关文章
- split(),preg_split()与explode()函数分析与介
split(),preg_split()与explode()函数分析与介 发布时间:2013-06-01 18:32:45 来源:尔玉毕业设计 评论:0 点击:965 split()函数可以实 ...
- string函数分析
string函数分析string函数包含在string.c文件中,经常被C文件使用.1. strcpy函数原型: char* strcpy(char* str1,char* str2);函数功能: 把 ...
- start_amboot()函数分析
一.整体流程 start_amboot()函数是执行完start.S汇编文件后第一个C语言函数,完成的功能自然还是初始化的工作 . 1.全局变量指针r8设定,以及全局变量区清零 2.执行一些类初始化函 ...
- uboot的jumptable_init函数分析
一.函数说明 函数功能:安装系统函数指针 函数位置:common/exports.c 二.函数分析 void jumptable_init (void) { int i; gd->jt = (v ...
- Linux-0.11内核源代码分析系列:内存管理get_free_page()函数分析
Linux-0.11内存管理模块是源码中比較难以理解的部分,如今把笔者个人的理解发表 先发Linux-0.11内核内存管理get_free_page()函数分析 有时间再写其它函数或者文件的:) /* ...
- 31.QPainter-rotate()函数分析-文字旋转不倾斜,图片旋转实现等待
在上章和上上上章: 28.QT-QPainter介绍 30.QT-渐变之QLinearGradient. QConicalGradient.QRadialGradient 学习了QPainter基础绘 ...
- 如何验证一个地址可否使用—— MmIsAddressValid函数分析
又是一篇内核函数分析的博文,我个人觉得Windows的内核是最好的老师,当你想实现一个功能之前可以看看Windows内核是怎么做的,说不定就有灵感呢:) 首先看下官方的注释说明: /*++ Routi ...
- STM32F10X固件库函数——串口清状态位函数分析
STM32F10X固件库函数——串口清状态位函数分析 最近在测试串口热插拔功能的时候,意外发现STM32F10X的串口库函数中,清理串口状态位函数稍稍有点不解.下面是改函数的源码: /******** ...
- 常用string函数分析
string函数分析string函数包含在string.c文件中,经常被C文件使用.1. strcpy函数原型: char* strcpy(char* str1,char* str2);函数功能: 把 ...
随机推荐
- Java基础语法(自定义类、ArrayList集合)
Java基础语法 今日内容介绍 u 自定义类 u ArrayList集合 第1章 引用数据类型(类) 1.1 引用数据类型分类 提到引用数据类型(类),其实我们对它并不陌生,如使用过的Scanner类 ...
- $.ajax同步/异步(async:false/true)
虽然说ajax用来执行异步请求的比较多,但有时还是存在需要同步执行的情况的. 比如:我需要通过ajax取执行请求以返回一个值,这个值在ajax后面是需要使用到的,这时就不能用异步请求了.这时候就需要使 ...
- Hadoop 2.7.0模拟分布式实验环境搭建[亲测]
实验目的: 本实验通过在PC电脑上同时运行3个虚拟机,一个为master节点,两个slave节点. 搭建环境: 主机:mac os 10.10 OS:CenOS 6.5 虚拟机:VMware ...
- SharePoint Online和SharePoint 2016 导出到Excel 表错误
导出到Excel是一个有用的SharePoint功能.偶尔您可能会遇到该功能无法正常工作的情况.有几个原因可能导致此功能无法正常工作. Problem #1 使用非32位Internet Explor ...
- python之删除指定目录指定日期下的日志文件
#=======================================================================================20190521以下脚本 ...
- python之元组,列表和字典的区别
Python语言包含6种内建的序列,其中,有两种主要的类型:列表和元组. 列表是可以修改的,而元组不可以,如果要添加或者删除某些元素,就只能用列表,为了限制某些元素,就会用到元组.一般来说,列表可以替 ...
- python爬虫之路——初识爬虫原理
爬虫主要做两件事 ①模拟计算机对服务器发起Request请求 ②接收服务器端的Response内容并解析,提取所需的信息 互联网页面错综复杂,一次请求不能获取全部信息.就需要设计爬虫的流程. 本书主要 ...
- C、C++、C#中struct的简单比较
比较这三者是因为C.C++.C#这三者存在着一定的血缘关系,而他们三者都有的struct却有很大的不同. 功能 C中的struct是最简单的.只能有成员变量而不能有成员函数. C++和C#中都支持,而 ...
- JNI接口的使用(简单版)
详见 http://b6ec263c.wiz03.com/share/s/2SX2oY0nX4f32CY5ax1bapaL2Qtc5q0tIQjG2yfwaU1MX4Ye
- 【转】 iOS学习之NSBundle介绍和使用
bundle是一个目录,其中包含了程序会使用到的资源.这些资源包含了如图像,声音,编译好的代码,nib文件(用户也会把bundle称为plug-in).对应bundle, cocoa提供了类NSBun ...