RT-Thread源码分析3:内核对象模型

文章目录

    • 前情提要
    • 内核对象模型的基本数据结构
      • 内核对象控制块的数据结构
      • 内核对象容器的数据结构
    • 内核对象管理方式
    • 对象操作的主要函数
      • rt_object_get_information(type)
      • rt_object_init(*object, type, *name)
      • rt_object_detach(object)
      • rt_object_is_systemobject(object)
      • rt_object_get_type(object)
      • rt_object_find(*name, type)
    • 关于作者

前情提要

源码文件:RT-Thread Nano V3.1.3\src\object.c (源文件修改日期:2018-01-25)
RT-Thread官网:https://www.rt-thread.org/

RT-Thread内核采用面向对象的设计思想进行设计,系统级的基础设施都是一种内核对象,例如线程,信号量,互斥量,定时器等。

对象容器中包含了每类内核对象的信息,包括对象类型,大小等。

对象容器给每类内核对象分配了一个链表,所有的内核对象都被链接到该链表上。

如图 RT-Thread 的内核对象容器及链表如下图所示:
在这里插入图片描述
从面向对象的观点,可以认为每一种具体对象是抽象对象的派生,继承了基本对象的属性并在此基础上扩展了与自己相关的属性。

在对象管理模块中,定义了通用的数据结构struct rt_object,用来保存各种对象的共同属性,各种具体对象只需要在此基础上加上自己的某些特别的属性,就可以清楚的表示自己的特征。

这种设计方法的优点有:

  1. 提高了系统的可重用性和扩展性,增加新的对象类别很容易,只需要继承通用对象的属性再加少量扩展即可。
  2. 提供统一的对象操作方式,简化了各种具体对象的操作,提高了系统的可靠性。

RT-Thread源码分析3:内核对象模型_第1张图片
由对象控制块 rt_object 派生出来的有:

线程对象、内存池对象、定时器对象、设备对象和 IPC对象(Inter-Process Communication);由 IPC对象派生出信号量、互斥量、事件集、邮箱、消息队列、信号等。

简单的说,在RT-Thread中,所有具体对象数据结构的根就是rt_object

内核对象模型的基本数据结构

内核对象模型有两个数据结构:内核对象控制块、内核对象容器
RT-Thread源码分析3:内核对象模型_第2张图片

内核对象控制块的数据结构

/**
 * Base structure of Kernel 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 */

#ifdef RT_USING_MODULE									/* 请忽略module成员 */
    void      *module_id;                               /**< id of application module */
#endif
    rt_list_t  list;                                    /**< list node of kernel object */
};
typedef struct rt_object *rt_object_t;                  /**< Type for kernel objects. */

内核对象支持的类型(type)有:

enum rt_object_class_type
{
    RT_Object_Class_Null   = 0,                         /**< The object is not used. */
    RT_Object_Class_Thread,                             /**< The object is a thread. */
    RT_Object_Class_Semaphore,                          /**< The object is a semaphore. */
    RT_Object_Class_Mutex,                              /**< The object is a mutex. */
    RT_Object_Class_Event,                              /**< The object is a event. */
    RT_Object_Class_MailBox,                            /**< The object is a mail box. */
    RT_Object_Class_MessageQueue,                       /**< The object is a message queue. */
    RT_Object_Class_MemHeap,                            /**< The object is a memory heap */
    RT_Object_Class_MemPool,                            /**< The object is a memory pool. */
    RT_Object_Class_Device,                             /**< The object is a device */
    RT_Object_Class_Timer,                              /**< The object is a timer. */
    RT_Object_Class_Module,                             /**< The object is a module. */
    RT_Object_Class_Unknown,                            /**< The object is unknown. */
    RT_Object_Class_Static = 0x80                       /**< The object is a static object. */
};

注:如 果 是 静 态 对 象, 那 么 对 象 类 型 的 最 高 位 将 是 1(是RT_Object_Class_Static与其他对象类型的与操作);

内核对象容器的数据结构

/**
 * The information of the kernel object
 */
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-Thread代码在开发编译时,会初始化一个rt_object_information类型的数组,作为内核对象容器。

