• rt_list_entry() 函数


    在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 *)返回

  • 相关阅读:
    20172327 2018-2019-1 《程序设计与数据结构》第二周学习总结
    20172327 2018-2019-1 《程序设计与数据结构》第一周学习总结
    20172327 2018-2019-1 《第一行代码Android》第二章学习总结
    20172327 2018-2019-1 《第一行代码Android》第一章学习总结
    学号 2017-2018-2《程序设计与数据结构》课程总结
    20172327 2017-2018-2 《程序设计与数据结构》实验5报告
    Django框架(五)-- 视图层:HttpRequest、HTTPResponse、JsonResponse、CBV和FBV、文件上传
    Django框架(四)-- 路由控制:有名/无名分组、反向解析、路由分发、名称空间、伪静态、APPEND_SLASH、不同版本的Django区别、Django虚拟环境搭建
    Django框架(三)-- orm增删改查、Django生命周期
    Django框架(二)-- 基本配置:app注册、模板配置、静态文件配置、数据库连接配置post和get
  • 原文地址:https://www.cnblogs.com/hotwater99/p/12444591.html
Copyright © 2020-2023  润新知