将 Win32 C/C++ 应用程序迁移到 POWER 上的 Linux,第 1 部分: 进程、线程和共享内存服务 (转载)

本文探讨了如何将Win32 C/C++应用程序移植到Linux pSeries平台,重点关注进程、线程和共享内存服务的迁移。在Linux中,使用GCC扩展的构造函数和析构函数替代Win32的DLL初始化。创建进程时,Linux的fork调用不同于Win32的CreateProcess,而线程模型中,Linux使用pthread库。此外,文章还讨论了线程同步、终止和共享内存的映射方法。
摘要由CSDN通过智能技术生成
特别是进程、线程和共享内存服务)到 POWER 上 Linux 的映射。本文可以帮助您确定哪种映射服务最适合您的需要。作者向您详细介绍了他在移植 Win32 C/C++ 应用程序时遇到的 API 映射。

概述
有很多方式可以将 Win32 C/C++ 应用程序移植和迁移到 pSeries 平台。您可以使用免费软件或者第三方工具来将 Win32 应用程序代码移到 Linux。在我们的方案中,我们决定使用一个可移植层来抽象系统 API 调用。可移植层将使我们的应用程序具有以下优势:

  • 与硬件无关。
    • 与操作系统无关。
    • 与操作系统上版本与版本间的变化无关。
  • 与操作系统 API 风格及错误代码无关。
  • 能够统一地在对 OS 的调用中置入性能和 RAS 钩子(hook)。

由于 Windows 环境与 pSeries Linux 环境有很大区别,所以进行跨 UNIX 平台的移植比进行从 Win32 平台到 UNIX 平台的移植要容易得多。这是可以想到的,因为很多 UNIX 系统都使用共同的设计理念,在应用程序层有非常多的类似之处。不过,Win32 API 在移植到 Linux 时是受限的。本文剖析了由于 Linux 和 Win32 之间设计的不同而引发的问题。

初始化和终止
在 Win2K/NT 上,DLL 的初始化和终止入口点是 _DLL_InitTerm 函数。当每个新的进程获得对 DLL 的访问时,这个函数初始化 DLL 所必需的环境。当每个新的进程释放其对 DLL 的访问时,这个函数为那个环境终止 DLL。当您链接到那个 DLL 时,这个函数会自动地被调用。对应用程序而言,_DLL_InitTerm 函数中包含了另外一个初始化和终止例程。

在 Linux 上,GCC 有一个扩展,允许指定当可执行文件或者包含它的共享对象启动或停止时应该调用某个函数。语法是 __attribute__((constructor))__attribute__((destructor))。这些基本上与构造函数及析构函数相同,可以替代 glibc 库中的 _init 和 _fini 函数。

这些函数的 C 原型是:


void __attribute__ ((constructor)) app_init(void);
void __attribute__ ((destructor)) app_fini(void);


				
        Win32 sample
_DLL_InitTerm(HMODULE modhandle, DWORD fdwReason, LPVOID lpvReserved)
{	
    WSADATA			Data;	
    switch (fdwReason)	
    {		
        case DLL_PROCESS_ATTACH:		
        if (_CRT_init() == -1)			
           return 0L;               
          /* start with initialization code */		
          app_init();		
          break;	
    case DLL_PROCESS_DETACH:		
         /* Start with termination code*/               
         app_fini();		
         _CRT_term();		
         break;      
    …..	
    default:		
          /* unexpected flag value - return error indication */		
            return 0UL;	
    }	return 1UL;		/* success */
}

      

进程服务
Win32 进程模型没有与 fork()exec() 直接相当的函数。在 Linux 中使用 fork() 调用总是会继承所有内容,与此不同, CreateProcess() 接收用于控制进程创建方面的显式参数,比如文件句柄继承。

CreateProcess API 创建一个包含有一个或多个在此进程的上下文中运行的线程的新进程,子进程与父进程之间没有关系。在 Windows NT/2000/XP 上,返回的进程 ID 是 Win32 进程 ID。在 Windows ME 上,返回的进程 ID 是除去了高位(high-order bit)的 Win32 进程 ID。当创建的进程终止时,所有与此进程相关的数据都从内存中删除。

为了在 Linux 中创建一个新的进程, fork() 系统调用会复制那个进程。新进程创建后,父进程和子进程的关系就会自动建立,子进程默认继承父进程的所有属性。Linux 使用一个不带任何参数的调用创建新的进程。 fork() 将子进程的进程 ID 返回给父进程,而不返回给子进程任何内容。

Win32 进程同时使用句柄和进程 ID 来标识,而 Linux 没有进程句柄。

进程映射表

Win32 Linux
CreateProcess fork()
execv()
TerminateProcess kill
ExitProcess() exit()
GetCommandLine argv[]
GetCurrentProcessId getpid
KillTimer alarm(0)
SetEnvironmentVariable putenv
GetEnvironmentVariable getenv
GetExitCodeProcess waitpid

创建进程服务
在 Win32 中, CreateProcess() 的第一个参数指定要运行的程序,第二个参数给出命令行参数。CreateProcess 将其他进程参数作为参数。倒数第二个参数是一个指向某个 STARTUPINFORMATION 结构体的指针,它为进程指定了标准的设备以及其他关于进程环境的启动信息。在将 STARTUPINFORMATION 结构体的地址传给 CreateProcess 以重定向进程的标准输入、标准输出和标准错误之前,您需要设置这个结构体的 hStdin、hStdout 和 hStderr 成员。最后一个参数是一个指向某个 PROCESSINFORMATION 结构体的指针,由被创建的进程为其添加内容。进程一旦启动,它将包含创建它的进程的句柄以及其他内容。


				
        Win32 example
PROCESS_INFORMATION    procInfo;
STARTUPINFO	        startupInfo;
typedef DWORD          processId;
char                   *exec_path_name
char                   *_cmd_line;


        GetStartupInfo( &startupInfo );     // You must fill in this structure
if( CreateProcess( exec_path_name,  // specify the executable program
                       _cmd_line,   // the command line arguments
                       NULL,       // ignored in Linux
                       NULL,       // ignored in Linux
                       TRUE,       // ignored in Linux
                       DETACHED_PROCESS | HIGH_PRIORITY_CLASS,
                       NULL,       // ignored i
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值