一类对象由一个容器数组成员管理,该数组成员作为一类对象的链表头管理其他链表节点。

对象容器数组初始化时,数组成员的链表头均指向自己。

当用户初始化/创建的具体对象实例时,对象实例通过链表节点的形式挂接在object_list上。

RT-Thread源码分析3:内核对象模型_第3张图片

对象操作的主要函数

rt_object_get_information(type)

函数功能:根据指定类型,从对象容器数组中获取数组成员的入口地址

函数内容:无

函数应用:核心代码

/**
 * This function will return the specified type of object information.
 *
 * @param type the type of object
 * @return the object type information or RT_NULL
 */
struct rt_object_information *
rt_object_get_information(enum rt_object_class_type type)
{
    int index;

    for (index = 0; index < RT_Object_Info_Unknown; index ++)
        if (rt_object_container[index].type == type) return &rt_object_container[index];

    return RT_NULL;
}

rt_object_init(*object, type, *name)

函数功能:初始化对象,该函数将初始化一个静态对象并将其放到系统对象管理器中。

函数内容:

  • 初始化object对象参数
  • object链接到对象容器链表中

函数应用:核心代码

/**
 * This function will initialize an object and add it to object system
 * management.
 *
 * @param object the specified object to be initialized.
 * 被初始化的指定对象;它必须指向具体的对象内存块,而不能是空指针或野指针
 * @param type the object type.
 * 初始化对象的类型;
 * @param name the object name. In system, the object's name must be unique.
 * 对象的名字;对象的名称。在系统中对象的名称必须唯一。
 */
void rt_object_init(struct rt_object         *object,
                    enum rt_object_class_type type,
                    const char               *name)
{
    register rt_base_t temp;
    struct rt_list_node *node = RT_NULL;
    struct rt_object_information *information;
#ifdef RT_USING_MODULE
    struct rt_dlmodule *module = dlmodule_self();
#endif

    /* get object information */							/* 第一步 */
    information = rt_object_get_information(type);			/* 从对象容器中,获取指定一类对象的数组成员入口地址 */
    RT_ASSERT(information != RT_NULL);
															/* 第二步 */			
    /* check object type to avoid re-initialization */		/* 遍历整个链表,避免重复初始化一个对象实例 */
															/* 但是:这段代码在非调试模式下,无法避免重复 */
    /* enter critical */									
    rt_enter_critical();
    /* try to find object */
    for (node  = information->object_list.next;				/* 遍历链表所有节点 */
            node != &(information->object_list);
            node  = node->next)
    {
        struct rt_object *obj;
															
        obj = rt_list_entry(node, struct rt_object, list);	/* 根据链表节点,找到当前对象结构体的起始地址 */
        RT_ASSERT(obj != object);							/* 个人感觉此处代码可以优化,重复初始化的话,直接返回 */
    }
    /* leave critical */
    rt_exit_critical();										

    /* initialize object's parameters */					/* 第三步:初始化对象参数 */
    /* set object type to static */
    object->type = type | RT_Object_Class_Static;			/* 设置为静态对象类型 */
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);			/* 设置对象实例的name成员 */

    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));	/* 默认不用RT_USING_HOOK时,为空 */

    /* lock interrupt */
    temp = rt_hw_interrupt_disable();						/* 关闭硬件中断 */

#ifdef RT_USING_MODULE										/* 默认不用RT_USING_MODULE */
    if (module)
    {
        rt_list_insert_after(&(module->object_list), &(object->list));	/*  */
        object->module_id = (void *)module;
    }
    else
#endif
    {
        /* insert object into information object list */		/* 第四步:对象实例插入到对象容器对应的链表中 */
        rt_list_insert_after(&(information->object_list), &(object->list));	/* 链表头插入对象 */
    }

    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
}

例如:初始化一个软件定时器对象,把实例对象链接到对象容器中

rt_object_init((rt_object_t)timer, RT_Object_Class_Timer, name);

RT-Thread源码分析3:内核对象模型_第4张图片

