使用ACE_Malloc

ACE_Malloc類的使用很簡單。首先,用你選擇的內存池和鎖定機制實例化ACE_Malloc,以創建分配器類。隨後用該分配器類實例化一個對象,這也就是你的應用將要使用的分配器。當你實例化分配器對象時,傳給構造器的第一個參數是一個字符串,它是你想要分配器對象使用的底層內存池的“名字”。將正確的名字傳遞給構造器非常重要,特別是如果你在使用共享內存的話。否則,分配器將會爲你創建一個新的內存池。如果你在使用共享內存池,這當然不是你想要的,因爲你根本沒有獲得共享。

  爲了方便底層內存池的共享(重複一次,如果你在使用共享內存的話,這是很重要的),

  在實例化

  表

ACE_Malloc類還擁有一個映射(map)類型接口:可被給每個被分配的內存block一個名字,從而使它們可以很容易地被在內存池中查找的另一個進程找到。該接口含有bind()和find()調用。bind()調用用於給由malloc()調用返回給ACE_Malloc的block命名。find()調用,如你可能想到的那樣,用於查找與某個名字相關聯的內存。ACE_Malloc模板類時,有若干不同的內存池類可用(如表3-2所示)。這些類不僅可用於分配在進程內使用的內存,也可以用於分配在進程間共享的內存池。這也使得爲何ACE_Malloc模板需要通過鎖定機制來實例化顯得更清楚了。當多個進程訪問共享內存池時,該鎖保證它們不會因此而崩潰。注意即使是多個線程在使用分配器,也同樣需要提供鎖定機制。3-2列出了各種可用的內存池:

 

池名

描述

ACE_MMAP_Memory_Pool

ACE_MMAP_MEMORY_POOL

使用

<mmap(2)>創建內存池。這樣內存就可在進程間共享了。每次更新時,內存都被更新到後備存儲(backing store)。

ACE_Lite_MMAP_Memory_Pool

ACE_LITE_MMAP_MEMORY_POOL

使用

<mmap(2)>創建內存池。不像前面的映射,它不做後備存儲更新。代價是較低可靠性。

ACE_Sbrk_Memory_Pool

ACE_SBRK_MEMORY_POOL

使用

<sbrk(2)>調用創建內存池。

ACE_Shared_Memory_Pool

ACE_SHARED_MEMORY_POOL

使用系統

V <shmget(2)>調用創建內存池。

Memory_Pool

 

內存可在進程間共享。

ACE_Local_Memory_Pool

ACE_LOCAL_MEMORY_POOL

通過

C++的new和delete操作符創建局部內存池。該池不能在進程間共享。

 

3-2 可用的內存池

 

  下面的例子通過共享內存池使用

  該例創建服務器進程,該進程創建內存池,再從池中分配內存。然後服務器使用從池中分配的內存來創建它想要客戶進程“拾取”的消息。其次,它將名字綁定

  客戶在開始運行後創建它自己的分配器,但是使用的是同一個內存池。這是通過將同一個名字傳送到分配器的構造器來完成的,然後客戶使用

ACE_Malloc類(該例使用ACE_SHARED_MEMORY_POOL來做演示,但表3-2中的任何支持內存共享的內存池都可以被使用)。bind)到這些消息,以使客戶能使用相應的find操作來查找服務器插入池中的消息。find()調用來查找服務器插入的消息,並將它們打印給用戶看。

 

3-2

#include "stdafx.h"
#include "ace/Malloc_T.h"
#include "ace/OS.h"
#include "ace/Null_Mutex.h"
#include "ace/MMAP_Memory_Pool.h" 
#define DATA_SIZE 100
#define MESSAGE1 "Hiya over there client process"
#define MESSAGE2 "Did you hear me the first time?"
char poolname[8]="My_Pool";
typedef ACE_Malloc<ACE_MMAP_Memory_Pool/*ACE_SHARED_MEMORY_POOL*/,ACE_Null_Mutex> Malloc_Allocator;
static void server (void)
{
//Create the memory allocator passing it the shared memory
//pool that you want to use
Malloc_Allocator shm_allocator(poolname);
//Create a message, allocate memory for it and bind it with
//a name so that the client can the find it in the memory
//pool
char* Message1=(char*)shm_allocator.malloc(strlen(MESSAGE1));
ACE_OS::strcpy(Message1,MESSAGE1);
shm_allocator.bind("FirstMessage",Message1);
ACE_DEBUG((LM_DEBUG,"<<%s\n",Message1));
//How about a second message
char* Message2=(char*)shm_allocator.malloc(strlen(MESSAGE2));
ACE_OS::strcpy(Message2,MESSAGE2);
shm_allocator.bind("SecondMessage",Message2);
ACE_DEBUG((LM_DEBUG,"<<%s\n",Message2));
//Set the Server to go to sleep for a while so that the client has
//a chance to do its stuff
ACE_DEBUG((LM_DEBUG,
   "Server done writing.. going to sleep zzz..\n\n\n"));
ACE_OS::sleep(2);
//Get rid of all resources allocated by the server. In other
//words get rid of the shared memory pool that had been
//previously allocated
shm_allocator.remove();
}
static void client(void)
{
//Create a memory allocator. Be sure that the client passes
// in the "right" name here so that both the client and the
//server use the same memory pool. We wouldn’t want them to
// BOTH create different underlying pools.
Malloc_Allocator shm_allocator(poolname);
//Get that first message. Notice that the find is looking up the
//memory based on the "name" that was bound to it by the server.
void *Message1;
if(shm_allocator.find("FirstMessage",Message1)==-1)
{
   ACE_ERROR((LM_ERROR,
    "Client: Problem cant find data that server has sent\n"));
   ACE_OS::exit(1);
}
ACE_OS::printf(">>%s\n",(char*) Message1);
ACE_OS::fflush(stdout);
//Lets get that second message now.
void *Message2;
if(shm_allocator.find("SecondMessage",Message2)==-1)
{
   ACE_ERROR((LM_ERROR,
    "Client: Problem cant find data that server has sent\n"));
   ACE_OS::exit(1);
}
ACE_OS::printf(">>%s\n",(char*)Message2);
ACE_OS::fflush(stdout);
ACE_DEBUG((LM_DEBUG,"Client done reading! BYE NOW\n"));
ACE_OS::fflush(stdout);
}
int main (int, char *[])
{
switch (ACE_OS::fork ())
{
case -1:
   ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "fork"), 1);
case 0:
   // Make sure the server starts up first.
   ACE_OS::sleep (1);
   client ();
   break;
default:
   server ();
   break;
}
return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章