1. 程式人生 > >將 Win32 C/C++ 應用程式遷移到 POWER 上的 Linux,第 1 部分: 程序、執行緒和共享記憶體服務 (轉載)

將 Win32 C/C++ 應用程式遷移到 POWER 上的 Linux,第 1 部分: 程序、執行緒和共享記憶體服務 (轉載)

特別是程序、執行緒和共享記憶體服務)到 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
CreateProcessfork()
execv()
TerminateProcesskill
ExitProcess() exit()
GetCommandLineargv[]
GetCurrentProcessIdgetpid
KillTimeralarm(0)
SetEnvironmentVariableputenv
GetEnvironmentVariablegetenv
GetExitCodeProcesswaitpid

建立程序服務
在 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 in Linux
                       NULL,       // ignored in Linux
               &startupInfo,
                    &procInfo))
        *processId = procInfo.dwProcessId;
else
{
        *processId = 0;
          return RC_PROCESS_NOT_CREATED;
}	
      

在 Linux 中,程序 ID 是一個整數。Linux 中的搜尋目錄由 PATH 環境變數(exec_path_name)決定。 fork() 函式建立父程序的一個副本,包括父程序的資料空間、堆和棧。 execv() 子例程使用 exec_path_name 將呼叫程序當前環境傳遞給新的程序。

這個函式用一個由 exec_path_name 指定的新的程序映像替換當前的程序映像。新的映像構造自一個由 exec_path_name 指定的正規的、可執行的檔案。由於呼叫的程序映像被新的程序映像所替換,所以沒有任何返回。


				
        Equivalent Linux code
#include <stdlib.h>
#include <stdio.h>

int    processId;
char  *exec_path_name;
char  *	cmd_line ;

cmd_line = (char *) malloc(strlen(_cmd_line ) + 1 );

if(cmd_line == NULL)
         return RC_NOT_ENOUGH_MEMORY;
         	
strcpy(cmd_line, _cmd_line);

if( ( *processId = 
        fork() ) == 0 )		// Create child
 {	
         char		*pArg, *pPtr;
         char		*argv[WR_MAX_ARG + 1];
         int		 argc;
         if( ( pArg = strrchr( exec_path_name, '/' ) ) != NULL )
                pArg++;
         else
                pArg = exec_path_name;
         argv[0] = pArg;
         argc = 1;
         
         if( cmd_line != NULL && *cmd_line != '/0' )
         {
                  
               pArg = strtok_r(cmd_line, " ", &pPtr);
               
               while( pArg != NULL )
               {
                              argv[argc] = pArg;
                              argc++;
                              if( argc >= WR_MAX_ARG )
                              break;
                              pArg = strtok_r(NULL, " ", &pPtr);
                }
         }
         argv[argc] = NULL;
         
         execv(exec_path_name, argv);
         free(cmd_line);
         exit( -1 );
}
else if( *processId == -1 )
{
           *processId = 0;
           free(cmd_line);
           return RC_PROCESS_NOT_CREATED;
}

      

終止程序服務
在 Win32 程序中,父程序和子程序可能需要單獨訪問子程序所繼承的由某個控制代碼標識的物件。父程序可以建立一個可訪問而且可繼承的副本控制代碼。Win32 示例程式碼使用下面的方法終止程序:

  • 使用 OpenProcess 來獲得指定程序的控制代碼。
  • 使用 GetCurrentProcess 獲得其自己的控制代碼。
  • 使用 DuplicateHandle 來獲得一個來自同一物件的控制代碼作為原始控制代碼。

如果函式成功,則使用 TerminateThread 函式來釋放同一程序上的主執行緒。然後使用 TerminateThread 函式來無條件地使一個程序退出。它啟動終止並立即返回。


				
        Win32 sample code
if( thread != (HANDLE) NULL )
{
    HANDLE	thread_dup;
    if( DuplicateHandle( OpenProcess(PROCESS_ALL_ACCESS, TRUE,  processId),
                                     thread,
                                     GetCurrentProcess(),
                                     &amp;thread_dup,  //Output
                                     0,
                                     FALSE,
                                     DUPLICATE_SAME_ACCESS ))
      {
            TerminateThread( thread_dup, 0);
       }
}
TerminateProcess(
        OpenProcess(PROCESS_ALL_ACCESS, TRUE, 
        processId), 
   (UINT)0 );

      

