线程
在RT-THread中,最小任务对应的是线程,RT-Thread就是一个能对这些线程进行管理和调度的多线程操作系统。
线程是实现任务的载体,它是RT-Thread中最基本的调度单元,描述了一个任务执行的运行环境,和这个任务所处的优先级。
RT-Thread中,线程由三部分构成:线程代码(入口函数)、线程控制块、线程堆栈;
- 线程代码(入口函数)包含以下两种形式:
- 线程控制块
包含用于管理线程的信息,如线程优先级、线程名称、线程状态等,也包含线程与线程之间连接用的链表结构,线程等待时间集合等
struct rt_thread;
struct rt_thread *rt_thread_t;
在rtdef.h中
/**
* Thread structure
*/
struct rt_thread
{
/* rt object */
char name[RT_NAME_MAX]; /**< the name of thread */
rt_uint8_t type; /**< type of object */
rt_uint8_t flags; /**< thread's flags */
#ifdef RT_USING_MODULE
void *module_id; /**< id of application module */
#endif
rt_list_t list; /**< the object list */
rt_list_t tlist; /**< the thread list */
/* stack point and entry */
void *sp; /**< stack point */
void *entry; /**< entry */
void *parameter; /**< parameter */
void *stack_addr; /**< stack address */
rt_uint32_t stack_size; /**< stack size */
/* error code */
rt_err_t error; /**< error code */
rt_uint8_t stat; /**< thread status */
/* priority */
rt_uint8_t current_priority; /**< current priority */
rt_uint8_t init_priority; /**< initialized priority */
#if RT_THREAD_PRIORITY_MAX > 32
rt_uint8_t number;
rt_uint8_t high_mask;
#endif
rt_uint32_t number_mask;
#if defined(RT_USING_EVENT)
/* thread event */
rt_uint32_t event_set;
rt_uint8_t event_info;
#endif
#if defined(RT_USING_SIGNALS)
rt_sigset_t sig_pending; /**< the pending signals */
rt_sigset_t sig_mask; /**< the mask bits of signal */
void *sig_ret; /**< the return stack pointer from signal */
rt_sighandler_t *sig_vectors; /**< vectors of signal handler */
void *si_list; /**< the signal infor list */
#endif
rt_ubase_t init_tick; /**< thread's initialized tick */
rt_ubase_t remaining_tick; /**< remaining tick */
struct rt_timer thread_timer; /**< built-in thread timer */
void (*cleanup)(struct rt_thread *tid); /**< cleanup function when thread exit */
/* light weight process if present */
#ifdef RT_USING_LWP
void *lwp;
#endif
rt_uint32_t user_data; /**< private user data beyond this thread */
};
typedef struct rt_thread *rt_thread_t;
/*@}*/
-
线程栈
RTT中没个线程都具有独立的栈空间,在进行线程切换时,系统会将当前线程的上下文保存在线程中,当线程要恢复运行时,再从线程栈读取上下文信息,恢复线程的运行;
线程上下文是指线程执行的环境,具体来说就是各个变量和数据包括所有寄存器变量、堆栈信息、内存信息等;
线程栈在形式上是一段连续的内存空间,可以通过定义一个数组或者申请一段动态内存来作为线程的栈。 -
线程创建
1-创建线程
(1)创建静态线程:
rt_err_t rt_thread_init(struct_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)
(2)创建动态线程:
rt_err_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)
2-启动线程
rt_err_t rt_thread_startup(rt_thread_t thread)
通过使用这个函数将创建的线程加入到线程就绪队列,执行调度;
官方示例代码:
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-08-24 yangjie the first version
*/
/*
* 程序清单:创建/删除、初始化线程
*
* 这个例子会创建两个线程,一个动态线程,一个静态线程。
* 一个线程在运行完毕后自动被系统删除,另一个线程一直打印计数。
*/
#include <rtthread.h>
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5
static rt_thread_t tid1 = RT_NULL;
/* 线程1的入口函数 */
static void thread1_entry(void *parameter)
{
rt_uint32_t count = 0;
while (1)
{
/* 线程1采用低优先级运行,一直打印计数值 */
rt_kprintf("thread1 count: %d\n", count ++);
rt_thread_mdelay(500);
}
}
ALIGN(RT_ALIGN_SIZE)
static char thread2_stack[1024];
static struct rt_thread thread2;
/* 线程2入口 */
static void thread2_entry(void *param)
{
rt_uint32_t count = 0;
/* 线程2拥有较高的优先级,以抢占线程1而获得执行 */
for (count = 0; count < 10 ; count++)
{
/* 线程2打印计数值 */
rt_kprintf("thread2 count: %d\n", count);
}
rt_kprintf("thread2 exit\n");
/* 线程2运行结束后也将自动被系统删除
(线程控制块和线程栈依然在idle线程中释放) */
}
/* 删除线程示例的初始化 */
int thread_sample(void)
{
/* 创建线程1,名称是thread1,入口是thread1_entry*/
tid1 = rt_thread_create("thread1",
thread1_entry, RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY, THREAD_TIMESLICE);
/* 如果获得线程控制块,启动这个线程 */
if (tid1 != RT_NULL)
rt_thread_startup(tid1);
/* 初始化线程2,名称是thread2,入口是thread2_entry */
rt_thread_init(&thread2,
"thread2",
thread2_entry,
RT_NULL,
&thread2_stack[0],
sizeof(thread2_stack),
THREAD_PRIORITY - 1, THREAD_TIMESLICE);
rt_thread_startup(&thread2);
return 0;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(thread_sample, thread sample);
仿真运行结果: