赞
踩
RT-Thread名为实时线程RTOS, 那么什么叫线程?
人们在生活中处理复杂问题时,惯用的方法就是“分而治之”,即把一个大问题分解成多个相对简单、比较容易解决的小问题,小问题逐个被解决了,大问题也就随之解决了。同样,在设计一个较为复杂的应用程序时,也通常把一个大型任务分解成多个小任务,然后通过运行这些小任务,最终达到完成大任务的目的。
在RT-Thread中,与上述小任务对应的程序实体就叫做“线程”(或任务),RT-Thread就是一个能对这些小“线程”进行管理和调度的多“线程”操作系统。线程是实现任务的载体,它是RT-Thread中最基本的调度单位,它描述了一个任务执行的运行环境,也描述了这个任务所处的优先等级。
线程的组成:
RTthread中,线程由三部分组成:线程代码(入口函数)、线程控制块、线程堆栈
线程代码:(线程的代码,我们也常称为,入口函数)
线程控制块
线程控制块是操作系统用于管理线程的一个数据结构,他会存放线程的一些信息,例如优先级、线程名称、线程状态等,也包线程与线程之间连接用的链表结构,线程等待事件的集合等。
struct rt_thread
struct rt_thread *rt_thread
在RTthread参考例程中,是这么一个结构体
我们点进入看一下,内部定义的线程控制块:
线程栈:
RT-Thread每个线程都具有独立的栈空间,当进行线程切换时,系统 会将当前线程的上下文保存在线程栈中,当线程 要恢复运行时,再从线程栈中读取上下文信息,恢复线程的运行。
线程上下文是指线程执行时的环境,具体来说就是各个变量和数据包括所有寄存器变量、堆栈信息、内存信息等。
线程栈在形式上是-段连续的内存空间 ,我们可以通过定 义个数组或者申请 段动态内存来作为线程的栈。
在我们创建线程的时候,我们有两个API函数可以用:
rt_err_t rt_thread_init : 这个API函数,创建一个静态线程。
rt_err_t rt_thread_creat: 这个API函数,创建动态的线程。
通常我们使用的一个启动线程API函数为:
rt_err_t rt_thread_startup(rt_thread_t thread),调用此函数后创建的线程会被加入到线程的就绪队列中,执行调度。
rt_err_t rt_thread_init,在这里,我们讲解一下,在这个API函数中,
rt_err_t rt_thread_creat:这个API函数:
在这个样例中,我们看到,
第一个使用的是动态创建线程,如果创建不成功,就不能启动此线程;可以从这里点进去看所有关于该线程的所有参数,了解线程的构造,并且这里我们可以得到线程1中,如果初始化成功,则返回的是一个指针;
第二个线程使用的静态创建线程,分配内存空间,并创建线程,同动态内存分配差不多;
下面是线程1的线程入口:
这里使用的是一个无线循环的计数器,每等待500ms,计数器+1;
之后就会创建线程;
创建之后,在这里运行此程序,将会看到
线程2,先打印!!!
这是为什么呢?
如果我们仔细去找程序的话,会发现,线程2的优先级设置的时候比线程1的优先级高且没有让出线程时间片的动作(代码),所以先打印了线程2,才打印线程1;
使用静态定义方式时,必须先定义静态的线程控制块,并且定义好堆栈空间,然后调用rt_thread_init来完成线程的初始化工作。采用这种方式,线程控制块和堆栈占用的内存会放在RAM段,这段空间在编译时就已经确定,它不是可以动态分配的,所以不能被释放。而只能使用rt_thread_detach函数将该线程控制块从对象管理器中脱离。
使用动态定义方式rt_thread_create时,RT-Thread会动态申请线程控制块和堆栈空间。在编译时,编译器是不会感知到这段空间的,只有在程序运行时,RT-Thread才会从系统堆中申请分配这段内存空间,当不需要使用该线程时,调用rt_thread_delete函数就会将这段申请的内存空间重新释放到内存堆中。
这两种方式各有利弊,
静态定义方式会占用RAM空间,但是不需要动态分配内存,运行时效率高。
动态方式不会占用额外的RAM空间,占用空间小,但是运行时需要动态分配内存,效率没有静态方式高。
总的来说,这两种方式就是空间和时间效率的平衡,可以根据实际环境需求选择采用具体的分配方式。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。