赞
踩
我们或许都听说过多线程的概念,其实在多CUP处理器上才真正的存在多线程的概念,每个CPU同时运行处理多个不同的任务。
那在我们的单核CPU的单片机上如何使用“多线程”来处理同一时刻请求的不同任务,来做到”同时“进行呢?
这个时候就需要引入线程管理了。在多线程操作系统中,需要开发人员把一个复杂的应用分解成多个小的、可调度的、
序列化的程序单元。而在 RT-Thread 中,与上述子任务对应的程序实体就是线程。
RT-Thread 的线程调度器是抢占式的,主要的工作就是从就绪线程列表中查找最高优先级线程,保证最高优先级的线程能够被运行,
最高优先级的任务一旦就绪,总能得到 CPU 的使用权。
线程分为五种状态:初始------->就绪------>运行------>挂起------>关闭
空闲线程:优先级最低,永远为就绪态,不被挂起。 用处:回收被删除线程资源(回收僵尸线程)
当线程优先级相同时,采用时间片轮转方式调度,单位一个时钟节拍
比如:A:10,B:5,那么A线程执行10个节拍,B线程执行5个节拍
rt_thread_yield():当前线程被换出,相同优先级的下一个就绪线程将被执行。
rt_schedule():当前线程并不一定被换出,而是在系统中选取就绪的优先级最高的线程执行。
创建线程分为两种方式:1、动态创建线程 2、静态创建线程
两种方式各有优缺点,使用分具体场合。接下来我将具体分析以下两种创建线程方式。
占用RAM空间(RW/ZI 空间),用户分配栈空间和线程句柄
优点:运行时不需要动态分配内存,运行时效率较高,实时性较好,
缺点:内存不能被释放,只能使用 rt_thread_detach() 函数将该线程控制块从对象管理器中脱离。
static rt_uint8_t thread1_stack[512]; //线程栈
static struct rt_thread thread1; //线程控制块
rt_thread_init(&thread1, //线程handle
"thread1", //线程名称
thread1_entry, //线程入口函数
RT_NULL, //线程入口参数
&thread1_stack[0], //线程栈地址
sizeof(thread1_stack), //线程栈大小
15, //线程优先级
5); //线程时间片
rt_thread_startup(&thread1); //线程进入就绪态
依赖与内存堆管理器,系统自动从动态内存堆分配栈空间
优点:创建方便,参数比较静态简便,内存可以由用户释放,调用 rt_thread_delete() 函数就会将这段申请的内存空间重新释放到内存堆中。
缺点:运行时需要动态分配内存,效率没有静态方式高,
static rt_thread_t thread_id = RT_NULL;
thread_id = rt_thread_create("dynamic_th", //名称
dynamic_entry, //线程代码
RT_NULL, //参数
1024, //栈大小
15, //优先级
20); //时间片
if (thread_id != RT_NULL)
rt_thread_startup(thread_id); //线程进入就绪态
else
rt_kprintf("dynamic_thread create failure\n");
return RT_EOK;
使用动态+静态方式,创建两个线程
//动态线程任务 static void dynamic_entry(void *param) { static int cnt = 0; while (++cnt) { rt_kprintf("dynamic_thread is run:%d\n",cnt); rt_thread_mdelay(500); } } //静态线程任务 static void static_entry(void *param) { static int cnt = 0; while (++cnt) { rt_kprintf("static_thread is run:%d\n",cnt); rt_thread_mdelay(500); } } static rt_uint8_t thread1_stack[512]; //线程栈 static struct rt_thread static_thread; //线程控制块 int thread_sample(void) { static rt_thread_t thread_id = RT_NULL; thread_id = rt_thread_create("dynamic_th", //名称 dynamic_entry, //线程代码 RT_NULL, //参数 1024, //栈大小 15, //优先级 20); //时间片 if (thread_id != RT_NULL) rt_thread_startup(thread_id); //线程进入就绪态 else rt_kprintf("dynamic_thread create failure\n"); rt_thread_init(&static_thread, //线程handle "static_thread", //线程名称 static_entry, //线程入口函数 RT_NULL, //线程入口参数 &thread1_stack[0], //线程栈地址 sizeof(thread1_stack), //线程栈大小 15, //线程优先级 5); //线程时间片 rt_thread_startup(&static_thread); //线程进入就绪态 return RT_EOK; } /* 导出到 msh 命令列表中 */ MSH_CMD_EXPORT(thread_sample, thread sample);
打开串口调试助手,输入thread_sample命令,可以看出我们的两个线程以及创建并且正常运行。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。