写出记录型信号量中的wait操作代码_UCOSII操作系统

      99b2ab561028a77cb0806f7c4ea1658d.png

    之前上过一门课程是实时控制系统,这门课程的主要学习目标就是就UCOSII操作系统,这是一个微型的嵌入式操作系统。

  1. UCOS操作系统是怎么管理任务的?

    e630a94dfca1ace8140a8a2e63786821.png

    1. 任务控制块是来管理任务的。

    2. 其中UCOSII操作系统把所有的任务都是通过双向链表来连接到一起的,为什么?我难道不能使用数组来分配空间嘛??

    3. 关键原因是;在整个UCOSII操作系统中,因为我们不知道用户到底需要多少个任务,所以使用链表的话,在编译后才确定的话,要比数组的方式优秀很多。

  2. UCOS操作系统是怎么运行的?

    71a7425ce45e7a4f4286ef9ac463b02b.png

            (1)睡眠态:首先我们的任务是按需分配的,你想要多少个任务的话,那么我们就创建多少个任务。

             (2)就绪状态:如果系统为任务配备了任务控制块并且在任务的就绪表中进行了就绪登记的话,则任务就具备了运行的充分条件,这个时候任务的状态就叫做就绪态。

(3)运行状态:处于就绪状态的任务如果经过UCOSII的位图机制,判断为处于最高优先级的任务的话,那么它就可以获得CPU的使用权,这时候就是运行状态。

(4)中断服务状态:这个真的就没有什么好说的了,连前后台系统都会存在的状态,触发到中断的条件,就会进入中断态,而且不管你是否处于运行态还是怎么样?

以上的4个状态是我认为UCOSII操作系统中必不可少的状态的。

(5)等待状态:这个状态的话,是可以通过裁剪UCOSII内核去掉的,其实这个状态就是为了满足任务之间的通讯和任务与中断服务子程序通信产生的一种状态。

3、UCOSII操作系统任务之间是通过什么进行通信的?

总所周知,UCOSII的任务是一个特殊的函数,没有类型,没有返回值。
里面是一个死循环。

那么为什么它能够跳出来执行别的任务?
它之所以能够跳出来跟别的任务进行通信的话,在下面的用户需要添加的代码中一定是有一个任务切换的函数调用的。实质上是CPU的SR寄存器中的任务堆栈的切换的过程。

那么它怎么跟别的任务进行通信?
常考题:Linux的进程间通信的方式:
信号量(互斥型信号量)、消息队列、共享内存、消息邮箱、事件标志组

其中UCOSII任务之间进行通信的方式除了共享内存,其余都存在。

其中有好几个是类型的:
比如信号量和互斥型信号量。使用这个是可以占用资源,或者同步任务的运行。

比如消息邮箱和消息队列,消息队列也称为多个消息邮箱,都是用来在任务之间传递数据的。

事件标记组:首先请求事件标记组的时候,通过一个整型数的某几个位,如果那几个位都已经置位或者都是为空的话,那么请求事件标记组的任务可以得到运行。

为什么需要互斥型信号量?
因为会产生任务优先级的反转问题?

什么是优先级反转?高优先级任务被低优先级任务剥脱CPU的使用权。
(1)假设现在有一个低的优先级任务占有CPU的内核,同时他占有了一些资源。
(2)此时,来了一个高优先级的任务,它想要得到这个资源,但是这个资源已经被低优先级的任务占有了。
(3)在后来来了一个中等优先级的任务,它因为优先级比低优先级的任务高,但是它的优先级没有高的优先级高,所以它强占CPU的使用权,继续执行。
(4)这时候,形成的情况就是中等优先级的任务比高优先级的任务更加早的执行,形成优先级反转的问题。

解决方案1:
如果低优先级任务占有的那个资源后,后面有更高的优先级任务到来的话,那么就把自己的优先级提高到那个想要占有优先级的任务。

解决方案2:
使用互斥型信号量。因为互斥型信号量,只有你自己请求,自己释放,不能通过别的任务释放,如果你请求一个已经请求过的互斥性信号量的话,那么直接跳过执行。

4、UCOSII操作系统的内存管理

参考:https://www.cnblogs.com/apollius/archive/2013/03/26/2981429.html
UCOSII中动态内存管理的C语言实现:

嵌入式编程比较关心的就是内存大小,在有限的内存中实现动态和静态的代码分配是有学问的,对于像malloc这类在运行的时候从堆中请求内存的函数,诺调用次数太多可能会造成内存的快速消息。

将所有已经分配好的空间计算好,利用全局变量分配到静态的代码空间中。
实际使用时调用自己编写好的内存管理函数从这块静态空间中申请内存。

内存的总体大小是受控的,所有涉及到动态内存的地方实际上都已经被预先分配好,在编译时候写在静态代码区。

每个内存管理块中记录了对应存储的数据地址(EntryAddr),当前可用的数组的地址(FreeAddr),当内存进行分配时候,这一位会进行偏移操作,指向还没有被分配的存储数组。而这些管理块也需要一个总的数组来存储其位置,否则这些指针也是无法初始化的指针。并且新建一个指针(*MMUFREE)指向当前还未被分配,可以用的管理块数组中位置。

可以看出核心思想是,所有需要实际存储的指针都由数组来保存,所有指针最终指向一个实际的变量,诺要使用这种内存管理,第一步要做的就是初始化MMUPOOL初始化内存池。调用MEMInit()之后将内部所有的成员形成一个链表,由MMUFree指向最开头的一个。

这样一来就可以为内存管理块分配一个实际的对象了,调用MemCreate()可以分配一个实际的对象给内存管理块,并且将内存管理与实际的内存存储去联系在一起。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值