我是靠谱客的博主 单纯春天,最近开发中收集的这篇文章主要介绍linux内核中的list_for_each_entry函数,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

通过结构体成员获取结构体地址

代码仅作解释,不能直接运行

// 结构体 :该结构体里面有一个节点 node,该节点会插入到 一个链表里面
struct input_handler {
	int minor;
	struct list_head	node;
};


// 链表 
struct list_head {
	struct list_head *next, *prev;   
};
	
int main(void)
{
	// 实化一个链表、创建一个结构体指针 -- 忽略链表初始化和节点插入过程,假设这些都已经完成
	struct input_handler *handler;
	struct list_head input_handler_list;


	/* input_handler_list链表里面链接的节点 是 handler结构体里的一个成员 -- node
	   参数①:结构体指针
	   参数②:链表头节点地址
	   参数③:节点名字 */
	list_for_each_entry(handler, &input_handler_list, node)
}


static inline void prefetch(const void *x) {;}


// ----------- 分析1  list_for_each_entry(pos, head, member)	 -------------------------------//
#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))

	/*  
		参数1:pos  = handler 结构体指针 	【解释:pointer of struct】
		参数2: head =  &input_handler_list	【链表头节点的地址,head就变成了一个指针 】
		参数3:member = node				【节点的名字】

	【1】for结构的初始化:得到了链表中 第一个节点的 父结构体指针,得到结构体指针就能操作该结构体
		 pos = list_entry(  (head)->next, typeof(*pos), member  );
	    【1.1】分析list_entry	
			 
	*/



// ----------- 分析2 list_entry(ptr, type, member)	 -------------------------------//
#define list_entry(ptr, type, member) 
	container_of(ptr, type, member)
	/*  
		参数1:ptr  = (head)->next 						【链表头节点的下一个节点】
		参数2: type = typeof(*pos) = typeof(*handler)	【得到结构体类型】
		参数3:member = node							【节点的名字】

	【1.1】list_entry的目的似乎是为了将参数的表达变的简单后,再进行具体操作
		   container_of(ptr, type, member)	
		  【1.1.1】分析container_of
	*/




// ----------- 分析3 container_of(ptr, type, member)  -------------------------------//
#define container_of(ptr, type, member) ({			
	const typeof( ((type *)0)->member ) *__mptr = (ptr);	
	(type *)( (char *)__mptr - offsetof(type,member) );})
	/*  
		参数1:ptr  = (head)->next 						【链表头节点的下一个节点】
		参数2: type = typeof(*pos) = typeof(*handler)	【得到结构体类型】
		参数3:member = node							【节点的名字】

	【1.1.1】
	 第一行分析
	 	简化成:const XXX *__mptr = (ptr); 等价于 const struct list_head *__mptr = input_handler_list->next;
	 	第一行定义了一个指针并初始化,初始化结果就是该指针就变成 head->next指针,存储的是节点的地址
	 		指针类型见下分析:	
			【(type *)0】将0强转为一个地址,地址(0x0000)变成一个type类型结构体的首地址,这里的type就是input_handler
			【typeof( ((type *)0)->member )】 取得这个type类型结构体中名为member的成员 的类型, 这里的member就是node
	第2行分析:
		简化成:(type *)( 地址 ); 等价于 struct input_handler *( 地址 )
		【 (char *)__mptr 】将__mptr从结构体指针转化为无符号整形指针,(char *)__mptr = 节点的地址
							offsetof得到的是一个无符号整形值
		最后结果就是  pos = list_entry( (head)->next, typeof(*pos), member ); 
						  = container_of(ptr, type, member);
						  = ({ const struct list_head *__mptr = input_handler_list->next;
							  (struct input_handler *)( 地址 )	
			*/




// ----------- 分析4 offsetof(TYPE, MEMBER)  -------------------------------//
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
	/*  
		参数2: type = typeof(*pos) = typeof(*handler)	【得到结构体类型】
		参数3:member = node							【节点的名字】

		【(TYPE *)0)->MEMBER】 取结构体中的成员
		【&(TYPE *)0)->MEMBER】取成员地址,由于该结构体地址从0x0开始,所以成员地址就是偏移地址
		【(size_t)addr】将获得的地址强制转化为 无符号整型 size_t
	*/

宏定义使用

代码可直接运行

/*  */
#include <stdio.h>		// ptintf; scanf	
#include <stdlib.h>	// 分配内存,释放内存


// 不要少了() -- ({})
#define XXX ({ 
	int i=5;    
	(int)(i-1);	})

int main(int argc, char **argv)
{

	int p;
	int t;
	p = XXX;


// 不要少了() -- ({})
	t = ({ 					
			int j=10;
			(int)(j-1);	
		 });
		
	printf("%dnr",p);
	printf("%dnr",t);
	return 0;
}

jj

最后

以上就是单纯春天为你收集整理的linux内核中的list_for_each_entry函数的全部内容,希望文章能够帮你解决linux内核中的list_for_each_entry函数所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部