外观
静态创建和动态创建任务的区别
约 1253 字大约 4 分钟
2026-11-10
常见的RTOS往往会提供两种任务创建接口,例如,在RT-Thread中,可以使用rt_thread_create()和rt_thread_init()。
那么,这两种接口到底有什么差异?在这篇文章中,我将深入内部实现来分析介绍。
使用差异
在RT-Thread中,使用rt_thread_create()创建任务的示例如下所示:
/* 动态创建任务 */
rt_thread_t tid;
tid = rt_thread_create("sensor",
sensor_thread_entry,
RT_NULL,
512, /* 栈大小 */
12, /* 优先级 */
10); /* 时间片 */
if (tid != RT_NULL)
{
rt_thread_startup(tid);
}从代码可以看出,只需要告诉RTOS任务函数入口、栈大小、优先级等参数,就可以自动完成任务的创建。当任务创建完成后,将返回任务的指针rt_thread_t tid。rt_thread_t实际上为指向任务控制块struct rt_thread的指针类型。
而如果使用rt_thread_init()创建任务,则使用示例如下:
/* 静态创建任务 */
static struct rt_thread sensor_thread;
static rt_uint8_t sensor_stack[512];
rt_thread_init(&sensor_thread,
"sensor",
sensor_thread_entry,
RT_NULL,
sensor_stack, /* 用户提供的栈空间 */
512, /* 栈大小 */
12, /* 优先级 */
10); /* 时间片 */
rt_thread_startup(&sensor_thread);此时,需要自己定义任务控制块sensor_thread,以及分配空间sensor_stack。然后,把这些内存的地址传给rt_thread_init()。
由此可见,相比rt_thread_create(),rt_thread_init()省去了任务控制块和栈空间的分配。
内部差异
其实,这两种方式最本质的区别,就是:任务控制块和栈空间的内存由谁来申请。
当调用rt_thread_create()时,RT-Thread内部会调用动态内存分配函数,从系统堆里分配内存,用于任务控制块和栈空间。一旦分配完成,则调用_thread_init()进行任务控制块的初始化。
rt_thread_t rt_thread_create(const char *name,
void (*entry)(void *parameter),
void *parameter,
rt_uint32_t stack_size,
rt_uint8_t priority,
rt_uint32_t tick)
{
struct rt_thread *thread;
void *stack_start;
thread = (struct rt_thread *)rt_object_allocate(RT_Object_Class_Thread,
name);
if (thread == RT_NULL)
return RT_NULL;
// 这里调用malloc()动态分配
stack_start = (void *)RT_KERNEL_MALLOC(stack_size);
if (stack_start == RT_NULL)
{
/* allocate stack failure */
rt_object_delete((rt_object_t)thread);
return RT_NULL;
}
_thread_init(thread,name,entry,parameter,stack_start,stack_size,priority,tick);
return thread;
}当调用rt_thread_init()时,RT-Thread则是直接调用_thread_init()进行任务控制块的初始化。
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_uint8_t priority,
rt_uint32_t tick)
{
/* parameter check */
RT_ASSERT(thread != RT_NULL);
RT_ASSERT(stack_start != RT_NULL);
/* initialize thread object */
rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name);
return _thread_init(thread,
name,
entry,
parameter,
stack_start,
stack_size,
priority,
tick);
}由此可见,在RT-Thread中,rt_thread_create()和rt_thread_init()的差异主要在于:任务栈和任务控制块是从堆中分配,还是由用户指定。
在一些资料中,将调用rt_thread_create()从堆中分配内存的方式,称之为动态创建;而调用rt_thread_init()并传入静态或全局内存的方式,称之为静态创建。
虽说两者的区别看起来不大,但在实际项目中会带来重要的影响。
主要影响
动态创建
动态创建的优点很明显:使用简单,用户只需要指定内存块大小;并且,任务数量可以在运行时动态增减,很灵活。
不过,它有几个隐患。
- 依赖堆管理:系统中必须配置了堆。
- 有分配失败的风险:如果堆太小或者过于碎片化,分配可能失败,用户必须处理这个问题。
- 分配时长不确定:动态内存分配操作的时长是不确定的,堆越碎片化,分配时间越长。对实时性要求很高的系统,这是一个隐患。
静态创建
静态创建的好处是:内存确定、不存在分配不出来的问题。而且不依赖堆管理,可以不配置堆空间,省下来的RAM可以做其他用途。同时,也不存在动态分配方式中的分配时长问题。
它的缺点就是:写起来较麻烦,需要自己定义TCB和栈数组;而且任务数量在编译时就固定了,不能动态增加。
综上所述
综上所述,动态创建和静态创建本质区别在于任务控制块和栈空间的内存由谁申请。动态方便但依赖堆,静态使用起来较为麻烦。
在实际项目中,应根据项目的可靠性要求和资源情况做出合适的选择。
如果你希望系统地学习RTOS底层原理,可以了解我的《RTOS开发与实战》课程。
课程不是简单地讲解FreeRTOS API的使用,而是带你从零开始编写一个RTOS内核,逐步实现任务管理、任务调度、上下文切换、同步与通信等核心机制,并通过一个远程温湿度监控设备项目,将操作系统原理应用到实际嵌入式开发中。
适合希望深入理解RTOS工作原理、提升嵌入式底层开发能力的同学。
