嵌入式课程设计报告(范例-含排版要求) 下载本文

嵌入式课程设计报告(范例-含排版要求)

1、系统概论

1.1内存管理技术理论 1.1.1为什么必须管理内存

内存管理是计算机编程最为基本的领域之一。在很多脚本语言中,您不必担心内存是如何管理的,这并不能使得内存管理的重要性有一点点降低。对实际编程来说,理解您的内存管理器的能力与局限性至关重要。在大部分系统语言中,比如C和C十十,您必须进行内存管理。追溯到在Apple 11上进行汇编语言编程的时代,那时内存管理还不是个大问题。您实际上在运行整个系统。系统有多少内存,您就有多少内存。您甚至不必费心思去弄明白它有多少内存,因为每一台机器的内存数量都相同。所以,如果内存需要非常固定,那么您只需要选择一个内存范围并使用它即可。不过,即使是在这样一个简单的计算机中,您也会有问题,其是当您不知道程序的每个部分将需要多少内存时。如果您的空间有限,而内存需求是变化的,那么您需要一些方法来满足这些需求:确定您是否有足够的内存来处理数据。从可用的内存中获取一部分内存。向可用内存池(pool)中返回部分内存,以使其可以由程序的其他部分或者其他程序使用。

实现这些需求的程序库称为分配程序(allocators), 因为它们负责分配和回收内存。程序的动态性越强,内存管理就越重要,您的内存分配程序的选择也就更重要。

1.1.2 C风格的内存分配程序

在大部分操作系统中,内存分配由以下两个简单的函数来处理:

Void *malloc(long numbytes):该函数负责分配numbytes大小的内存,并返回指向第一个字节的指针。

Void free(void* firstbyte):如果给定一个由先前的malloc返回的指针,那么该函数会将分配的空间归还给进程的“空闲空间”

Malloc_init将是初始化内存分配程序的函数。它要完成以下三件事:将分配程序标识为己经初始化,找到系统中最后一个有效内存地址,然后建立起指向我们管理的内存的指针。

malloc()的实现有很多,这些实现各有优点与缺点。在设计一个分配程序时,要面临许

0 / 25

嵌入式课程设计报告(范例-含排版要求)

多需要折衷的选择,其中包括:分配的速度;回收的速度;有线程的环境的行为;内存将要被用光时的行为:局部缓存;簿记(Bookkeeping)内存开销;虚拟内存环境中的行为;小的或者大的对象;实时保证。

基于malloc()的内存管理的缺点:不只是我 们的内存管理器有缺点,基于malloc()的内存管理器仍然也有很多缺点,不管您使用的是哪个分配程序。对于那些需要保持长期存储的程序使用malloc()来管理内存可能会非常令人失望。如果您有大量的不固定的内存引用,经常难以知道它们何时被释放。生存期局限于当前函数的内存非常容易管理,但是对于生存期超出该范围的内存来说,管理内存则困难得多。

1.2嵌入式系统对内存管理的要求

1. 快速性:

嵌入式系统中对实时性的保证,要求内存分配要尽可能地快。因此在嵌入式系统中,不可能采用通用操作系统中地复杂而完善地内存策略,一般都采取简单、快速地内存管理策略。 2. 可 靠 性:

嵌入式内存分配地请求必须得到满足,如果分配失败可能会带来灾难性地后果。嵌入式系统应用环境千变万化,其中有一些是对可靠性要求极高地。比如,汽车地自动驾驶系统中,系统检测到即将撞车,如果因为内存分配失败而不能执行相应的操作,就会发生车毁人亡的惨剧,这是不能容忍的。 3. 高 效 性:

内存分配要尽可能减少浪费。不可能为了保证满足所有的内存分配请求而将内存配置的无限大。一方面,嵌入式系统对成本的要求使得内存在其中只是一种有限得资源;另一方面,即使不考虑成本得因素,系统有限得空间决定了可配置得内存容量是很有限的。

1.3嵌入式系统的内存管理特点

许多软件使用虚拟内存,程序过大,可以交换到虚拟存储器上。然而在嵌入式系统中特别要求实时性很强的系统来说,这个功能的确不那么重要,因为这个机制会浪费时间,所以,嵌入式系统的应用程序还是在固定的地方运行比较好。考虑到一些CPU有这方面的特点,也可以保留虚拟存储器的代码,这样能够使得不同进程使用相同代码。如果没有了这个功能,

