引言
在当今的软件设计中,为了在不同的产品线上重复使用相同的代码,需要将代码从一个平台移植到另一个平台。虽然这种代码的重复利用非常重要,但是很少有人讨论该采用何种方法来减少设计可移植软件的成本,本文将介绍一种可行的设计方案。
可移植代码的重要性
过去,
嵌入式应用程序一般不需要运行在不同的硬件平台和不同的操作系统上,因此开发者也不需要考虑让代码运行到
多平台上的问题。
随着技术的发展,市场竞争的激烈,厂家必须不断开发新产品。如果是需要为新产品重新设计新软件,一来开发周期长,另一方面,代码要经过严格测试后才能推出,就会影响产品的面市时间。因此,将已有的、已经过测试的代码移植到新产品上就是一个很好的办法,进而开发者被要求
设计出可运行在不同硬件平台或不同操作系统下的应用程序。但是,由于系统设计可选择不同的设备、不同的子系统以及CPU,范围非常广泛,这样的不确定性势必会增加开发多平台软件的难度。
使用抽象层设计可移植代码
抽象层的先进之处在于它能够提取应用程序的基本内容,并将其与系统实现相隔离。这里关键是要将应用程序的逻辑算法与其运行环境相隔离。例如,在读取文件时,应用程序应该只关心文件的内容,而不在意文件是存在于FAT文件系统中,还是EXT2文件系统中;在数据通信中,通信双方应该只关心收发的数据本身,至于数据传输的媒体则不是应用程序该考虑的。
多平台软件的系统构成如图1所示,这种方法可广泛地应用在各种应用程序中。就像系统的机械组件可以被抽象,通信接口、CPU资源、存储设备等也可以被抽象。灵活使用抽象层可以将应用程序简化为一个紧凑并可重复利用的代码。

图1 多平台软件系统构成图
操作系统抽象层
操作系统函数永远不要被直接调用,应将其包装到一个“操作系统抽象层”的库中,把应用程序从底层的操作系统中脱离出来。于是,当将应用程序移植到其他操作系统时,只要简单地移植操作系统抽象层即可,无需修改应用程序的代码。 这不仅将原应用程序的正确性和可靠性带到了新平台上,还加速了移植过程。此外,当在向新平台移植的过程中发现错误时,操作系统抽象层将是调试的最有效的起点。
操作系统抽象层应该输出函数原型,同时,不管底层的操作系统是如何实现的,抽象层应该对应用程序隐藏它们的一些特殊行为。例如,拿对信号量的操作来说,在大多数操作系统中,相同的进程可以多次获取一个信号量,而某些操作系统在递归获取信号量时会阻塞调用者。这里假设操作系统抽象层库输出一个信号量获取函数OS_SemTake(),那么它必须禁止该系统的标准操作,完成通用信号量获取的功能,使该函数独立于底层的操作系统。在递归获取信号量这个例子中,开发者必须实现递归行为本身。具体实现中,一些操作系统可能要比较两个任务的ID,这两个任务一个是上次要求获取信号量的任务,另一个是本次要求获取信号量的任务。如果两个ID相同,说明是在同一进程中,函数将增加信号量的计数器,且不调用操作系统的信号量获取函数。相应的,信号量释放函数必须对信号量的计数器进行递减操作,直到计数器为0,才调用操作系统的信号量释放函数释放信号量。