rt-thread的內核對象管理深入解析

rt-thread採用內核對象管理系統來訪問和管理所有內核對象.首先來看看rt-thread的內核對象是如何定義的:

1 數據結構
1.1 對象控制塊
在include/rtdef.h頭文件中可以找到內核對象有結構定義:

/**
 * Base structure of Kernel object
 */
struct rt_object
{
    char       name[RT_NAME_MAX];//名稱
    rt_uint8_t type;//內核對象類型 
    rt_uint8_t flag;//內核對象標誌        
 
#ifdef RT_USING_MODULE
    void      *module_id;//模塊ID
#endif
    rt_list_t  list;//內核對象鏈表節點
};
typedef struct rt_object *rt_object_t;

這裏需要注意地是,上述內核對象控制塊包含了一rt_list_t類型的成員list,這個是一鏈表節點,便於將此內核對象加入到一鏈表中,其結構如下定義:

struct rt_list_node
{
    struct rt_list_node *next; //指向下一節點
    struct rt_list_node *prev; //指向前一節點
};
typedef struct rt_list_node rt_list_t;
 

另內核對象類型取值有如下類型:

/**
 *  The object type can be one of the follows with specific
 *  macros enabled:
 *  - Thread
 *  - Semaphore
 *  - Mutex
 *  - Event
 *  - MailBox
 *  - MessageQueue
 *  - MemHeap
 *  - MemPool
 *  - Device
 *  - Timer
 *  - Module
 *  - Unknown
 *  - Static
 */
enum rt_object_class_type
{
    RT_Object_Class_Thread = 0, //線程
#ifdef RT_USING_SEMAPHORE
    RT_Object_Class_Semaphore, //信號量
#endif
#ifdef RT_USING_MUTEX
    RT_Object_Class_Mutex,   //互斥鎖
#endif
#ifdef RT_USING_EVENT
    RT_Object_Class_Event,  //事件
#endif
#ifdef RT_USING_MAILBOX
    RT_Object_Class_MailBox,  //郵箱
#endif
#ifdef RT_USING_MESSAGEQUEUE
    RT_Object_Class_MessageQueue,  //消息隊列
#endif
#ifdef RT_USING_MEMHEAP
    RT_Object_Class_MemHeap,      //內存堆
#endif
#ifdef RT_USING_MEMPOOL
    RT_Object_Class_MemPool,     //內存池
#endif
#ifdef RT_USING_DEVICE
    RT_Object_Class_Device,     //設備驅動
#endif
    RT_Object_Class_Timer,      //時鐘
#ifdef RT_USING_MODULE
    RT_Object_Class_Module,     //模塊
#endif
    RT_Object_Class_Unknown,      //未知內核對象類型
    RT_Object_Class_Static = 0x80  //rt-thread以此位標誌是否爲系統內核對象
};
需要注意的是,rt-thread將內核對象的type的最高位若爲1,則表示此內核對象爲系統內核對象,否則非系統內核對象.


 1.2 內核對象容器
RTT使用內核對象容器來管理同一類型的內核對象,並將其放入同一鏈表中,便於訪問.內核對象信息的結構如下定義:

/**
 * The information of the kernel object
 */
struct rt_object_information
{
    enum rt_object_class_type type;          //內核對象類型
    rt_list_t                 object_list;   //內核對象鏈表
    rt_size_t                 object_size;   //內核對象所佔的大小
};

 1.3 內核對象管理系統
RTT中,每一類型的內核對象都會有一內核對象容器來包容,這個類型的內核對象容器實際上是用一鏈表(見1.2節所示的內核對象容器結構定義),這個鏈表將所有相同類型的內核對象鏈接起來.由於每一類型都對應着有一個這樣的內核對象容器來管理,那麼所有內核對象容器整體就叫做內核對象管理系統.

如下圖示:

RTT中,內核對象管理系統是用一個rt_object_information數組來實現的,如下:

#define _OBJ_CONTAINER_LIST_INIT(c)\//內核對象容器的鏈表初始化,這裏用一個宏來定義,鏈表的前一節點和後一節點在初始化時都指向本身所在地址
    {&(rt_object_container[c].object_list), &(rt_object_container[c].object_list)}
 