1 / 25

嵌入式课程设计报告(范例-含排版要求)

每个程序都需要自己的运行库,在内存中就会有库的很多拷贝。其实只需把交换空间的长度设置为零,就可以关闭虚拟内存的页面换入和换出功能。对一些CPU,虚拟存储器的功能提供内存管理,防止不同程序占用相同的地址空间。而在嵌入式系统中,使用简单、绝对的地址空间,因此这种功能也不会起作用。不过这倒提供了防止误写以至于使系统崩溃的功能。很多嵌入式系统习惯使用“全局变量”,让进程共享数据。

1.4内存管理策略概述

内存管理策略大致可分为静态分配和动态分配两大类。

静态分配的可用内存大小在编译时确定。系统初始化阶段预先分配好同定数量的内存,用于存放所有需使用的对象和数据结构。程序运行过程中能且只能使用这内存。动态分配的内存在程序运行时根据需要向系统申请后获得,只有在需要的时候.才分配或归还。由于嵌入式系统的特殊性,开发人员必须在编译内核和开发应用时都参与系统的内存管理。

1.5内存管理模块策略及实现考量 1.5.1简单内存模型

设计之初。最简单直接的一种技术其实就是“不管理”,即所有静态分配在栈中的、动态分配在堆中的变量和数据结构.这二者的分配、释放,全交给编译器、链接程序和运行时库去完成,开发者只需负责合理设置系统栈、堆及任务栈。该模型的一例如图1.

这种方法一般用于操作系统原型的设计.易于配置的、或内存相对宽裕且实时性要求不高的系统的初始设计。

2 / 25

嵌入式课程设计报告(范例-含排版要求)

1.5.2静态方式

为简单、特殊考虑或安全计算,可以只使用静态技术。

静态内存分配在程序执行前进行,效率较高;编译时可精确预估系统内存需求状况;所有分配动作所需时间同定且很小;分配的内存一般不归还。外部碎片很少;程序易测试,可靠性高。这些优点使得静态分配尤其适用于实时应用和高安全系统。

另一方面.静态分配必须考虑可能发生的最坏情况,因此往往分配比实际用量更多的内存。预先分配内存也增加了系统的启动时间。使用静态分配,常需限制系统中同时容纳的进程数,结束旧任务之后才能开始新任务。为限制容量,必须指定程序将存储的最大数据量。这些均会降低系统的可用性。要求在程序执行前就知道所需的内存类型和数量,显然缺少灵活性。

但在只采用静态分配的内存管理方式中,不仅操作系统内核本身。用户进程也必须全部采用静态分配。所以,只能通过以下几种方式设置运行前已指定了大小的任务栈:由用户传递一个静态分配的数组首地址参数给任务构造函数;使用模板参数;继承通用任务类。实现自己的特定任务子类,在子类构造函数中给予其静态分配的栈。

1.5.3动态方式

大部分面向过程和面向对象语言都提供在堆中创建和回收对象的动态管理机制,并在缺省状态下使用。本系统就是采用这样的方式来进行设计的。

静态分配注重效率和安全,动态分配则偏重于灵活性。它避免分配不被使用的内存,降低内存总体需求;改善设计质量,使系统更易编写、扩展和维护:运行时间分配内存减少了系统的启动时间。

当然,灵活性也需付出代价:动态内存管理需要额外区块头部的开销;内存分配和归还需花费处理器时间。典型情况和最坏情况下的内存需求难以估计;内存耗尽的处理会增加代码的复杂度;易造成内存碎片,增加内存的额外开销和不可预测性。

动态分配的内存必须由操作系统管理。通常使用的是链表法。它维持一个已分配和空闲的内存段的链表。

段是进程或是两个进程间的空洞。段链表通常按照地址排序。在进程结束或被换出时更新十分简单、直接。使用双链表结构更易于找到上一个表项以检查是否可以合并。

进程和空洞按照地址顺序存放在链表中时。在系统知道要分配的内存大小的前提下,可

3 / 25