在 Linux 中,使用 kill 子例程傳送 SIGTERM 訊號來終止特定程序(processId)。然後呼叫設定 WNOHANG 位的 waitpid 子例程。這將檢查特定的程序並終止。


				
        Equivalent  Linux code
pid_t	nRet;
int	status;

kill( processId, SIGTERM );
nRet = waitpid( processId, &status, WNOHANG);  //Check specified
   process is terminated
      

程序依然存在服務
Win32 OpenProcess 返回特定程序(processId)的控制代碼。如果函式成功,則 GetExitCodeProcess 將獲得特定程序的狀態,並檢查程序的狀態是否是 STILL_ACTIVE。


				
        Win 32 sample
HANDLE      nProc;
DWORD       dwExitCode;

nProc = OpenProcess(PROCESS_ALL_ACCESS, TRUE, processId);
if ( nProc != NULL)
{
     GetExitCodeProcess( nProc, &dwExitCode );
     if (dwExitCode == STILL_ACTIVE )
            return RC_PROCESS_EXIST;
     else
            return RC_PROCESS_NOT_EXIST;
}
else
     return RC_PROCESS_NOT_EXIST;
      

在 Linux 中,使用 kill 子例程傳送通過 Signal 引數指定的訊號給由 Process 引數(processId)指定的特定程序。Signal 引數是一個 null 值,會執行錯誤檢查,但不傳送訊號。


				
        Equivalent Linux code
if ( kill ( processId, 0 ) == -1 && errno == ESRCH ) // No process can 
                                       be found
                             // corresponding to processId
         return RC_PROCESS_NOT_EXIST;
else
        return RC_PROCESS_EXIST;

      

執行緒模型
執行緒 是系統分配 CPU 時間的基本單位;當等待排程時,每個執行緒保持資訊來儲存它的“上下文”。每個執行緒都可以執行程式程式碼的任何部分,並共享程序的全域性變數。

構建於 clone() 系統呼叫之上的 LinuxThreads 是一個 pthreads 相容執行緒系統。因為執行緒由核心來排程,所以 LinuxThreads 支援阻塞的 I/O 操作和多處理器。不過,每個執行緒實際上是一個 Linux 程序,所以一個程式可以擁有的執行緒數目受核心所允許的程序總數的限制。Linux 核心沒有為執行緒同步提供系統呼叫。Linux Threads 庫提供了另外的程式碼來支援對互斥和條件變數的操作(使用管道來阻塞執行緒)。

對有外加 LinuxThreads 的訊號處理來說,每個執行緒都會繼承訊號處理器(如果派生這個執行緒的父程序註冊了一個訊號處理器的話。只有在 Linux Kernel 2.6 和更高版本中支援的新特性才會包含 POSIX 執行緒支援,比如 用於 Linux 的 Native POSIX Thread Library(NPTL)。

執行緒同步、等待函式、執行緒本地儲存以及初始化和終止抽象是執行緒模型的重要部分。在這些之下,執行緒服務只負責:

  • 新執行緒被建立,threadId 被返回。
  • 通過呼叫 pthread_exit 函式可以終止當前的新執行緒。

執行緒對映表

Win32 Linux
_beginthreadpthread_attr_init
pthread_attr_setstacksize
pthread_create
_endthreadpthread_exit
TerminateThread pthread_cancel
GetCurrentThreadIdpthread_self

執行緒建立
Win32 應用程式使用 C 執行期庫,而不使用 Create_Thread API。使用了 _beginthread 和 _endthread 例程。這些例程會考慮任何可重入性(reentrancy)和記憶體不足問題、執行緒本地儲存、初始化和終止抽象。

Linux 使用 pthread 庫呼叫 pthread_create() 來派生一個執行緒。

threadId 作為一個輸出引數返回。為建立一個新執行緒,要傳遞一組引數。當新執行緒被建立時,這些引數會執行一個函式。stacksize 用作新執行緒的棧的大小(以位元組為單位),當新執行緒開始執行時,實際的引數被傳遞給函式。

指定執行緒程式(函式)
進行建立的執行緒必須指定要執行的新執行緒的啟動函式的程式碼。啟動地址是 threadproc 函式(帶有一個單獨的引數,即 threadparam)的名稱。如果呼叫成功地建立了一個新執行緒,則返回 threadId。Win32 threadId 的型別定義是 HANDLE。Linux threadId 的型別定義是 pthread_t。

threadproc
要執行的執行緒程式(函式)。它接收一個單獨的 void 引數。
threadparam
執行緒開始執行時傳遞給它的引數。

設定棧大小
在 Win32 中,執行緒的棧由程序的記憶體空間自動分配。系統根據需要增加棧的大小,並在執行緒終止時釋放它。在 Linux 中,棧的大小在 pthread 屬性物件中設定;pthread_attr_t 傳遞給庫呼叫 pthread_create()


				
        Win32 sample
int		hThrd;
DWORD          dwIDThread;
unsigned       stacksize;
void           *thrdparam; //parameter to be passed to the thread when it 
                                  //begins execution
HANDLE         *threadId;

if( stacksize < 8192 )
     stacksize = 8192;
else
     stacksize = (stacksize/4096+1)*4096;
     
     hThrd = _beginthread( thrdproc,    // Definition of a thread entry 
                                                                  //point
                                NULL,
                                stacksize,
                                thrdparam);
if (hThrd == -1)
     return RC_THREAD_NOT_CREATED);
     *threadId = (HANDLE) hThrd;
