|
本帖最后由 cxzs1234 于 2019-5-12 16:25 编辑
在第六章中主要讲解的是线程的实现。懂点计算机的都知道进程与线程,但我总是把两者给混淆了,感觉两个都差不多应该是一个意思。后来查了一下算是彻底的搞清楚了,一个或多个线程可以组成一个进程。我们应该可以进程比作目标任务,而线程就是完成这个目标的子任务,线程与线程之间相互独立又相互联系。也因此可以知道线程就是最基本最重要的组件了。在FreeRTOS中的Task其实也就是线程的意思。
在定义线程栈中有一句话很重要。“为每个线程都分配独立的栈空间,通常是预定义好的全局数组或动态分配的一段内存空间”。在看视频教程时候就有两种建立线程、信号量、邮箱等都是有两种方法建立方法:静态和动态。在我的理解中,静态分配的内存无法被回收掉一直会存在,对与这样创建的线程更多的是用到是一直存在的线程,这样,而动态分配的内存可以回收,但是可能引起内存碎片化。个人见解,仅供参考。在学习过程中遇到ALIGN(n),一直不理解什么意思,而且好像在哪里见过,经查证,这个东西被用于设置函数变量时候用到,让所作用的结构成员对齐n字节。
线程的执行是由系统调度的,系统为了顺利的调度线程,为每一个线程都定义了一个线程控制块,里面存放线程的信息参数。 在线程初始化时遇到了链表而且是双向链表,链表是一种常见的数据结构,之前有接触过,但就是不知道干什么用的,用到哪里,和没学差不多。这次还真的让自己再次的理解了双向链表的作用。链表就像车链子,那个不用了,拆下来,在将剩下的连接上去,照样还是一个环。在RT-Thread中主要作用是将控制块挂在链表中,便于删除、增加线程后,还是一个完整的链表,从而不影响系统调度其他线程。
在cpuport.c中有个rt_hw_stack_init()函数,该函数用来初始化线程的栈,当线程的第一次运行时,加载到CPU寄存器的参数存放在这个线程栈里面。stack_frame结构体其实就是存储MCU内核里面的那16个寄存器(R0-R15)的,当异常发生或者要切换线程时RTT内核需要将MCU内核的寄存器保存起来,以便恢复该线程是所有的计算参数和程序运行位置(PC)都能恢复原来值,这样该线程会继续运行了。初始化时会看到deadbeef,这个在最早期时程序员对已分配但还未初始化的内存中用该数字来填充,使得程序员在调试时可以很容易地定位到目标内存区域。也成为“Magic Number”。
实现就绪列表中,我们可以看到RT_THREAD_PRIORITY_MAX原来用到这里,这个值越大就要初始化越多的链表,感觉还是这个值最好还是小一点的好,这样可以节省一点内存。
临界段,顾名思义程序执行到一个不能被打断的地方,在这个地方有比较重要的数据,比如我们要串口打印一行数字信息,但是这时候切换任务了,另一个任务也发打印数字信息,这样就会接着上次打印的继续显示,这样打印的数据我们还能看懂么?在临界阶段还可能是外部中断引起的,当然系统调度也是由中断引起的,这样在运行到关键位置时候把所有的中断都关闭就行了,等运行完后在把所有的中断开启就可以避免悲剧的发生,当然ARM有些是关闭掉的,但那一定是很严重的问题了,在重要的数据也没有直接死机重要吧。
此内容由EEWORLD论坛网友cxzs1234原创,如需转载或用于商业用途需征得作者同意并注明出处
|
|