在rt_thread_find()函数中,调用了rt_list_entry()函数:
rt_thread_t rt_thread_find(char *name) { struct rt_object_information *information; struct rt_object *object; struct rt_list_node *node; /* enter critical */ if (rt_thread_self() != RT_NULL) rt_enter_critical(); /* try to find device object */ information = rt_object_get_information(RT_Object_Class_Thread); RT_ASSERT(information != RT_NULL); for (node = information->object_list.next; node != &(information->object_list); node = node->next) { object = rt_list_entry(node, struct rt_object, list); if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0) { /* leave critical */ if (rt_thread_self() != RT_NULL) rt_exit_critical(); return (rt_thread_t)object; } } /* leave critical */ if (rt_thread_self() != RT_NULL) rt_exit_critical(); /* not found */ return RT_NULL; } RTM_EXPORT(rt_thread_find);
information(rt_object_information)的定义如下:
struct rt_object_information { enum rt_object_class_type type; /**< object class type */ rt_list_t object_list; /**< object list */ rt_size_t object_size; /**< object size */ };
rt_object的定义如下:
struct rt_object { char name[RT_NAME_MAX]; /**< name of kernel object */ rt_uint8_t type; /**< type of kernel object */ rt_uint8_t flag; /**< flag of kernel object */ rt_list_t list; /**< list node of kernel object */ };
在对象初始化时--rt_object_init()函数,会将该对象指针(rt_list_t list)插入到information的链表中进行管理。
/* insert object into information object list */ rt_list_insert_after(&(information->object_list), &(object->list));
在下面这段代码中information->object_list 是记录RT_Object_Class_Thread类型对象指针的链表。
object = rt_list_entry(node, struct rt_object, list);
node是information->object_list中的某个对象指针,来自于某个rt_object结构体中的成员rt_list_t list。
调用rt_list_entry()函数,根据成员(rt_list_t list)的地址获得结构体 rt_object 的地址(对象指针)。
information = rt_object_get_information(RT_Object_Class_Thread); for (node = information->object_list.next; node != &(information->object_list); node = node->next) { object = rt_list_entry(node, struct rt_object, list); ///// }
下面来看下具体是怎么实现的。
/** * @brief get the struct for this entry * @param node the entry point * @param type the type of structure * @param member the name of list in structure */ #define rt_list_entry(node, type, member) \ rt_container_of(node, type, member) /** * rt_container_of - return the member address of ptr, if the type of ptr is the * struct type. */ #define rt_container_of(ptr, type, member) \ ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
在rt_container_of()函数中
输入值 ptr: object->list, type: struct rt_object, member: rt_list_t list
返回值 object
((type *)0) 把0地址强制转换成了(type *)类型的指针,代入例子就是地址为0的虚拟 (rt_object *) 对象
((type *)0)->member 指向了该type的成员(rt_object下的list)
&((type *)0)->member 获得该成员(list)的地址
因为是从0开始的,因此上述得到的地址也就是list成员在rt_object结构体中的偏移地址
(char *)(ptr) 以字节为单位得到object->list的实际地址
object->list的实际地址 = object的实际地址 + list成员在rt_object结构体中的偏移地址
将这个式子反一下:
object的实际地址 = object->list的实际地址 - list成员在rt_object结构体中的偏移地址
(char *)(ptr) - (unsigned long)(&((type *)0)->member)
最后将该地址强制转换为对象指针(type *)返回
原文:https://www.cnblogs.com/hotwater99/p/12444591.html