本文共 5449 字,大约阅读时间需要 18 分钟。
代码参考 :https://www.cnblogs.com/Anker/p/3475643.html
链表结构参考 :struct list_head { struct list_head *next, *prev; };
下面用代码来说明这个用法:
如下是定义一个包含有 链表节点的结构体。//定义app_info链表结构typedef struct application_info{ int app_id; int up_flow; int down_flow; struct list_head app_info_node;//链表节点}app_info;
下面这是通过链表节点获取整个结构体的宏
在kernel 中,通过list_entry 获取含有节点的结构体的起始地址,也就获取了使用的结构体//计算member在type中的位置#define offsetof(type, member) (size_t)(&((type*)0)->member)//根据member的地址获取type的起始地址#define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member)*__mptr = (ptr); \ (type *)((char *)__mptr - offsetof(type, member)); })#define list_entry(ptr, type, member) \ container_of(ptr, type, member)
在main 函数中,
app_info * app_info_list = (app_info *) malloc(sizeof(app_info)); app_info *app1,*app2,*app3; struct list_head *head = &app_info_list->app_info_node; INIT_LIST_HEAD(head); //插入三个app_info app1 = get_app_info(100,10,20); list_add_tail(&app1->app_info_node, head); app2 = get_app_info(200,20,40); list_add_tail(&app2->app_info_node, head); app3 = get_app_info(400,40,80); list_add_tail(&app3->app_info_node, head); /* 获取含有app3 结构体的值*/ temp_app = list_entry(&app3->app_info_node,app_info,app_info_node);
//计算member在type中的位置#define offsetof(type, member) (size_t)(&((type*)0)->member)//根据member的地址获取type的起始地址#define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member)*__mptr = (ptr); \ (type *)((char *)__mptr - offsetof(type, member)); })
第一部分:
const typeof(((type )0)->member)__mptr = (ptr); 第一部分其实定义了一个__mptr,这个指针将被强制转化,并且指向ptr。结合上述使用的例子: list_entry(&app3->app_info_node,app_info,app_info_node); type就是app_info, ptr则是app3->app_info_node中的地址。 member 是 app_info_node因此宏的第一部分则是定义了一个0指针,指针类型是app_info,则在程序运行时,会开辟出一段内存,内存大小就是app_info结构体的大小,在这个结构体中,有一个成员的类型是app_info_node,因此所定义的__mptr的类型便是app_info_node,而这个指针指向的是app3->app_info_node中的地址。
第二部分:
(type *)((char *)__mptr - offsetof(type, member)); 便是用刚刚获得的地址减去app_info_node在结构体中的偏移值。如下图所示: 是offsetof(type, member) 的含义,也就是member距离结构体开始的偏差。当知识实际的member地址以后,用实际的地址减去偏差的大小,就可以得到整个结构体的实际的地址。#include#include //计算member在type中的位置#define offsetof(type, member) (size_t)(&((type*)0)->member)//根据member的地址获取type的起始地址#define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member)*__mptr = (ptr); \ (type *)((char *)__mptr - offsetof(type, member)); })#define LIST_HEAD_INIT(name) { &(name), &(name) }#define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name)struct list_head { struct list_head *next, *prev; };// name = { &(name), &(name) }static inline void INIT_LIST_HEAD(struct list_head *list){ list->next = list; list->prev = list;}static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next){ next->prev = new; new->next = next; new->prev = prev; prev->next = new;}/** * list_add - add a new entry * @new: new entry to be added * @head: list head to add it after * * Insert a new entry after the specified head. * This is good for implementing stacks. */static inline void list_add(struct list_head *new, struct list_head *head){ __list_add(new, head, head->next);}/** * list_add_tail - add a new entry * @new: new entry to be added * @head: list head to add it before * * Insert a new entry before the specified head. * This is useful for implementing queues. */static inline void list_add_tail(struct list_head *new, struct list_head *head){ __list_add(new, head->prev, head);}//定义app_info链表结构typedef struct application_info{ int app_id; int up_flow; int down_flow; struct list_head app_info_node;//链表节点}app_info;#define list_entry(ptr, type, member) container_of(ptr, type, member)static app_info * get_app_info (int app_id, int up_flow, int down_flow){ app_info * temp = (app_info *)malloc(sizeof(app_info)); temp->app_id = app_id; temp->up_flow = up_flow; temp->down_flow = down_flow; return temp;}int main(void){ app_info * app_info_list = (app_info *) malloc(sizeof(app_info)); app_info *app1,*app2,*app3,*temp_app; struct list_head *head = &app_info_list->app_info_node; INIT_LIST_HEAD(head); //插入三个app_info app1 = get_app_info(100,10,20); list_add_tail(&app1->app_info_node, head); app2 = get_app_info(200,20,40); list_add_tail(&app2->app_info_node, head); app3 = get_app_info(400,40,80); list_add_tail(&app3->app_info_node, head); /* 获取含有app3 结构体的值*/ temp_app = list_entry(&app3->app_info_node,app_info,app_info_node); return 0;}