对图像切槽

    本章之前提到过,每个设备任务可以分配到的内存数量是有限的,但究竟有限到什么程度,可能说出来会让有些人大吃一惊,因为现在对于一台桌面台式机,有500M或者1G的内存已经很普遍了。分配给SSI和RAC/OM用于图像数据存储任务的初始内存差230K是10M(确切地说是10255360个字节)。大家讨论过,在太空飞行器着陆后,可以增加其内存分配。这意味着任何内存管理机制都必须很灵活,而这也是设计的基本要求。默认的存储机制需要至少处理四个SSI图片(或者两对,每个“眼睛”包含一个图片),而且至少四张RAC/OM图片,这些图片都存储在相同的内存空间中。这种零散的大小分配方式意味着至少在初始阶段,不可能“挤进”超过四张的全尺寸大小的SSI图像。

    在嵌入式系统中,使用动态内存分配通常被认为是一个非常糟糕的想法。为了避免内存碎片、内存泄露、空指针、莫名其妙的程序崩溃以及可能完全无法完成任务,飞行软件编码规范禁止使用动态内存分配(C的malloc函数及其家族)。这意味着不论分配给成像软件的内存有多小,它都需要自己在该内存范围内管理图像数据,而且软件必须健壮、可靠。

    为了满足以上需求,成像软件的解决方案是在启动时,使用一组函数作为内存管理器,用来为ICS预分配内存。内存管理器是图像数据处理的核心组件。为了避免冲突,采用阻塞信号来控制三个成像任务间的共享访问(实际上,在太空飞行器软件中的任何一个任务都可能使用共享内存,但实际情况是只有照相机使用共享内存)。

    静态内存分配被划分成“槽”,它可能大到足以容纳一个全尺寸大小的SSI图像,或者是较小的RAC/OM图像。图3-5显示了ICS图像存储空间的默认组织方式。

    对图像切槽 - 图1

    图 3-5:默认的图像“槽”分配

    这只是一种可能的配置方式,每种类型的槽的个数可以通过接收从地面传输上来的命令而随时改变。

    每个图像还包含一个包含头数据的关联结构。图像头数据记录了以下信息,如定义生成图像的照相机的代码、曝光时间、选择的图像处理选项、图像维度、可能使用的光学过滤器以及图像如何压缩(如果采用了压缩方法)。部分的头数据是由生成图像的设备任务生成的,其余部分是由ICS在把图像数据发送给太空处理器“下行”的处理程序之前生成的。由于头数据并非图像数据本身,它存储在一个独立的内存槽,直到需要执行“下行”操作时才使用。每个图像槽和其关联的头数据需要通过协力的方式进行跟踪和处理。

    如图3-6所示,内存管理器实际上只是一组函数集合,这些函数在一个结构数组上执行操作。内存槽的当前状态是保存在数组中,这些数组实际上构成了一个物理内存空间及其内容的动态模型。

    对图像切槽 - 图2

    图 3-6:内存槽管理数组

    其中一个数组包含图像数据的结构体,每个图像槽对应一个结构体。该结构体通过C语言类型定义如下:


    typedef struct{ uint16_t slot_status; /*<Owned or unowned / int16_t slot_owner; /*<-1 if slot is unowned / int16_t slot_size; /*<either RAC/OM or SSI sized / uint16_tslot_address; /**<address of data space of slot / }ics_img_slot_entry_t;

    第二个数组包含指向头数据入口的结构体,其定义如下:


    typedef struct{ uint16_t slot_status; /*<Owned or unowned / int16_t slot_owner; /*<-1 if unowned / int16_t img_id; /*<associated image data slot number / uint16_t hdr_data[ICS_HDR_SLOT_SZ];/*<array for header data / }ics_hdr_slot_entry_t;

    注意:图像的头结构体包含该图像ID的入口。这一点是很有必要的,因为槽可以以任意次序进行分配和释放,而且不能保证一个图像槽入口的索引和它原来关联的头数据槽的索引是同一个索引。我们采用图像ID把图像和头数据入口绑定在一起,而不是依赖于数组中的索引偏移来保证图像和头数据入口是同步的。

    由于可以动态重新配置图像的槽分配,内存管理器可以适应于特定的任务。一方面,如果为火星上的某天制定的计划(或者称一个Sol)和通过SSI成像相关,那么我们就可以通过槽配置来最小化RAC/MECA的大小分配,即设置为默认的配置。另一方面,如果该计划和很多的RAC或OM图像相关,那么我们可以对内存进行配置,使得它能够处理上限39个、较小尺寸的图像。