我们在讨论系统移植的时候,通常会提到一个概念:平台。平台可以是硬件平台,也可以是软件平台,软件平台通常指的就是操作系统。而按照应用领域的不同,我们又可以将软件平台细分为J2EE、.NET平台,如此等等。
衡量系统的可移植性要从两个角度来看待,一个是垂直的,一个是水平的。所谓的垂直移植性,就是如何将一个应用程序从某个平台的一个版本移植到另外一个版本。如将一个应用程序从win32移植到win64,或将操作系统从IA-32移植到IA-64 CPU等。所谓的水平移植性,就是如何将一个应用程序从一个平台移植到另外一个平台。如将一个应用程序从windows平台移植到Linux平台,或将操作系统从Intel平台移植到ADM等。
在这篇文章中,我们主要讲述了两类平台,一类是硬件平台,另外一类就是操作系统平台。我们将重点阐述C++应用程序在操作系统平台上的移植。
对系统软硬件起到隔离作用,从而提高系统软件的可移值性及有效地利用人力资源、缩短开发周期和提高产品的可靠性。
硬件抽象层的特点
n 硬件抽象层具有与硬件密切相关性;
n 硬件抽象层具有与操作系统无关性;
n 接口定义的功能应包含硬件或系统所需硬件支持的所有功能;
n 接口定义简单明了,太多接口函数会增加软件模拟的复杂性;
n 具有可测性的接口设计有利于系统的软硬件测试和集成。
Windows操作系统的HAL模块,封装了对大部分硬件的底层数据交换和操作。
参考Windows操作系统的整体结构图:
对比UNIX操作系统的整体结构图:
不论是桌面应用领域还是嵌入式应用领域,在大多数情况下,这些领域的应用都构建在操作系统之上。每个操作系统都各有其特点,在特定的领域这些操作系统的功能基本相同,而操作系统的基础架构的不一致性,也直接导致了构建在操作系统之上的领域应用的不一致性。往往领域应用需要构建在多个平台之上,这就引入了所谓的“移植”。如何将一个特定的领域应用从一个平台移植到另外一个平台,这是一个相对的问题,我们只能尽可能把平台不一致性的部分给提取、抽象出来,提供应用程序的可移植性。
对于应用程序的可移植性,一直都没有公论,下面我们提供了C++应用程序在操作系统平台之间的移植时的一种解决方案。
a. 选择一种可移植的程序语言,如C++。
其实这也并不是必须的。现在的Java/C#都建在虚拟机之上,从本质上来说,如果虚拟机是可移植的,那么用这些语言编写出来的应用程序也是可移植的。从这点上来说,Java/C#其实是可移植的。
b. 尽量使用C标准库函数。
因为这些库函数,一般的操作的系统提供商和编译器提供商都提供了相应的支持。
c. 分离出不可移植的类型定义,并在应用程序中使用这些定义。
下面阐述是集中常见的情况:
n 文件分隔符
WINDOWS平台采用的是”/”,而UNIX/linux使用的是”/”。
那么把这个部分分离出来,可使用如下的定义:
#ifdef UNIX
#define SEPERATOR ‘/’
#endif
#ifdef _WINDOWS||__MSDOS__
#define SEPERATOR ‘/’
#endif
n 基本类型,不同操作系统版本对于基本类型、指针的定义是有差别的。
如在64位系统上,指针是64位的。;而在32位系统上,指针是32位的。
那么把这个部分分离出来,可使用如下的定义:
typedef char int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
typedef unsigned char uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned int uint_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
#ifndef _INTPTR_T_DEFINED
#ifdef _WIN64
typedef __int64 intptr_t;
#else
typedef int intptr_t;
#endif
#define _INTPTR_T_DEFINED
#endif
#ifndef _UINTPTR_T_DEFINED
#ifdef _WIN64
typedef unsigned __int64 uintptr_t;
#else
typedef unsigned int uintptr_t;
#endif
#define _UINTPTR_T_DEFINED
#endif
typedef intptr_t ssize_t;
d. 抽象应用程序依赖于平台API相关的接口,对于不同的平台提供不同的实现。
例如,对于线程的操作,linux和windows平台的API有着不同的定义。
那么我们可以把线程操作相关的接口给抽象出来,如:
class Thread
{
public:
static Thread* Create();
static Thread* CurrentThread() const;
void Suspend();
void Join();
void Sleep();
void Start();
uint_t GetID() const;
bool IsAlive() const;
void SetPriority(int32_t priority);
int32_t GetPriority() const;
//...
};