内核对象基类object
这个基类是内核所有对象的基类
在rt-thread/include/rtdef.h文件里有对内核对象基类object的定义
/*** 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_MODULEvoid *module_id; /**< id of application module */
#endifrt_list_t list; /**< list node of kernel object */
};
typedef struct rt_object *rt_object_t; /**< Type for kernel objects. */
object属性有 内核对象名字 , 内核对象类型 , 内核对象标志,还有一个链表节点。
内核对象信息结构体
/*** 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_object_class_type是一个枚举类型,定义如下
/*** 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_Null = 0x00, /**< The object is not used. */RT_Object_Class_Thread = 0x01, /**< The object is a thread. */RT_Object_Class_Semaphore = 0x02, /**< The object is a semaphore. */RT_Object_Class_Mutex = 0x03, /**< The object is a mutex. */RT_Object_Class_Event = 0x04, /**< The object is a event. */RT_Object_Class_MailBox = 0x05, /**< The object is a mail box. */RT_Object_Class_MessageQueue = 0x06, /**< The object is a message queue. */RT_Object_Class_MemHeap = 0x07, /**< The object is a memory heap. */RT_Object_Class_MemPool = 0x08, /**< The object is a memory pool. */RT_Object_Class_Device = 0x09, /**< The object is a device. */RT_Object_Class_Timer = 0x0a, /**< The object is a timer. */RT_Object_Class_Module = 0x0b, /**< The object is a module. */RT_Object_Class_Memory = 0x0c, /**< The object is a memory. */RT_Object_Class_Unknown = 0x0e, /**< The object is unknown. */RT_Object_Class_Static = 0x80 /**< The object is a static object. */
};
有我们常见的线程,信号量等等,最后一个静态类型 就是 第一位 置1。
这里我们只关注 设备类 ,也就是 RT_Object_Class_Device
它们之间具体是个什么关系呢
具体我们来看rt-thread/src/object.c文件
对象容器
对象容器就是一个rt_object_information类型的数组,数组名_object_container,数组长度为RT_Object_Info_Unknown,这个数组中的每个值都是rt_object_information类型。
static struct rt_object_information _object_container[RT_Object_Info_Unknown] =
{/* initialize object container - thread */{RT_Object_Class_Thread, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Thread), sizeof(struct rt_thread)},
#ifdef RT_USING_SEMAPHORE/* initialize object container - semaphore */{RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)},
#endif
#ifdef RT_USING_MUTEX/* initialize object container - mutex */{RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex)},
#endif
#ifdef RT_USING_EVENT/* initialize object container - event */{RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event)},
#endif
#ifdef RT_USING_MAILBOX/* initialize object container - mailbox */{RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_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_Info_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_Info_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_Info_MemPool), sizeof(struct rt_mempool)},
#endif
#ifdef RT_USING_DEVICE/* initialize object container - device */{RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)},
#endif/* initialize object container - timer */{RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)},
#ifdef RT_USING_MODULE/* initialize object container - module */{RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)},
#endif
#ifdef RT_USING_HEAP/* initialize object container - small memory */{RT_Object_Class_Memory, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Memory), sizeof(struct rt_memory)},
#endif
};
这个容器(数组)到底有多大呢,也就是RT_Object_Info_Unknown为几呢?
还是在object.c文件中有一个枚举类型定义rt_object_info_type我们来看一下它。
/** define object_info for the number of _object_container items.*/
enum rt_object_info_type
{RT_Object_Info_Thread = 0, /**< The object is a thread. */
#ifdef RT_USING_SEMAPHORERT_Object_Info_Semaphore, /**< The object is a semaphore. */
#endif
#ifdef RT_USING_MUTEXRT_Object_Info_Mutex, /**< The object is a mutex. */
#endif
#ifdef RT_USING_EVENTRT_Object_Info_Event, /**< The object is a event. */
#endif
#ifdef RT_USING_MAILBOXRT_Object_Info_MailBox, /**< The object is a mail box. */
#endif
#ifdef RT_USING_MESSAGEQUEUERT_Object_Info_MessageQueue, /**< The object is a message queue. */
#endif
#ifdef RT_USING_MEMHEAPRT_Object_Info_MemHeap, /**< The object is a memory heap */
#endif
#ifdef RT_USING_MEMPOOLRT_Object_Info_MemPool, /**< The object is a memory pool. */
#endif
#ifdef RT_USING_DEVICERT_Object_Info_Device, /**< The object is a device */
#endifRT_Object_Info_Timer, /**< The object is a timer. */
#ifdef RT_USING_MODULERT_Object_Info_Module, /**< The object is a module. */
#endif
#ifdef RT_USING_HEAPRT_Object_Info_Memory, /**< The object is a memory. */
#endifRT_Object_Info_Unknown, /**< The object is unknown. */
};
可以看到是由宏定义决定的,宏定义在rtconfig.h文件中。
在这个枚举类型中RT_Object_Info_Thread,RT_Object_Info_Timer,RT_Object_Info_Unknown, 是必然有的。而且RT_Object_Info_Unknown放在最后一个位置。
那么我们现在定义了RT_USING_DEVICE,开启设备类。那么这个枚举类型中一共有四个元素,所以RT_Object_Info_Unknown = 3。
然后 对象容器的长度 就也为3 。里面分别有线程,定时器,还有设备的对象信息rt_object_information。
这个容器直接进行了初试化,每个元素的第二个成员也就是链表通过宏,指向本身进行初始化,也就是这个链表头(哨卫)前后都指向本身。这个链表用来链接同类的对象,后面会学习到。
#define _OBJ_CONTAINER_LIST_INIT(c) \{&(_object_container[c].object_list), &(_object_container[c].object_list)}
内核对象函数
rt_object_get_information
/*** @brief This function will return the specified type of object information.** @param type is the type of object, which can be* RT_Object_Class_Thread/Semaphore/Mutex... etc** @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 (_object_container[index].type == type) return &_object_container[index];return RT_NULL;
}
这个函数用于获取对象的类型信息,输入值是rt_object_class_type ,返回值是rt_object_information 指针。它们俩的关系是rt_object_class_type 是rt_object_information 的第一个成员。也就是说通过类型来获取这个类型的对象的具体信息(后面为了要链表)。
它是咋实现的呢。
通过遍历对象容器_object_container来实现。
rt_object_get_length
/*** @brief This function will return the length of object list in object container.** @param type is the type of object, which can be* RT_Object_Class_Thread/Semaphore/Mutex... etc** @return the length of object list*/
int rt_object_get_length(enum rt_object_class_type type)
{int count = 0;rt_ubase_t level;struct rt_list_node *node = RT_NULL;struct rt_object_information *information = RT_NULL;information = rt_object_get_information((enum rt_object_class_type)type);if (information == RT_NULL) return 0;level = rt_hw_interrupt_disable();/* get the count of objects */rt_list_for_each(node, &(information->object_list)){count ++;}rt_hw_interrupt_enable(level);return count;
}
这个函数用于获取对象链表的长度,输入值是rt_object_class_type ,也就是哪一类对象,然后获取这类对象上的链表链接的长度。
rt_list_for_each是一个宏,用来遍历链表。
/*** rt_list_for_each - iterate over a list* @pos: the rt_list_t * to use as a loop cursor.* @head: the head for your list.*/
#define rt_list_for_each(pos, head) \for (pos = (head)->next; pos != (head); pos = pos->next)
具体实现:先获取类型的对象信息,对象信息里有一个链表节点,这个节点是链表头(哨卫),从次开始遍历链表,从而获取链表长度,注意这个长度是不包含哨卫的。
rt_object_get_pointers
/*** @brief This function will copy the object pointer of the specified type,* with the maximum size specified by maxlen.** @param type is the type of object, which can be* RT_Object_Class_Thread/Semaphore/Mutex... etc** @param pointers is the pointer will be saved to.** @param maxlen is the maximum number of pointers can be saved.** @return the copied number of object pointers.*/
int rt_object_get_pointers(enum rt_object_class_type type, rt_object_t *pointers, int maxlen)
{int index = 0;rt_ubase_t level;struct rt_object *object;struct rt_list_node *node = RT_NULL;struct rt_object_information *information = RT_NULL;if (maxlen <= 0) return 0;information = rt_object_get_information((enum rt_object_class_type)type);if (information == RT_NULL) return 0;level = rt_hw_interrupt_disable();/* retrieve pointer of object */rt_list_for_each(node, &(information->object_list)){object = rt_list_entry(node, struct rt_object, list);pointers[index] = object;index ++;if (index >= maxlen) break;}rt_hw_interrupt_enable(level);return index;
}
rt_object_init
/*** @brief This function will initialize an object and add it to object system* management.** @param object is the specified object to be initialized.** @param type is the object type.** @param name is 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_MODULEstruct rt_dlmodule *module = dlmodule_self();
#endif /* RT_USING_MODULE *//* 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);if (obj) /* skip warning when disable debug */{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);RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));/* lock interrupt */temp = rt_hw_interrupt_disable();#ifdef RT_USING_MODULEif (module){rt_list_insert_after(&(module->object_list), &(object->list));object->module_id = (void *)module;}else
#endif /* RT_USING_MODULE */{/* insert object into information object list */rt_list_insert_after(&(information->object_list), &(object->list));}/* unlock interrupt */rt_hw_interrupt_enable(temp);
}
rt_object_detach
/*** @brief 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);
}
如果使用HEAP,#ifdef RT_USING_HEAP ,则有下面的函数rt_object_allocate和rt_object_delete
rt_object_allocate
/*** @brief This function will allocate an object from object system.** @param type is the type of object.** @param name is 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;
#ifdef RT_USING_MODULEstruct rt_dlmodule *module = dlmodule_self();
#endif /* RT_USING_MODULE */RT_DEBUG_NOT_IN_INTERRUPT;/* get object information */information = rt_object_get_information(type);RT_ASSERT(information != RT_NULL);object = (struct rt_object *)RT_KERNEL_MALLOC(information->object_size);if (object == RT_NULL){/* no memory can be allocated */return RT_NULL;}/* clean memory data of object */rt_memset(object, 0x0, information->object_size);/* initialize object's parameters *//* set object type */object->type = type;/* set object flag */object->flag = 0;/* 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();#ifdef RT_USING_MODULEif (module){rt_list_insert_after(&(module->object_list), &(object->list));object->module_id = (void *)module;}else
#endif /* RT_USING_MODULE */{/* 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;
}
rt_object_delete
/*** @brief This function will delete an object and release object memory.** @param object is 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));/* reset object type */object->type = RT_Object_Class_Null;/* lock interrupt */temp = rt_hw_interrupt_disable();/* remove from old list */rt_list_remove(&(object->list));/* unlock interrupt */rt_hw_interrupt_enable(temp);/* free the memory of object */RT_KERNEL_FREE(object);
}
rt_object_is_systemobject
/*** @brief This function will judge the object is system object or not.** @note Normally, the system object is a static object and the type* of object set to RT_Object_Class_Static.** @param object is 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_object_get_type
/*** @brief This function will return the type of object without* RT_Object_Class_Static flag.** @param object is 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_object_find
/*** @brief This function will find specified name object from object* container.** @param name is the specified name of object.** @param type is 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;information = rt_object_get_information((enum rt_object_class_type)type);/* parameter check */if ((name == RT_NULL) || (information == RT_NULL)) return RT_NULL;/* which is invoke in interrupt status */RT_DEBUG_NOT_IN_INTERRUPT;/* enter critical */rt_enter_critical();/* try to find object */rt_list_for_each(node, &(information->object_list)){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;
}