(一)RTT的线程
RTT的线程相当于别的RTOS的任务,它的组成有三部分:
1、线程代码:类似我们以前在写裸机代码的时候,实现某个功能的函数,在这个地方实现我们的功能逻辑。
2、线程控制块:是一个结构体,每一个线程都有属于自己的结构体,方便RTT来管理,实现诸如任务调度、启动、删除等操作。
3、堆栈:保存对应线程的环境,方便重新获取CPU使用权时恢复离开时的状态。
(二)动态线程与静态线程
静态线程与动态线程的区别在于堆栈,动态线程的堆栈是动态分配的,而静态线程的堆栈是预先就分配好的(通常是定义一个全局数组)。
至于为什么要区分?原因在于两者的堆栈存储的位置不一样,我们选择静态或动态线程是至于空间和速度考虑。当然对于STM32这种单片机,几乎没啥区别。(分析,具体补一篇)
(三)具体举例:线程的创建与删除
还是先看主函数,简单到恐怖如斯:
extern int thread_sample_init(void);
//第三次课 2018.7.24
#include <rtthread.h>
int main(void)
{
/* user app entry */
thread_sample_init();
return 0;
}
看看thread_sample_init()这个函数,它创建了两个线程,具体分析,已经在注释解释的很清楚了。
/* 线程示例的初始化 */
int thread_sample_init(void)
{
/* 创建线程1 */
tid1 = rt_thread_create("t1", /* 线程1的名称是t1 */
thread1_entry, RT_NULL, /* 入口是thread1_entry,参数是RT_NULL */
THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE);//优先级为 25
if (tid1 != RT_NULL) /* 如果获得线程控制块,启动这个线程 */
{
tid1->cleanup = thread1_cleanup;/*thread1_cleanup在线程1退出后执行*/
rt_thread_startup(tid1);
}
/* 创建线程2 */
tid2 = rt_thread_create("t2", /* 线程2的名称是t2 */
thread2_entry, RT_NULL, /* 入口是thread2_entry,参数是RT_NULL */
THREAD_STACK_SIZE, THREAD_PRIORITY - 1, THREAD_TIMESLICE);
if (tid2 != RT_NULL) /* 如果获得线程控制块,启动这个线程 */
{
tid2->cleanup = thread2_cleanup;
rt_thread_startup(tid2);
}
return 0;
}
接着,我们看看线程1和线程2的实体,分别为thread1_entry()和thread2_entry(),线程1的优先级为25,而线程2的优先级为24(数字越小,优先级越高)。线程1是不断打印count字符的大小,而线程2则是延时一段时间后,删除线程1,再延时一段时间后退出。而thread1_cleanup和thread2_cleanup在对应线程退出后执行。
代码注释详细,不懂请留言。
/* 线程1的入口函数 */
static void thread1_entry(void *parameter)
{
rt_uint32_t count = 0;
while (1)
{
/* 线程1采用低优先级运行,一直打印计数值 */
rt_kprintf("thread count: %d\n", count ++);
count ++;
}
}
static void thread1_cleanup(struct rt_thread *tid) //当线程退出的时候执行
{
if (tid != tid1)
{
return ;
}
rt_kprintf("thread1 end\n");
tid1 = RT_NULL;
}
/* 线程2的入口函数 */
static void thread2_entry(void *parameter)
{
/* 线程2拥有较高的优先级,以抢占线程1而获得执行 */
/* 线程2启动后先睡眠10个OS Tick */
rt_thread_delay(10);
/*
* 线程2唤醒后直接删除线程1,删除线程1后,线程1自动脱离就绪线程
* 队列
*/
rt_thread_delete(tid1);
/*
* 线程2继续休眠10个OS Tick然后退出,线程2休眠后应切换到idle线程
* idle线程将执行真正的线程1控制块和线程栈的删除
*/
rt_thread_delay(10);
}
static void thread2_cleanup(struct rt_thread *tid)
{
/*
* 线程2运行结束后也将自动被删除(线程控制块和线程栈在idle线
* 程中释放)
*/
if (tid != tid2)
{
return ;
}
rt_kprintf("thread2 end\n");
tid2 = RT_NULL;
}
实验效果如下,由现象可以,达到预期要求。
(四)总结
由于时间有限,很多东西都没有深究,比如也没有写关于静态线程的代码实现。这些坑慢慢补,个人还是觉得还是要多使用RTT来实现一些具体的项目,遇到问题后,努力解决后,能更加理解这个操作系统。
总结一下,用到的函数: