对象容器的实现
Posted 旭日初扬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对象容器的实现相关的知识,希望对你有一定的参考价值。
一、简介
1.1、什么是对象
在RT-thread中所有的数据结构都是对象。
1.2、什么是容器
- 存放对象(线程)的地方叫容器。
- 目的:RT-Thread 的组件 finsh 通过扫描容器的内核 对象来获取各个内核对象的状态,然后输出调试信息。
二、实现
2.1、对象枚举定义
*线程,信号量,互斥量、事件、邮箱、消息队列、内存堆、内存池、设 备和定时器的枚举定义
即为每个对象打上了一个数字标 签,具体代码如下。 */
enum rt_object_class_type
RT_Object_Class_Thread = 0, // 对象是线程
RT_Object_Class_Semphore, // 对象是信号量
RT_Object_Class_Mutex, // 对象是互斥量
RT_Object_Class_Event, // 对象是事件
RT_Object_Class_MailBox, // 对象是邮箱
RT_Object_MessageQueue, // 对象是消息队列
RT_Objece_Class_MemHeap, // 对象是内存堆
RT_Object_Class_MemPool, // 对象是内存池
RT_Object_Clasee_Device, // 对象是设备
RT_Object_Class_Timer, // 对象是定时器
RT_Object_Class_Module, // 对象是模块
RT_Object_Class_Unknown, // 对象未知
RT_Object_Class_Static, // 对象是静态对象
;
/ C 语言知识:如果枚举类型的成员值没有具体指定,那么后一 个值是在前一个成员值的基础上加 1。
enum rt_object_info_type
RT_Object_info_Thread = 0, // 对象是线程
#ifdef RT_USIGN_SEMAPHORE
RT_Object_Info_Semaphore, // 对象是信号量
#endif
#ifdef RT_USIGN_EVENT // 对象是事件
RT_Object_Info_Event,
#endif
#ifdef RT_USING_MUTEX
RT_Object_Info_Mutex, // 对象是互斥量
#endif
#ifdef RT_USIGN_MAILBOX
RT_Object_Info_mailBox, // 对象是邮箱
#endif
#ifdef RT_USING_MESSAGEQUEUE
RT_Object_Info_MessageQueue, // 对象是消息队列
#endif
#ifdef RT_USING_MEMHEAP
RT_Object_Info_MemHeap, /* 对象是内存堆 */
#endif
#ifdef RT_USING_MEMPOOL
RT_Object_Info_MemPool, /* 对象是内存池 */
#endif
#ifdef RT_USING_DEVICE
RT_Object_Info_Device, /* 对象是设备 */
#endif
RT_Object_Info_Timer, /* 对象是定时器 */
#ifdef RT_USING_MODULE
RT_Object_Info_Module, /* 对象是模块 */
#endif
RT_Object_Info_Unknown, /* 对象未知 */
;
2.2、对象数据类型定义
/*内核对象的基础数据结构
线程控制块中添加数据
*/
struct rt_object
char name[RT_NAME_MAX]; // 定义在config.h 默认8
rt_uint8_t type; // 对象类型
rt_uint8_t flags; // 对象状态
rt_list_t list; // 对象的列表节点 挂载在什么容器中
rt_list_t tlist; // 线程节点列表
void *sp; // 线程栈指针
void *entry; // 线程入口地址
void *parameter; // 线程形参
void *stack_addr; // 线程起始地址
rt_uint32_t stack_size; // 线程栈大小,单位字节
;
typedef struct rt_object *rt_object_t;
2.3、获取指定类型对象信
tatic struct rt_object_information rt_object_container[RT_Object_Info_Unknown] =
// 初始化容器对象 --线程(对象类型)
RT_Object_Class_Thread,
// 初始化对象列表节点头里面的 next 和 prev 两个节点指 针分别指向自身(对象列表节点)
_OBJ_CONTAINER_LIST_INIT(RT_Object_info_Thread),
// 获取线程对象的大小,即整个线程控制块的大小
sizeof(struct rt_thread),
// 初始化对象容器--信号量
#ifdef RT_USING_SEMAPHORE
RT_Object_Class_Semaphore,
_OBJ_CONTANER_LIST_INIT(RT_Object_Info_Semaphore),
sizeof(struct rt_semaphore),
#endif
// 初始化对象容器--互斥量
#ifdef RT_USING_MUTEX
RT_Object_Class_Mutex,
_OBJ_CONTANER_LIST_INIT(RT_Object_Info_Mutex),
sizeof(struct rt_Mutex),
#endif
// 邮箱
#ifdef RT_USIGN_MAILBOX
RT_Object_Class_mailBox,
_OBJ_CONTANER_LIST_INIT(RT_Object_Info_mailBox),
sizeof(struct rt_mailBox) ,
#endif
// 事件 初始化对象容器—事件,由宏 RT_USING_EVENT 决定
#ifdef RT_USIGN_EVENT
RT_Object_Class_Event,
_OBJ_CONTANER_LIST_INIT(RT_Object_Info_Event),
sizeof(struct rt_Event) ,
#endif
// 消息队列
#ifdef RT_USIGN_MESSAGEQUEUE
RT_Object_Class_MessageQueue,
_OBJ_CONTANER_LIST_INIT(RT_Object_Info_MessageQueue),
sizeof(struct rt_MessageQueue) ,
#endif
// 内存堆
#ifdef RT_USIGN_MEMHEAP
RT_Object_Class_MemHeap,
_OBJ_CONTANER_LIST_INIT(RT_Object_Info_MemHeap),
sizeof(struct rt_MemHeap) ,
#endif
// 内存池
#ifdef RT_USIGN_MEMPOOL
RT_Object_Class_MemPool,
_OBJ_CONTANER_LIST_INIT(RT_Object_Info_MemPool),
sizeof(struct rt_Mempool) ,
#endif
// 设备
#ifdef RT_USIGN_DEVICE
RT_Object_Class_Device,
_OBJ_CONTANER_LIST_INIT(RT_Object_Info_Device),
sizeof(struct rt_Device) ,
#endif
// 定时器
#ifdef RT_USIGN_TIMER
RT_Object_Class_Timer,
_OBJ_CONTANER_LIST_INIT(RT_Object_Info_Timer),
sizeof(struct rt_Timer) ,
#endif
// 模块
#ifdef RT_USIGN_MODULE
RT_Object_Class_Module,
_OBJ_CONTANER_LIST_INIT(RT_Object_Info_Module),
sizeof(struct rt_Module) ,
#endif
;
/*获取指定类型的对象*/
/**
* 该函数将初始化对象并将对象添加到对象容器中
*
* @param object 要初始化的对象
* @param type 对象的类型
* @param name 对象的名字,在整个系统中,对象的名字必须是唯一的
*/
// const修饰的变量具有常属性,不可以修改它的值。 修饰形参时,保护形参不被修改
void rt_object_init(struct rt_object *object,enum rt_object_class_type type,const char *name)
// register 定义局部变量 将变量存入寄存器,寄存器中的访问比内快
// 一般的只有编译器将变量优化后才能存入寄存器
register rt_base_t temp;
struct rt_object_information *information;
// 获取对象信息,从容器中拿到对应对象列表头指针
information = rt_object_get_information(type);
// 设置对象类型为静态
object->type = type|RT_Object_Class_Static;
// 拷贝名字
rt_strncpy(object->name,name,RT_NAME_MAX);
// 关中断 接下来链表的操作不希望被中断
temp = rt_hw_interrupt_disable();
// 将对象插入到容器的对应列表中,不同类型的对象所在的列表不一样
rt_list_insert_after(&(information->object_list),&(object->list));
// 使能中断
rt_hw_interrupt_enable(temp);
2.4、对象初始化
/**
* 获取指定类型的对象信息
*
* @param type 对象类似
* @return 对象信息 or RT_NULL
*/
// 指针函数:返回值为指针的函数(地址值) 返回值是一个指向rt_object_information(地址类型)的指针
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;
2.5、调用初始化函数
#include "public.h"
// rt开头+文件名+函数名 表示外部函数,可以由用户调用。
//_rt开头+文件名+函数名 表示内部函数, 只可以在RT_thread内部使用。
/**************************************************************
线程函数
功能:关联线程栈,线程函数实体,线程控制块
所有跟线程相关的函数都在此文件中实现
**************************************************************/
// 1、线程结构体(控制块)指针 2、线程入口 3、线程参数 4、线程栈的起始地址 5、线程栈的大小,单位为字节
rt_err_t rt_thread_init(struct rt_thread *thread,
const char *name,
void (*entry)(void *parameter),
void *parameter,
void *stack_start,
rt_uint32_t stack_size)
// 线程对象初始化
rt_object_init((rt_object_t)thread,RT_Object_Class_Thread,name);
// 初始化线程链表节点,通过它来实现把线程插入各种链表(类似于一个钩子,把线程控制块挂载在各种链表)
rt_list_init(&(thread->tlist));
// 将线程入口保存到线程控制块的 entry 成员中。
thread ->entry = (void*)entry;
// 将线程入口形参保存到线程控制块的 parameter 成员中。
thread ->parameter = parameter;
// 将线程栈起始地址保存到线程控制块的 stack_start 成员中。
thread ->stack_addr = stack_start;
// 将线程栈起大小保存到线程控制块的 stack_size 成员
thread ->stack_size = stack_size;
// 初始化线程栈,并返回线程栈顶指针。rt_hw_stack_init()
thread->sp = (void *)rt_hw_stack_init( thread->entry,
thread->parameter,
(void *)((char *)thread->stack_addr + thread->stack_size - 4) );
// 初始化线程成功返回错误码 RT_EOK
return RT_EOK;
以上是关于对象容器的实现的主要内容,如果未能解决你的问题,请参考以下文章
一起写框架-Ioc内核容器的实现-对象的调用-@Bean注解注入容器的对象