__________________________________________________________________     
                          
        Equivalent Linux code
                                                            
#include <pthread.h>

pthread_t   *threadId;
void         thrdproc  (void *data);  //the thread procedure (function) to 
                                               //be executed. 
                      //It receives a single void parameter
void        *thrdparam; //parameter to be passed to the thread when it 
                               //begins execution
pthread_attr_t  attr;
int             rc = 0;

if (thrdproc == NULL || threadId == NULL)
     	return RC_INVALID_PARAM);
     	
if (rc = pthread_attr_init(&attr))	
     return RC_THREAD_NOT_CREATED);  // EINVAL, ENOMEM
      
if (rc = pthread_attr_setstacksize(&attr, stacksize))
     return RC_THREAD_NOT_CREATED);   // EINVAL, ENOSYS
     
if (rc = pthread_create(threadId, &attr, (void*(*)(void*))thrdproc, 
   thrdparam))
     return RC_THREAD_NOT_CREATED);      // EINVAL, EAGAIN

      

終止執行緒服務
在 Win32 中,一個執行緒可以使用 TerminateThread 函式終止另一個執行緒。不過,執行緒的棧和其他資源將不會被收回。如果執行緒終止自己,則這樣是可取的。在 Linux 中,pthread_cancel 可以終止由具體的 threadId 所標識的執行緒的執行。

Win32 Linux
TerminateThread((HANDLE *) threadId, 0); pthread_cancel(threadId);

執行緒狀態
在 Linux 中,執行緒預設建立為可合併(joinable)狀態。另一個執行緒可以使用 pthread_join() 同步執行緒的終止並重新獲得終止程式碼。可合併執行緒的執行緒資源只有在其被合併後才被釋放。

Win32 使用 WaitForSingleObject() 來等待執行緒終止。

Linux 使用 pthread_join 完成同樣的事情。

Win32 Linux
unsigned long rc;

rc = (unsigned long) WaitForSingleObject (threadId, INIFITE);
unsigned long rc=0;

rc = pthread_join(threadId,
void **status);

結束當前執行緒服務的執行
在 Win32 中,使用 _endthread() 來結束當前執行緒的執行。在 Linux 中,推薦使用 pthread_exit() 來退出一個執行緒,以避免顯式地呼叫 exit 例程。在 Linux 中,執行緒的返回值是 retval,可以由另一個執行緒呼叫 pthread_join() 來獲得它。

Win32 Linux
_endthread(); pthread_exit(0);

獲得當前執行緒 ID 服務
在 Win32 程序中,GetCurrentThreadId 函式獲得進行呼叫的執行緒的執行緒識別符號。Linux 使用 pthread_self() 函式來返回進行呼叫的執行緒的 ID。

Win32 Linux
GetCurrentThreadId() pthread_self()
Win32 Equivalent Linux code
Sleep (50) struct timespec timeOut,remains;

timeOut.tv_sec = 0;
timeOut.tv_nsec = 500000000; /* 50 milliseconds */

