您的位置:首页 > 其它

应用程序从Windows到Mac OS x的迁移

2010-11-12 17:17 316 查看
作者 Jerry Peng

在移植之前我们需要了解不同的目标平台,学习不同平台下编程的基础知识。Mac OS X系统是基于BSD Unix的内核环境,支持Standard C++ Library,类似fopen、fread、fwrite、stl函数及其他函数在Mac OS X中也可使用。另外,在Win32 API和BSD API之间还存在一对一映射:CreateFile对应open、ReadFile对应read、WriteFile对应write、DeviceIOControl对应ioctl、CloseFile对应close等等。

l 工程类型
大的工程项目中一般会有多个工程文件,在移植的时候我们也希望保留原来的工程组织结构,所以一般是建立和原工程对应的工程文件。在Windows平台我们可以用vc++创建动态链接库(.dll)、静态库(.lib)、可执行文件(.exe)等工程类型,对应在Mac平台我们可以用xcode IDE创建动态链接库(.dylib)、静态库(.a)、可执行文件等类型的工程。

l 数据类型
Mac平台基本数据类型关键字与windows上平台上有差别,所以移植的过程中我们要注意用对应的关键字进行替换。如LONG、ULON DWORD等等,直接编绎会报错,我们可以在windows上找到原始的定义,然后再找到Mac平台对应的类型。一般不要在原文件直接替换,最好定义成宏:
#ifdef _MAC_OS_X
Typedef u_long ULONG;
#endif

l 进程
Mac平台与windows的进程模型有很大的不同。在windows平台创建进程有CreateProcess(),对应的Mac上可以用fork()和execv()来实现。相应的结束进程TerminateProcess()、取进程ID GetCurrentProcessID()、进程退出Exitprocess()、等待进程Waitforsingleobject()等对应有kill()、getpid()、waitpid()、exit()。
launch进程:
[Windows]
if (!::CreateProcess( NULL,(LPTSTR)szCmdLine,
NULL, NULL, TRUE, dwCreateFlags, NULL, NULL, &si, &pi)){
}

[Mac OS X]
int rc =
fork();
switch(rc)
{
case -1:
printf("Fork() function
failed !!");
break;
case 0:
setpgid(0,0);
execv(pszCmdLine,
NULL);
break;
default:
ret = 0;
break;
}
进程间通信方式有多种, windows下的CreatePipe()管道方式对应Mac下可以用pipe(),mkfifo()实现。注意Pipe()要求进程间有亲缘性,移植的过程中要根据进程上下文来选择正确的API。

l 线程
Mac平台支持POSIX线程模型,windows下的线程调用可以用POSIX
API来实现。Windows下线程API主要有创建线程CreateThread()、退出线程ThreadExit()、等待线程WaitForSingleObject()、设置线程优先级SetThreadPriority()等对应的POSIX有pthread_create()、pthread_exit()、pthread_join()、 pthread_attr_setschedpolicy()、pthread_attr_setschedparam()。
在 Windows 32位系统中,一个进程可寻址4GB的虚拟内存空间,除去2GB的内核空间,在2GB的用户空间上可以创建的线程数目是有限的。默认情况下,每个线程有1MB栈空间可用。因此,您最多可以创建 2,028 个线程。如果您减小默认栈大小,那么可以创建更多线程。
对于 POSIX 线程限制而言,local_lim.h 中定义的
THREAD_THREADS_MAX 宏定义了数目的上限。
线程间的同步在windows下可以用:
事件(Event):对应Mac平台信号量(Semaphore)、条件变量(Conditional
variable)
信号量(Semaphore):对应Mac平台信号量(Semaphore)
互斥(Mutexe):对应Mac平台互斥(Mutexe)
临界区(Critical section):对应Mac平台互斥(Mutexe)等来实现.
事件的移植:
[windows]
HANDLE hEvent;
// Thread 1
DWORD dwRetCode;
hEvent =
CreateEvent();
dwRetCode =
WaitForSingleObject(hEvent, INFINITE);
switch(dwRetCode)
{
case WAIT_OBJECT_O :
default :
}
CloseHandle(hEvent);
// Thread 2
SetEvent(
hEvent);

[Mac Semaphore]
sem_t sem
;
// Thread 1
int retCode ;
retCode =
sem_init(sem, 0, 0);
retCode =
sem_wait(&sem);
retCode = sem_destroy(
&sem);
//
Thread 2
sem_post(&sem);

[Mac Conditional
variable]
pthread_mutex_t
mutex;
pthread_cond_t
condvar;

// Thread 1
pthread_mutex_lock(&mutex);
pthread_cond_wait(&condvar,
&mutex);
pthread_mutex_unlock(&mutex);
// Thread 2
pthread_mutex_lock(&mutex);
pthread_cond_signal(&condvar);
pthread_mutex_unlock(&mutex);

原子锁的移植
inline long
InterlockedIncrement( volatile long *val )
{
__gnu_cxx::__exchange_and_add((volatile
int *)val,1);
return *val;
}

inline long
InterlockedDecrement( volatile long *val )
{
__gnu_cxx::__exchange_and_add((volatile
int *)val,-1);
return *val;
}

inline long
InterlockedExchangeAdd(volatile long* Addend, long Increment )
{
int ret =
__gnu_cxx::__exchange_and_add((volatile int *)Addend,(int)Increment);
return (long)ret;
}

l 移植C/C++程序的注意事项
应该了解程序的框架,不要只针对某一个API进行移植,要理解程序上下文。
不同平台的API的用法要仔细研究。

References:
l 《Porting to
Mac OS X from Windows Win32 API

l 《windows核心编程》
l Unix环境高级编程
l http://www.ibm.com/developerworks/aix/library/au-porting/?S_CMP=cn-a-aix&S_TACT=105AGX52
l http://www.ibm.com/developerworks/linux/library/l-ipc2lin1.html?S_TACT=105AGX52&S_CMP=cn-a-l
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: