RT-Thread内核笔记
基于RT-Thread 3.1.3源码分析
仅作为学习与记录之用,如有错误,欢迎指出
文章目录
1、内核基础
rt-thread实时内核的实现包括:对象管理、线程管理、调度器、线程间通信管理、时钟管理、内存管理。内核最小的资源占用情况是3KB ROM,1.2KB RAM.
2、RT-Thread内核对象模型
静态对象和动态对象
RT-Thread 系统级的基础设施都是一种内核对象,例如线程,信号量,互斥量,定时器等。内核对象分为两类:静态内核对象和动态内核对象,静态内核(rt_thread_init)对象通常放在 RW 段和 ZI 段中,在系统启动后在程序中初始化;动态内核(rt_thread_create)对象则是从内存堆中创建的,而后手工做初始化。
内核对象管理架构
RT-Thread的内核对象包括线程、信号量、互斥量、事件、邮箱、消息队列和定时器、内存池、设备驱动等。初始化后的内核对象将插入到内核对象类型的链表里。
对象容器在代码里的体现是一个 struct rt_object_information 类型的静态数组中的元素,static struct rt_object_information rt_object_container[ ]。
/* 对象容器初始化 */
/* rt-thread中,每一个类型的内核对象都有一个内核对象容器来包容,每个内核容器里有很多个对象(线程容器里有线程1 线程2...),内核对象由链表相连 */
static struct rt_object_information rt_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)},
/* initialize object container - semaphore */
/* 初始化信号量对象容器 */
{RT_Object_Class_Semaphore, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Semaphore), sizeof(struct rt_semaphore)},
/* initialize object container - mutex */
/* 初始化互斥量对象容器 */
{RT_Object_Class_Mutex, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Mutex), sizeof(struct rt_mutex)},
/* initialize object container - event */
/* 初始化事件对象容器 */
{RT_Object_Class_Event, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Event), sizeof(struct rt_event)},
/* initialize object container - mailbox */
/* 初始化邮箱对象容器 */
{RT_Object_Class_MailBox, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MailBox), sizeof(struct rt_mailbox)},
/* initialize object container - message queue */
/* 初始化消息队列对象容器 */
{RT_Object_Class_MessageQueue, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MessageQueue), sizeof(struct rt_messagequeue)},
/* initialize object container - memory heap */
/* 初始化内存堆对象容器 */
{RT_Object_Class_MemHeap, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemHeap), sizeof(struct rt_memheap)},
/* initialize object container - memory pool */
/* 初始化内存池对象容器 */
{RT_Object_Class_MemPool, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_MemPool), sizeof(struct rt_mempool)},
/* initialize object container - device */
/* 初始化设备驱动对象容器 */
{RT_Object_Class_Device, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Device), sizeof(struct rt_device)},
/* initialize object container - timer */
/* 初始化定时器对象容器 */
{RT_Object_Class_Timer, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Timer), sizeof(struct rt_timer)},
/* initialize object container - module */
{RT_Object_Class_Module, _OBJ_CONTAINER_LIST_INIT(RT_Object_Info_Module), sizeof(struct rt_dlmodule)},
};
struct rt_object_information 类型是内核对象容器的数据结构,其结构体的数据结构如下:
/**
* 对象容器的数据结构
*/
struct rt_object_information
{
enum rt_object_class_type type; /* 对象的类型 */
rt_list_t object_list; /* 对象的链表 */
rt_size_t object_size; /* 对象的大小 */
};
- type为内核的类型,内核类型是一个枚举类型,enum rt_object_class_type;
- object_list是链表,新创建的对象将以类型为匹配,插入到相应类型的链表的后面。在容器里,这里的链表其实是相对应内核对象链表的头节点;
- object_size是对象的大小,此大小值与创建时的类型相关,是在容器初始化时就已经指定了的大小。
系统支持的内核对象类型如下:
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_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 /* 对象为静态对象 */
};
对象控制块
内核对象控制块的数据结构(内核对象基类)
struct rt_object
{
/* 注册到系统中的驱动设备名称 */
char name[RT_NAME_MAX];
/* 驱动设备的类型 enum rt_device_class_type */
rt_uint8_t type;
/* 驱动设备注册时指定的标志位,RT_DEVICE_FLAG_RDONLY...... */
rt_uint8_t flag;
#ifdef RT_USING_MODULE
void *module_id; /**< id of application module */
#endif
rt_list_t list; /* 内核对象的链表 */
};
所有的内核对象信息均是继承于rt_object基本对象的属性,并在其基础上扩展了自己相关的属性。
*此图来源RT-THREAD官网
内核对象如果是静态的对象,那么对象类型的最高位将是1(对象类型|RT_Object_Class_Static),否则就是动态对象。系统最多能够的对象类别数目是127个(0111 1111)。
源码分析
初始化对象
初始化对象用于静态对象创建。比如rt_thread_init。
/**
* 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
/* 获取当前内核对象容器 */
/* rt-thread中,每一个类型的内核对象都有一个内核对象容器来包容 */
/* 当前操作是从内核对象容器中,相当于寻找相应对象容器里链表的头结点 */
information = rt_object_get_information(type);
/* 检查当前的对象 */
/* 如果当前对象为空,说明内核容器表里没有这个类型的内核容器 */
RT_ASSERT(information != RT_NULL);
/* 进入临界区 */
rt_enter_critical();
/* try to find object */
/* 寻找对象容器里,是否存在当前要新建的对象 */
for (node = information->object_list.next;
node != &(information->object_list);
node = node->next)
{
struct rt_object *obj;
/* 根据节点找到struct rt_object结构体的首地址,如果这个首地址与传入的结构体首地址相同,则说明这个结构体已经被插入到链表里了 */
obj = rt_list_entry(node, struct rt_object, list);
/* 如果当前要新建的对象已经存在,则会触发断言 */
RT_ASSERT(obj != object);
}
/* 离开临界区 */
rt_exit_critical();
/* initialize object's parameters */
/* set object type to static */
/* 此函数适用于静态创建的对象,将type加上静态,主要是在对象删除(rt_object_delete)时用于判断 */
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));
/* 关闭中断使能 */
temp = rt_hw_interrupt_disable();
#ifdef RT_USING_MODULE
if (module)
{
rt_list_insert_after(&(module->object_list), &(object->list));
object->module_id = (void *)module;
}
else
#endif
{
/* 将对象插入到对应类型的内核容器中的链表里 */
rt_list_insert_after(&(information->object_list), &(object->list));
}
/* 重新打开中断使能 */
rt_hw_interrupt_enable(temp);
}
脱离对象
脱离对象针对的是静态创建的对象。
/**
* 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);
}
初始化对象时,将对象插入到对象容器的链表里了,脱离操作就是从链表里,去除节点。
分配对象
分配对象是动态创建的对象。在动态内存堆中申请空间来创建对象。
/**
* 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;
#ifdef RT_USING_MODULE
struct rt_dlmodule *module = dlmodule_self();
#endif
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_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);
/* return object */
return object;
}
删除对象
删除对象适用于动态创建的对象。
其函数是执行判断当前的对象类型为非静态创建的对象,然后从容器链表里移除当前的节点,最后释放掉动态内存。
/**
* 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));
/* 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);
/* free the memory of object */
RT_KERNEL_FREE(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.
* 该函数用来判断对象是否是系统对象。系统对象是静态对象,type是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;
}
获取对象类型
/**
* 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);
/* 置RT_Object_Class_Static位的是静态变量,type为8位的数据类型 */
return object->type & ~RT_Object_Class_Static;
}
寻找指定名称的类型对象
/**
* 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)
{
/* 此处的node其实指向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;
}