RT_Thread学习记录2

        在最近几天,跟着B站上的RT_thread官方教程把RT_Thread的基础教程给看完了。对于RT_thread的学习也告一段落了,本想着学完RT_Thread操作系统之后直接跟着研究生学长一起做学校和某公司合作的项目,在项目中学习。再请教了就业的学长之后,决定先从基础做起,接下来会开始对于C语言,数据结构,计算机组成原理,计算机网络,操作系统等科目进行系统性的学习,巩固和深入自己对于这些知识的了解。今天听了学长的“方法论”,感觉说的很对,不要过度担心找不到工作这种问题,我应该把精力放在自我提升上面,学习知识和技能,把工作作为我学习和技能过程中的一个关卡礼物。

        预计在接下来的的几个月里会深入的学习C语言以及数据结构等内容,可能会更新一些关于这些内容的学习笔记。

        接着总结有关RTT的内容。

        优先级:在RTT中最大优先级为256级,而在STM32操作系统中一般设置对大优先级为32级。高优先级率先占用CPU,同等优先级的线程按照时间片的长短轮流占用CPU。

        钩子函数:RTT中的钩子函数分为空闲钩子函数程调度钩子函数。分别通过rt_thread_idle_sethook()函数和tr_scheduler_sethook()函数进行设定,其中空闲钩子函数的参数是一个函数,意味着在CPU没有线程执行的时候对于该空闲函数进行循环执行。线程调度钩子函数的参数也是一个函数,但是该函数需要有两个形参 为两个进程控制块的指针,用于在这两个线程间切换时进行调度。

        保护临界区,使用rt_enter_critical()函数和rt_exit_critical()函数关闭和开启进程调度,防止在对于变量进行赋值的过程中被中断函数打断。相同rt_hw_interrupt_disable()和rt_hw_interrupt_enable()分别为关闭和开启系统中断。

        信号量:信号量一般用于进行同步通讯。两个信号量full设置为0和empty设置为临界资源数量。占用临界资源时需要用rt_sem_take()函数对于信号量的value值做减1操作。在归还信号量时需要调用rt_sem_release()函数。

        与信号量相似,互斥量mutex用于保证互斥量每次只能被一个线程所访问,在访问互斥资源之前需要rt_mutex_take操作,并在访问互斥资源结束之后rt_mutex_release操作。值得注意的是,对于信号量的使用,有可能导致优先级反转的问题,而互斥量不会发生优先级反转的问题,低优先级的优先级会提升到等待访问该互斥资源的最高优先级的进程的优先级等级,释放完互斥资源之后优先级恢复初始化的等级。且不像semaphore信号量,对于信号量的release操作可以在中断函数中完成,而对于mutex互斥量,只有take到的线程才能对互斥量做release操作。

        事件集:event,事件集可以当作多个信号量,当一个进程的进行需要同时两个不同进程的完成,或者需要两个不同的临街资源的时候,可以使用事件集。事件集的原理和信号量的原理相同,一个事件集中可以有32个事件(由于RTT操作系统为32位操作系统,指针一般都是32位)。线程1可以发送事件集中多个事件集的|或操作,同样,进程2可以拿走事件集中的一个或多个事件,并清除该事件集中被拿走的事件。

        邮箱:互斥量,信号量,事件集都只能传送一个信号,进行线程间通信,而不能进行数据交换。一封邮件固定为4个字节的内容,对于32位处理系统,一个指针的大小即为4字节。线程可以使用send函数把4字节的邮件发送到邮箱里,其他线程可以从邮箱的链表头来接受这些邮件进行处理。

        消息队列:用来接收线程和中断服务程序中发出的不固定长度的消息。并把消息缓存在自己的内存空间中。其他线程能从消息队列中读取相应的消息进行对应的处理。消息列表有空闲列表,消息链表头,消息链表尾。从空闲列表中取出空间写入数据后存放于消息列表尾。RTT消息队列支持金鸡消息,urgent不同于send,是直接把写入的消息框放在消息链表头第一个被取走。消息队列的最小消息框为4B,可以是4字节的倍数,在计算空间时,总占用空间 = n*(消息框大小+4B)  这个 4B指的是指针的大小,每个消息框会有一个指针

        软件定时器:软件定时器在硬件定时器的基础上进行定时,时间到了之后对调用用户设置的timeout回调函数。定时器分为hardtimer和softtimer模式,硬件定时器的超时函数在中断上下文中执行,要求快进快出,hardtimer为默认模式。sfottimer的超时函数在系统的timer线程的上下文中进行,通过宏定义RT_USING_TIMER_SOFT来决定是否使用该模式。开启SFOTTIMER模式之后,需要在定时器初始化中指定一下该模式才能开启该模式。 flag有 one shut ,超时函数只运行一次,。periodic 定时事件到达后周期性的调用超时函数,hardtimer工作在hard模式下, softtimer同。

        内存池:内存池和动态内存堆都是内存管理。内存对可以分配任意大小的内存块,但是分配效率不高,内次都要进行空闲内存的查找,且容易产生内存碎片。内存池用来分配大量大小相同的小内存块。使用内存池可以极大的加快动态内存的分配和释放的速度,且尽可能避免内存的碎片化。RTT的内存池支持挂起,没有空闲内存块时,申请内存的线程会被挂起,因此内存池非常适合用于内存资源同步的情景。对于内存池的使用和堆的使用相似,都需要alloc和free进行申请和释放。每个小内存块的大小最小为4个字节,且以4字节为计数单位。在计算空间时,总占用空间 = n*(消息框大小+4B)  这个 4B指的是指针的大小,每个小内存块会有一个指针。

        

        另外,今天学习到了一些关于C语言指针的内容,算是唤醒了一些早前学习C语言的记忆.

        一级指针:int * p定义了可以指向int类型数据的指针变量,占4个字节,p所存放的地址指向的是值,   一级指针指向的是值存放的地址
        二级指针:int **p定义了一个指针*p,p所存放的地址是值的地址,及p所存放的地址是一个指向int类型变量的指针。 二级指针指向的是指针存放的 地址
        一级指针能通过形参修改实参中指针所指向地址的值
        二级指针能修改实参中指针所指向的地址
        指针数组: int* p[3] 一共有 三个int类型指针 的数组
        数组指针:int (*p) [2] 表明该指针指向了一个数组。
        野指针是指指向不存在存储空间的指针,在定义指针的时候记得的初始化