rt_object_detach(object)

函数功能:该函数将从对象管理器中脱离一个静态的对象,但是该静态对象并不会被释放。

函数内容:

  • 复位对象类型
  • 从对象容器对应链表中移出对象节点

函数应用:核心代码

/**
 * This function will detach a static object from object system,
 * and the memory of static object is not freed.
 *
 * @param object the specified object to be detached.
 */
void rt_object_detach(rt_object_t object)
{
    register rt_base_t temp;

    /* object check */
    RT_ASSERT(object != RT_NULL);

    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));

    /* reset object type */
    object->type = 0;							/* 复位对象类型 */

    /* lock interrupt */
    temp = rt_hw_interrupt_disable();

    /* remove from old list */
    rt_list_remove(&(object->list));			/* 从链表中删除对象节点 */

    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);
}

例如:

rt_object_detach((rt_object_t)timer);

RT-Thread源码分析3:内核对象模型_第5张图片

rt_object_is_systemobject(object)

函数功能:此函数将判断对象是否为系统对象。

函数内容:通常,系统对象是静态对象, 对象类型设置为RT_Object_Class_Static。

函数应用:通常,应用在断言函数中

/**
 * This function will judge the object is system object or not.
 * Normally, the system object is a static object and the type
 * of object set to RT_Object_Class_Static.
 *
 * @param object the specified object to be judged.
 *
 * @return RT_TRUE if a system object, RT_FALSE for others.
 */
rt_bool_t rt_object_is_systemobject(rt_object_t object)
{
    /* object check */
    RT_ASSERT(object != RT_NULL);

    if (object->type & RT_Object_Class_Static)
        return RT_TRUE;

    return RT_FALSE;
}

例如:

RT_ASSERT(rt_object_is_systemobject(&timer->parent));

rt_object_get_type(object)

函数功能:此函数将返回没有RT_Object_Class_Static标志的对象类型。

函数内容:无

函数应用:通常,应用在断言函数中

/**
 * This function will return the type of object without
 * RT_Object_Class_Static flag.
 *
 * @param object the specified object to be get type.
 *
 * @return the type of object.
 */
rt_uint8_t rt_object_get_type(rt_object_t object)
{
    /* object check */
    RT_ASSERT(object != RT_NULL);

    return object->type & ~RT_Object_Class_Static;
}

例如:

RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);

rt_object_find(*name, type)

函数功能:根据指定对象类型、名字,从对象容器链表中找到对应对象实例的地址

函数内容:无

函数应用:内核代码无调用

/**
 * This function will find specified name object from object
 * container.
 *
 * @param name the specified name of object.
 * @param type the type of object
 *
 * @return the found object or RT_NULL if there is no this object
 * in object container.
 *
 * @note this function shall not be invoked in interrupt status.
 */
rt_object_t rt_object_find(const char *name, rt_uint8_t type)
{
    struct rt_object *object = RT_NULL;
    struct rt_list_node *node = RT_NULL;
    struct rt_object_information *information = RT_NULL;

    /* parameter check */
    if ((name == RT_NULL) || (type > RT_Object_Class_Unknown))
        return RT_NULL;

    /* which is invoke in interrupt status */
    RT_DEBUG_NOT_IN_INTERRUPT;

    /* enter critical */
    rt_enter_critical();

    /* try to find object */
    if (information == RT_NULL)
    {
        information = rt_object_get_information((enum rt_object_class_type)type);	/* 获取这一类对象的链表头 */
        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 */
            rt_exit_critical();

            return object;
        }
    }

    /* leave critical */
    rt_exit_critical();

    return RT_NULL;
}

本文完~

关于作者

微信公众号:萤火虫的电子笔记

分享电子产品开发软、硬件方面知识,51单片机、STM32、ARM、AltiumDesigner PCB设计、开发平台、软件工具等知识分享。

欢迎转发,请注明出处及作者。关注微信公众号,获取最新文章动态。
在这里插入图片描述

你可能感兴趣的:(嵌入式:RTOS,RT-Thread,内核对象,源码分析,代码分析)