//內核對象管理系統,這裏用rt_object_information數組來實現
struct rt_object_information rt_object_container[RT_Object_Class_Unknown] =
{
    /* initialize object container - thread */)},//線程對象信息
    {RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_Thread), sizeof(struct rt_thread#ifdef RT_USING_SEMAPHORE
    /* initialize object container - semaphore *///信號量對象信息
    {RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_Semaphore), sizeof(struct rt_semaphore)},
#endif
#ifdef RT_USING_MUTEX
    /* initialize object container - mutex *///互斥鎖對象信息
    {RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_Mutex), sizeof(struct rt_mutex)},
#endif
#ifdef RT_USING_EVENT
    /* initialize object container - event *///事件對象信息
    {RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_Event), sizeof(struct rt_event)},
#endif
#ifdef RT_USING_MAILBOX
    /* initialize object container - mailbox *///郵箱對象信息
    {RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_MailBox), sizeof(struct rt_mailbox)},
#endif
#ifdef RT_USING_MESSAGEQUEUE
    /* initialize object container - message queue *///消息隊列對象信息
    {RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_MessageQueue), sizeof(struct rt_messagequeue)},
#endif
#ifdef RT_USING_MEMHEAP
    /* initialize object container - memory heap *///內存堆對象信息
    {RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_MemHeap), sizeof(struct rt_memheap)},
#endif
#ifdef RT_USING_MEMPOOL
    /* initialize object container - memory pool *///內存池對象信息
    {RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_MemPool), sizeof(struct rt_mempool)},
#endif
#ifdef RT_USING_DEVICE
    /* initialize object container - device *///設備驅動對象信息
    {RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_Device), sizeof(struct rt_device)},
#endif
    /* initialize object container - timer *///時鐘對象信息
    {RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_Timer), sizeof(struct rt_timer)},
#ifdef RT_USING_MODULE
    /* initialize object container - module *///模塊對象信息
    {RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Class_Module), sizeof(struct rt_module)},
#endif
};


 2 內核對象接口
2.1 內核對象初始化
RTT提供靜態和動態兩種初始化接口,如下:

靜態初始化是將一個已經存在的且佔有內存空間的對象初始化,它的接口如下:

/**
 * 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_object_information *information;      //對象容器
 
#ifdef RT_USING_MODULE //如果使用了模塊,那麼對象容器指向本線程所包含的對象窗口,否則指向全局對象管理系統中對應的容器
    /* get module object information */
    information = (rt_module_self() != RT_NULL) ? 
        &rt_module_self()->module_object[type] : &rt_object_container[type];
#else
    /* get object information */
    information = &rt_object_container[type];
#endif
 
    /* 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);//給名字賦值
 
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));//使用鉤子函數
 
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();//關中斷
 
    /* insert object into information object list */
    rt_list_insert_after(&(information->object_list), &(object->list));//將初始化的內核對象加入到對應容器中
 
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);//開中斷
}
動態初始化是指對象原本並不存在,在不內存中,需要動態爲其分配內存,其接口如下:


 

/**
 * This function will allocate an object from object system
 *
 * @param type the type of object
 * @param name the object name. In system, the object's name must be unique.
 *
 * @return object
 */