nanosleep(&timeOut, &remains);
用於 Win32 Sleep 函式的時間段的單位是毫秒,可以是 INFINITE,在這種情況下執行緒將永遠不會再重新開始。 Linux sleep 函式類似於 Sleep,但是時間段以秒來計。要獲得毫秒級的精度,則使用 nanosleep 函式來提供同樣的服務。

Win32 SleepEx 函式掛起 當前執行緒,直到下面事件之一發生:

  • 一個 I/O 完成回撥函式被呼叫。
  • 一個非同步過程呼叫(asynchronous procedure call,APC)排隊到此執行緒。
  • 最小超時時間間隔已經過去。

Linux 使用 sched_yield 完成同樣的事情。

Win32 Linux
SleepEx (0,0) sched_yield()

共享記憶體服務
共享記憶體允許多個程序將它們的部分虛地址對映到一個公用的記憶體區域。任何程序都可以向共享記憶體區域寫入資料,並且資料可以由其他程序讀取或修改。共享記憶體用於實現程序間通訊媒介。不過,共享記憶體不為使用它的程序提供任何訪問控制。使用共享記憶體時通常會同時使用“鎖”。

一個典型的使用情形是:

  1. 某個伺服器建立了一個共享記憶體區域,並建立了一個共享的鎖物件。
  2. 某個客戶機連線到伺服器所建立的共享記憶體區域。
  3. 客戶機和伺服器雙方都可以使用共享的鎖物件來獲得對共享記憶體區域的訪問。
  4. 客戶機和伺服器可以查詢共享記憶體區域的位置。
Win32 Linux
CreateFileMaping,
OpenFileMapping
mmap
shmget
UnmapViewOfFilemunmap
shmdt
MapViewOfFilemmap
shmat

建立共享記憶體資源
Win32 通過共享的記憶體對映檔案來建立共享記憶體資源。Linux 使用 shmget/mmap 函式通過直接將檔案資料合併入記憶體來訪問檔案。記憶體區域是已知的作為共享記憶體的段。

檔案和資料也可以在多個程序和執行緒之間共享。不過,這需要程序或執行緒之間同步,由應用程式來處理。

如果資源已經存在,則 CreateFileMapping() 重新初始化共享資源對於程序的約定。如果沒有足夠的空閒記憶體來處理錯誤的共享資源,此呼叫可能會失敗。 OpenFileMapping() 需要共享資源必須已經存在;這個呼叫只是請求對它的訪問。

在 Win32 中,CreateFileMapping 不允許您增加檔案大小,但是在 Linux 中不是這樣。在 Linux 中,如果資源已經存在,它將被重新初始化。它可能被銷燬並重新建立。Linux 建立可以通過名稱訪問的共享記憶體。 open() 系統呼叫確定對映是否可讀或可寫。傳遞給 mmap() 的引數必須不能與 open() 時請求的訪問相沖突。 mmap() 需要為對映提供檔案的大小(位元組數)。

對 32-位核心而言,有 4GB 虛地址空間。最前的 1 GB 用於裝置驅動程式。最後 1 GB 用於核心資料結構。中間的 2GB 可以用於共享記憶體。當前,POWER 上的 Linux 允許核心使用 4GB 虛地址空間,允許使用者應用程式使用最多 4GB 虛地址空間。

Win32 Linux
PAGE_READONLY PROT_READ
PAGE_READWRITE (PROT_READ | PROT_WRITE)
PAGE_NOACCESS PROT_NONE
PAGE_EXECUTE PROT_EXEC
PAGE_EXECUTE_READ (PROT_EXEC |PROT_READ)
PAGE_EXECUTE_READWRITE (PROT_EXEC | PROT_READ | PROT_WRITE)

要獲得 Linux 共享記憶體的分配,您可以檢視 /proc/sys/kernel 目錄下的 shmmax、shmmin 和 shmall。

在 Linux 上增加共享記憶體的一個示例:

echo 524288000 > /proc/sys/kernel/shmmax
最大共享記憶體增加到 500 MB。

下面是建立共享記憶體資源的 Win32 示例程式碼,以及相對應的 Linux nmap 實現。


				
        Win32 sample code
