欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

linux内核中的list_for_each_entry函数

程序员文章站 2022-03-09 21:44:44
...

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

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

// 结构体 :该结构体里面有一个节点 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("%d\n\r",p);
	printf("%d\n\r",t);
	return 0;
}

jj

相关标签: c++ 内核 linux