下面直接把自己看网课的随手记搬上来,用于自己的回忆,比较杂乱。

9.互斥信号量,二值信号量,用于互斥访问
两个信号量full设置为0和empty设置为缓冲区大小
生产者线程优先级高于消费者线程 
生产者:先查看empty信号量中有无空位(是否大于0),take二值信号量之后完成上锁,并开始对于信号量生产的工作,完成之后release二值信号量并接下来release一个full信号量用于表示已有产品。
消费者:rt_sem_take(sem,rt_waiting_froever)先进行查看full信号量有无产品(full是否大于0),接下来就是进行临界区资源消费操作,再释放一个空位empty消耗量用于表示已经有空位给生产者生产产品
在该生产者和消费者的信号量约束之下,生产者最多生产5个产品(例如),只有消费者消费之后才能接着生产新的产品,empty信号量可以通过自定义大小来决定生产者最多生产多少个产品。

 10.互斥量,互斥量用于保证互斥量每次只能被一个线程所访问,有locked和unlocked两种状态,在rtos中有rt_mutex这样一个结构体用作互斥量控制块用于管理互斥量的一个数据结构,struct rt_mutex{
struct rt_ipc_object parent ; rt_uint16_t value ;8t  original_priority; 8t  hold;  struct rt_thread *owner (指向线程控制块的拥有者)}
类似于信号量和线程的定义,互斥量也有动态和静态两种定义方式
静态:struct rt_mutex static_mutex  动态:rt_mutex_t  dynamic_mutex
对于互斥量的操作基本与semaphore相同,只是把semaphore换做了mutex
rt_mutex_init用于静态互斥量的初始化
}
detach函数用于脱离静态互斥量,将互斥量从内核除去
动态互斥量的创建和删除:create 和delete
take 和release 
如果take函数没能够在时间内等待得到一个信号量,会返回一个rt_Etime_out。互斥量支持递归持有:如果一个线程已经take到互斥量了,再次take互斥量这个线程不会被挂起,互斥量管理块hold成员会做+1操作,而在semaphore信号量中,take信号量的操作可能会导致该线程被挂起,例如信号量value不足的情况,因此不能用于IPC中断当中。对于release函数,只有take到的线程才能使用release操作,只能在线程中进行释放。semaphore的release操作可以在中断中进行。  
信号量强调的是运行步骤,两个事件的运行的步骤。互斥量只能锁上的人才能开锁,强调的是许可和权限
使用信号量可能导致线程优先级反转的问题,而互斥量可以通过优先级继承的方法解决优先级反转的问题。