typedef struct
 {
   // This receives a pointer within the current process at which the 
   // shared memory is located.
   // The same shared memory may reside at different addresses in other
   // processes which share it.
       void *	location;
       HANDLE	hFileMapping;
}mem_shared_struct, *mem_shared, *token;

mem_shared_struct   *token;

if ((*token = (mem_shared) malloc(sizeof(mem_shared_struct))) == NULL)     
     return RC_NOT_ENOUGH_MEMORY;
     
if (newmode == new_shared_create)
   (*token)->hFileMapping = CreateFileMapping((HANDLE) 0xFFFFFFFF, NULL,
                 PAGE_READWRITE,
                 0,
                (DWORD) size,
                 (LPSTR) name);
 else
      (*token)->hFileMapping = OpenFileMapping(FILE_MAP_ALL_ACCESS,
                 FALSE,
                 (LPSTR) name);
if ((*token)->hFileMapping == NULL)
{
      free( *token );
      return RC_SHM_NOT_CREATED );
}

(*token)->location = MapViewOfFile((*token)->hFileMapping,
                                      FILE_MAP_READ | FILE_MAP_WRITE, 
                                      0, 0, 0);
if ((*token)->location == NULL)
{
      CloseHandle((*token)->hFileMapping);
            free(*token);
            return RC_OBJECT_NOT_CREATED;
}
____________________________________________________________________
                     
        Equivalent Linux code
                                  
typedef struct
{    	
      void    *location;
      int	 nFileDes;	
      cs_size	 nSize;	
      char	 *pFileName;
}mem_shared_struct, *mem_shared, token;

mode_t	mode=0;
int	flag=0;
int	i, ch='/0';
char   name_buff[128];

if (newmode == new_shared_create)
                  flag = O_CREAT;
else if (newmode != new_shared_attach)	
                  return RC_INVALID_PARAM;
                  
if ((*token = (mem_shared) malloc(sizeof(mem_shared_struct))) == NULL)
               return RC_NOT_ENOUGH_MEMORY;
               
strcpy(name_buff, "/tmp/" );
strcat(name_buff, name );

if(((*token)->pFileName = malloc(strlen(name_buff)+1)) == NULL )
{     
      free(*token);
      return RC_NOT_ENOUGH_MEMORY;
}

mode |= S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
flag |= O_RDWR;

if(newmode == new_shared_create)    
      remove(name_buff);
      
if(((*token)->nFileDes = open(name_buff, flag, mode)) < 0)
{    
      free((*token)->pFileName);
      free(*token);
      return RC_OBJECT_NOT_CREATED;
}

if(newmode == new_shared_create)
{    
      lseek((*token)->nFileDes, size - 1, SEEK_SET);
      write((*token)->nFileDes, &ch, 1);
}
if(lseek((*token)->nFileDes, 0, SEEK_END) < size)
{	
         free((*token)->pFileName);
         free(*token);
         return RC_MEMSIZE_ERROR;
}
(*token)->location = mmap( 0, size,
                  PROT_READ | PROT_WRITE,
                  MAP_VARIABLE | MAP_SHARED, 
                      (*token)->nFileDes,
                                  0);
                                  
if((int)((*token)->location) == -1)
{   
       free((*token)->pFileName);
       free(*token);    
       return RC_OBJECT_NOT_CREATED;
}

(*token)->nSize = size;strcpy((*token)->pFileName, name_buff);

      

刪除共享記憶體資源
為銷燬共享記憶體資源,munmap 子例程要取消被對映檔案區域的對映。munmap 子例程只是取消對 mmap 子例程的呼叫而建立的區域的對映。如果某個區域內的一個地址被 mmap 子例程取消對映,並且那個區域後來未被再次對映,那麼任何對那個地址的引用將導致給程序發出一個 SIGSEGV 訊號。

Win32 等價的 Linux 程式碼
UnmapViewOfFile(token->location);

CloseHandle(token->hFileMapping);
munmap(token->location, token->nSize);

close(token->nFileDes);

remove(token->pFileName);

free(token->pFileName);

結束語
本文介紹了關於初始化和終止、程序、執行緒及共享記憶體服務從 Win32 API 到 POWER 上 Linux 的對映。這絕對沒有涵蓋所有的 API 對映,而且讀者只能將此資訊用作將 Win32 C/C++ 應用程式遷移到 POWER Linux 的一個參考。