rt-thread采用内核对象管理系统来访问和管理所有内核对象.首先来看看rt-thread的内核对象是如何定义的:
在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,则表示此内核对象为系统内核对象,否则非系统内核对象.
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; //内核对象所占的大小 };
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 };
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; }
如果对象是静态初始化的,那么对应的是脱离,如果是动态初始化的,则是删除.
脱离接口如下:
/** * 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会自动找到对象的前一节点和后一节点,然后删除本身节点.
/** * 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; }
/** * 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; }
/** * @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的内核对象系统源码分析已完!