11.优先级反转:指高优先级线程通过互斥访问共享资源时,该IPC对象已经被一低优先级所持有,而这个低优先级线程在运行过称重又被一些(多个)中等优先级的线程抢占,低优先级无法完成工作并释放资源,导致高优先级线程被许多具有低优先级的进程阻塞,高优先级线程实时性得不到保证。
RT thread互斥量的优先级继承,高优先级会把持有临街资源的低优先级拉到和自己优先级相等的等级。占用共享资源的线程的优先级将会提高到等待该资源的进程的最高优先级,释放完该资源后,优先级重新恢复到初始设定值。
对于共享资源资源进行互斥访问的代码段应该尽可能的短,尽快释放共享资源

12.事件集的使用
事件集控制块 struct rt_event{ struct ipc_object parent;  32t set;}
可以通过结构体定义静态事件集 也可以用 rt_event_t 指针来定义动态事件集
init ,detach,create,delete,send (事件指针,32位int事件集)发送事件,
recv接受事件(事件指针,32位事件集,option事件关联方式一般是多个一位1的32位数的|操作:and,or,clear这三种操作可以用|来一起执行,clear在执行后清除事件中对应事件位的值,,timeout,receved指针用于接受32位的事件参数)

13.邮箱
邮箱用于线程中通信,信号量也可以通信但是不能用于数据交换。又想一封邮件只能容纳固定4个字节的内容,对于32位的处理系统,指针的大小即为4个字节,rtt的处理系统就是32位的。线程可以吧4字节的邮件发送到邮箱里,其他线程可以从邮箱中接收这些邮件并进行处理。
邮箱控制块 struct rt_mailbox{ rt_ipc_object parent;  }

14.消息队列的使用
用来接收来自线程和中断服务例程中发出的不固定长度的消息,并把消息缓存存在自己的内存空间中。其他线程能从消息队列中读取相应的消息并进行对应的处理
空闲列表,消息链表头,消息链表尾。从空闲列表拿出消息框写入消息并放在消息链表尾
rtt消息队列支持紧急消息,在消息框写完消息后直接放在消息链表头。
消息队列已满之后,线程发送消息的进程就会失败,读取消息,无消息的话会返回失败或根据一定时间进行等待。
继承于系统的ipc对象  pool

15.软件定时器,在硬件定时器基础上,一时钟滴答为长度单位,提供时钟滴答整数倍的定时能力,时间到之后,会调用用户设置的timeout回调函数,用户需要定时运行的程序会在timeout中进行处理
定时器分为 hardtimer和softtimer模式  
hardtimer的定时器超时函数在中断上下文环境中执行,超时函数的要求和中断服务例程的要求相同,快进快出,在定时器初始化时候指定该模式,是rtt默认定时器模式
softtimer在系统的timer线程的上下文中进行,通过宏定义RT_USING_TIMER_SOFT来决定是否使用该模式。开启SFOTTIMER模式之后,需要在定时器初始化中指定一下该模式才能开启该模式。
struct rt_timer{}
init 中void (*timeout)(形参)是超时处理函数的函数指针。 flag有 oneshut超时函数只运行一次, periodic 定时事件到达后周期性的调用超时函数,hardtimer工作在hard模式休息下, softtimer同。flag需要在前两个和后两个中各取一个逻辑或 | ,
rt_timer_start 启动定时器 stop停止定时器 

16.内存池的使用 
内存池和动态内存堆都是内存管理
内存堆可以分配任意大小的内存块。但是分配效率不高,每次都要进行空闲内存块查找,二是容易产生内存碎片。
内存池是用于分配大量大小相同的小内存块。使用内存池可以极大地加快内存分配和释放的速度,尽可能的避免内存碎片化。RTT的内存池支持线程挂起功能。当内存池中没有空闲的内存块时。申请内存池的线程会被挂起,知道内存池中有新的可用内存快,再将刮起的线程唤醒。因此内存池非常适合需要通过内存资源进行同步的场景
先申请一大块内存,再分钟多个小内存块,再通过链表的方式链接起来的。申请内存时,系统从空闲列表中取出链表头的第一个内存块分配。
init 中的 void* start 参数是内存块的地址,可以使用数组提前定义出来  block_size 最小都是4的整数倍,及一个小的内存块最小4个字节,size指pool的存储空间,block_size指的是小内存块的大小。 小内存块的个数为size /(block_size+4【4是32位操作系统中一个指针的大小】)
rt_mp_alloc 和rt_mp_free要成对使用防止内存块泄漏。
rt_mp_alloc (管理结构体指针,时间)申请内存块 
tr_mp_free ()释放内存块

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值