阻塞与非阻塞的内存函数
实际中,设计良好的内存分配函数应当允许进行永久阻塞(bloking forever)、时限阻塞(blocking for a timeout period)或永不阻塞(no blocking at all)的分配。
一个阻塞内存分配函数可以使用一个计数信号量或者一个互斥信号量锁(mutex lock)实现。 分配请求必须首先成功的获得计数信号量,接着获取互斥信号量锁。
当阻塞内存分配用同步原语开放时,计数信号量和互斥信号量锁的使用消除了优先权倒置的问题。也就是让分配与回收之间的操作成为不可被中断的原语。然后借助计数信号量和互斥信号量锁解决了任务读藏数据,或读后改等错误,也防止一个较低的任务占用了内存资源,而较高的任务却因为无法获得内存资源而被迫阻塞的优先级倒置问题。
硬件内存管理单元
涉及到了虚拟内存管理。这是一种带海量存储(mass storage)的技术。这个特征允许运行一个比内存更大的程序。(牺牲时间换来的)具体内容读我笔记的人一定知道。内存管理单元MMU(Memory Management Unit)提供几个功能。首先,MMU对每次内存访问将虚拟地址转换为物理地址,其次MMU提供内存保护。
如果一个MMU在嵌入系统中是开放的,则物理地址典型的分为页(page)。硬件根据页的属性增强了内存的访问。企图向一个只读的内存区域写,将触发一个内存访问异常。
说了这么多内存管理,其实MyOS(51)的运行环境中只有128B或者256B的内存空间。少的可怜!不过这可以启示未来MyOS的其它处理器版本!
用并发将应用模块化
设计实时系统 应用 时,必须完成许多活动。一组活动需要标识出确定的元素。最终,设计队伍必须考虑如何将应用分解为并发的任务。
以下内容将是如何分解与注意事项
由表及里分解应用的方法
大多数情况下,在实时嵌入式系统开始工作之前,设计者坚持一组需求。如果需求不明确,则首先的行动之一式保证多个需求固定下来。二义性的区域也必须得到丰富。详细需求应当从文档中获得,如 软件需求规格说明SRS(Software Requirement Specification)
由表及里的方法(outside-in approach)这种方法遵循一个过程标识系统的输入和输出,并将其表示为简单的高层的上下文框图。*中间的圈表示软件应用 *围绕在周围的矩形表示应用的输入和输出设备 *箭头标由具体的含义名,表示输入和输出通信的流程。
标识并发的指导原则和建议
由表及里分解应用的方法是一种实践方法的例子而已,还有其它的多种设计方式。这种方式确定某些明确的要求处理实践和动作的任务。进一步对此框图进行细化将产生另外的任务。
并发单元:
将一个应用并发封装为可管理单元是非常重要的。一个并发单元(unit of concurrency)可以是一个任务或者一个进程,也可以是任何可调度的,可以竞争CPU处理时间的执行线程。(虽然ISR不能被调度与其它例程并发的运行,但仍将其作为并发设计)
分解过程主要是优化并行执行,将实时应用的性能和响应性最大化。
伪与真并发执行:
单处理器主要是在进行伪并发执行,因为一个CPU上只有一个程序计数器(也叫指令指针)可以使用,因此,在任何时刻都只有一个指令在运行。
多处理器情况下,基本RTOS典型的是分布式的。这时整个系统是在真并发执行,但是每个CPU仍然是在伪并发执行的。
设计并发任务时的指导原则:
原则1:标识设备的依赖性
我的理解就是将外部设备分为主动与被动两种。然后根据不同类型设备的特性,来编制与指派任务。对于中断产生设备的机制与我设想的完全相同。将ISR设计成为一种调度,来处理多个设备产生的中断,通过一个通信机制,通知一个在任务级别的服务程序来进行处理。当然这个任务级别的服务程序被给予最高的任务优先级。
主动设备的建议如下:
1:为单独的主动异步I/O设备指派单独的任务。
2:对不经常产生中断的且具有很长死线的I/O设备进行任务组合。
3:为具有不同输入和输出速率的设备指派单独的任务。因为速率高的I/O设备因为着容许处理的时间短。
4:给中断产生设备相关的任务指派更高的优先级。
5:指派一个资源控制任务控制对I/O设备的访问。
6:为必须交给多个任务的I/O设备请求一个事件分发任务。
被动设备的建议如下:
1:当与这些设备的通信时非周期并且死线非常遥远,则指派一个单任务与被动设备接口。
2:指派发开的多个表决任务给被动设备发送周期性的请求。
3:通过计时器事件触发表决请求。
4:指派相对较高优先级别表决具有相对低周期的任务。但是要慎用,因为过多的表决导致负载的剧增。
原则2:标识事件的依赖性
原则3:标识时间的依赖性
a:标识关键和紧急活动
b:标识不同的周期性执行速率
c:标识临时聚合
原则4:标识计算性边界活动 计算性边界活动通常被甚至成较低的优先权。因为她们有遥远的死线和漫长的运算时间。当不需要更关键的任务时,她们得到时间运行。
原则5:标识功能性聚合
功能性聚合要求把相对紧密的执行活动函数组或代码列收集成为一个单独的任务。另外,如果两个任务紧密耦合(传递大量数据),也应当考虑合并为一个任务。
原则6:标识服务于特殊目的的任务
原则7:标识顺序聚合
把那些必须按照给定顺序发生的活动组合成为一个任务,从而进一步强调顺序操作的需求
可调度性分析和速率单调性分析
可调度性分析决定是否所有的任务可以调度运行,并且满足他们使用调度算法建立的死线,同时仍然要获得优化的处理器利用率。注意!分析只观察如何满足时序要求,而不是功能要求。
测试方法有RMA基本的可调度性测试,公式如下:
C1/T1+……Cn/Tn<=U(n)=n(2^(1/n)-1) 1<=i<=n
Ci是周期性任务i相关的最坏执行时间
Ti是任务i相关的周期
n是任务的个数
当不等式成立时说明所有任务可以满足死线。
扩展的RMA可调度性测试,公式如下:
C1/T1+……+Ci/Ti+Bi/Ti<=U(i)=i(2^(1/i)-1) 1<=i<=n
Bi是被经历的最长阻塞时间
不等式成立说明第i个任务可以满足死线的,同时它是可调度的。