rt_object_t rt_object_allocate(enum rt_object_class_type type, const char *name)//動態初始化接口只需要傳入名字和類型
{
    struct rt_object *object;
    register rt_base_t temp;
    struct rt_object_information *information;//對象容器
 
    RT_DEBUG_NOT_IN_INTERRUPT;
 
#ifdef RT_USING_MODULE//同上面那個接口一樣,獲取對象容器
    /*
     * get module object information,
     * module object should be managed by kernel object container
     */
    information = (rt_module_self() != RT_NULL && (type != RT_Object_Class_Module)) ?
                  &rt_module_self()->module_object[type] : &rt_object_container[type];
#else
    /* get object information */
    information = &rt_object_container[type];
#endif
 
    object = (struct rt_object *)rt_malloc(information->object_size);//爲對象動態分配內存空間
    if (object == RT_NULL)
    {
        /* no memory can be allocated */
        return RT_NULL;
    }
    
    /* initialize object's parameters */
 
    /* set object type */
    object->type = type;//設置類型
 
    /* set object flag */
    object->flag = 0;//設置標誌爲0
 
#ifdef RT_USING_MODULE
    if (rt_module_self() != RT_NULL)
    {
        object->flag |= RT_OBJECT_FLAG_MODULE;//如果使用了模塊功能,則將flag標誌設置爲模塊標誌
    }
    object->module_id = (void *)rt_module_self();//設置模塊ID
#endif
 
    /* copy name */
    rt_strncpy(object->name, name, RT_NAME_MAX);//給名稱賦值
 
    RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));//使用鉤子函數
 
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();//關中斷
 
    /* insert object into information object list */
    rt_list_insert_after(&(information->object_list), &(object->list));//將此對象加入對應容器
 
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);//關中斷
 
    /* return object */
    return object;
}

 2.2 脫離或刪除對象
如果對象是靜態初始化的,那麼對應的是脫離,如果是動態初始化的,則是刪除.

脫離接口如下:

/**
 * 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));//使用鉤子函數
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();//關中斷
 
    /* remove from old list */
    rt_list_remove(&(object->list));//從窗口中移除
 
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);//開中斷
}
刪除接口如下:


 

/**
 * This function will delete an object and release object memory.
 *
 * @param object the specified object to be deleted.
 */
void rt_object_delete(rt_object_t object)
{
    register rt_base_t temp;
 
    /* object check */
    RT_ASSERT(object != RT_NULL);
    RT_ASSERT(!(object->type & RT_Object_Class_Static));//刪除的對象必須是非系統對象
    RT_OBJECT_HOOK_CALL(rt_object_detach_hook, (object));//使用鉤子函數
 
    /* lock interrupt */
    temp = rt_hw_interrupt_disable();//關中斷
 
    /* remove from old list */
    rt_list_remove(&(object->list));//從對應的容器中移除
 
    /* unlock interrupt */
    rt_hw_interrupt_enable(temp);//開中斷
 
#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB)//如果使用了模塊功能且採用的是SLAB動態內存管理模式
    if (object->flag & RT_OBJECT_FLAG_MODULE) 
        rt_module_free((rt_module_t)object->module_id, object);//釋放模塊ID所佔空間
    else
#endif
 
    /* free the memory of object */
    rt_free(object);//釋放內核對象所佔空間
}

 其中rt_list_remove會自動找到對象的前一節點和後一節點,然後刪除本身節點.

2.3 判斷是否爲系統內核對象
/**
 * 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)//RTT是通過內核對象的type的最高位是否爲1來判斷此對象是否爲系統內核對象的
        return RT_TRUE;
 
    return RT_FALSE;
}
2.4  查找內核對象

 

/**
 * 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;
    struct rt_list_node *node;
    struct rt_object_information *information;
    extern volatile rt_uint8_t rt_interrupt_nest;
 
    /* parameter check *///輸入系統檢查
    if ((name == RT_NULL) || (type > RT_Object_Class_Unknown))
        return RT_NULL;
 
    /* which is invoke in interrupt status */
    if (rt_interrupt_nest != 0)//確保當前沒有中斷嵌套
        RT_ASSERT(0);
 
    /* enter critical */
    rt_enter_critical();//進入臨界區
 
    /* try to find object */
    information = &rt_object_container[type];//獲取對應的對象容器
    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;
}
 

3 內核對象系統初始化
/**
 * @ingroup SystemInit
 *
 * This function will initialize system object management.
 *
 * @deprecated since 0.3.0, this function does not need to be invoked
 * in the system initialization.
 */
void rt_system_object_init(void)
{
}

從源代碼可以看出,自從0.3.0以後,RTT就已經沒有必須再使用此接口來對內核對象初始化了,因此,此函數是空的,但在系統初始化時還會保留調用些函數.


 至此,RTT的內核對象系統源碼分析已完!
————————————————
版權聲明:本文爲CSDN博主「flydream0」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/flydream0/article/details/8568463

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章