RTT小师弟 · 2021年03月19日

RT-Thread 内核学习笔记 - 内核对象rt_object

背景

学习下RT-Thread,除了基础的应用,应该花点时间,研究下内核的实现
RT-Thread内核,整体代码量不大,很适合研究,后期,打算在这个基础上,开发一些软件包。
之前了解了一点数据结构的知识,感觉,没有真正的使用起来,程序=数据结构+算法。
万事开头难,先从最基本的概念开始。

内核对象控制块

对象(object)结构体

image

对象可以派生具体的对象

image

导火索

今天,想仔细看看RT-Thread 的内核的对象,基本上都是结构体,看看结构体的大小
单片机的程序,一般短小精悍是每个嵌入式软件工程师追求的,实现相同功能,占用最少资源,意味着硬件成本会进一步降低。
编写一个函数,打印一下rt_object 等对象的结构体占用的内存RAM大小。

void print_kernel_object_size(void)
{

struct rt_object obj;
rt_kprintf("struct rt_object size=%d\n", sizeof(obj));
rt_kprintf("rt_list_t size=%d\n", sizeof(rt_list_t));
rt_kprintf("struct rt_timer size=%d\n", sizeof(struct rt_timer));
rt_kprintf("struct rt_thread size=%d\n", sizeof(struct rt_thread));
rt_kprintf("struct rt_ipc_object size=%d\n", sizeof(struct rt_ipc_object));
rt_kprintf("struct rt_semaphore size=%d\n", sizeof(struct rt_semaphore));
rt_kprintf("struct rt_mutex size=%d\n", sizeof(struct rt_mutex));
rt_kprintf("struct rt_event size=%d\n", sizeof(struct rt_event));
rt_kprintf("struct rt_mailbox size=%d\n", sizeof(struct rt_mailbox));
rt_kprintf("struct rt_messagequeue size=%d\n", sizeof(struct rt_messagequeue));
rt_kprintf("struct rt_mempool size=%d\n", sizeof(struct rt_mempool));
rt_kprintf("struct rt_device size=%d\n", sizeof(struct rt_device));
rt_kprintf("struct rt_device_graphic_info size=%d\n", sizeof(struct rt_device_graphic_info));

}

MSH_CMD_EXPORT(print_kernel_object_size, print_kernel_object_size); //导出命令

运行效果

msh />pri
print_kernel_object_size
msh />print_kernel_object_size
struct rt_object size=20
rt_list_t size=8
struct rt_timer size=44
struct rt_thread size=128
struct rt_ipc_object size=28
struct rt_semaphore size=32
struct rt_mutex size=36
struct rt_event size=32
struct rt_mailbox size=48
struct rt_messagequeue size=60
struct rt_mempool size=52
struct rt_device size=80
struct rt_device_graphic_info size=12

struct rt_object size=20,说明当:RT_NAME_MAX为8时,内核对象大小为:20字节(8+ (4)+8 = 20)
不难分析,rt_uint8_t type,rt_uint8_t flag,因为内存对齐,占用了2+2=4个字节。(Keil MDK5 armcc)

/**

  • 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_MODULE

void      *module_id;                               /**< id of application module */

endif

rt_list_t  list;                                    /**< list node of kernel object */

};

当我尝试更改内核对象中的成员:rt_uint8_t type --> rt_uint32_t type,验证下结构体大小变化时,发生了Assert 栈溢出。

image

\ | /

  • RT - Thread Operating System
    / | \ 4.0.3 build Jan 16 2021
    2006 - 2020 Copyright by rt-thread team

thread: stack overflow

经过调试,发现是线程结构体引起的对齐问题。

image

看来,还是不要直接改基础的内核控制块。
要改rt_object的结构体大小,其他对象派生的对象,都要注意下。

总结

通过打印rt_object等结构体的大小,了解了rt_object的基本构成。
基本了解到了其他内核对象,如rt_thread(线程控制块),rt_timer(定时器控制块),rt_list_t(双向链表)的RAM占用大小。
了解到rt_object的派生方式,增加其他对象的特殊属性,构成其他的对象,用链表链接起来,用于OS管理。

原文链接:https://club.rt-thread.org/ask/article/2493.html
推荐阅读
关注数
8063
内容数
181
小而美的物联网操作系统,经过14年的累积发展,RT-Thread 已经拥有一个国内最大的嵌入式开源社区,同时被广泛应用于能源、车载、医疗、消费电子等多个行业,累积装机量超过4亿台,成为国人自主开发、国内最成熟稳定和装机量最大的开源 RTOS。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息