服務(wù)器程序設(shè)計(jì)部分
續(xù)上在這里我將要向大家簡單介紹一下游戲服務(wù)器中必須要處理另外一項(xiàng)主要技術(shù):
內(nèi)存分配處理技術(shù)也可以稱為內(nèi)存池處理技術(shù)(這個(gè)比較洋氣,前面通俗的好,呵呵)
開始向大家介紹一般情況下我們對于內(nèi)存的一些基本操作。簡單而言,內(nèi)存操作就只有三個(gè)步驟:申請、使用、銷毀。而對于這些操作我們在C和C++中的處理方式略有不同:
在C中我們一般用malloc(….)函數(shù)來進(jìn)行申請,而對應(yīng)銷毀已經(jīng)申請的內(nèi)存使用free(…)函數(shù)。
在C++我們一般使用new操作符和delete操作符進(jìn)行處理申請和銷毀。
大家一定要問了,我們一般都是這樣處理的呀!!沒有什么可以說的哦!!呵呵,我感覺就有還是有一些東東和大家聊的哦。先聊簡單幾條吧!!
1.Malloc(…..)和free(….), new ….和 delete …必須成對出現(xiàn)不可以混雜哦,混雜的話,后果就不可以想了哦!!(也沒有什么,就是內(nèi)存被泄漏了,呵呵)
2.在我們使用new …和delete ….一定要注意一些細(xì)節(jié),否則后果同上哦!!什么細(xì)節(jié)呢?下面看一個(gè)簡單的例子:
char *block_memory = NULL;
block_memory = new char[1024];
delete block_memory;
block_memory = NULL;
大家沉思一會。。。。。。。。。
大家看有錯(cuò)嗎?沒有錯(cuò)吧!!
如果說沒有錯(cuò)的,就要好好補(bǔ)補(bǔ)課了,是有錯(cuò)的,上面實(shí)際申請的內(nèi)存是沒有完全被釋放的,為什么呢?因?yàn)榇蠹覜]有注意第一條的完全匹配原則哦,在new 的時(shí)候有[ ],我們在delete 怎么就沒有看見[ ] 的影子呢? 這就造成了大錯(cuò)有1023個(gè)字節(jié)沒有被釋放。正確的是 : delete []block_memory;
關(guān)于內(nèi)存基本操作的我是說這兩條,其他要注意還是有的,基本就源于此了。
了解了上面那些接下來就想大家說說服務(wù)器內(nèi)存處理技術(shù)了。上面都沒有弄清楚了,就算了。呵呵。
大家都知道,我們的服務(wù)器要頻繁的響應(yīng)客戶端的消息同時(shí)要將消息發(fā)送到客戶端,并且還要處理服務(wù)器后臺游戲World的運(yùn)行。這樣我們就必須要大量的使用內(nèi)存,并且要進(jìn)行大量的內(nèi)存操作(申請和銷毀)。而在這樣的操作中,我們還必須要保證我們的絕對正確無誤,否則就會造成內(nèi)存的泄漏,而內(nèi)存泄漏對于服務(wù)器而言是非常可怕的,也可能就是我們服務(wù)器設(shè)計(jì)失敗的毒藥。而我們?nèi)绾芜M(jìn)行服務(wù)器內(nèi)存的正確和合理的管理呢?那就是我們
必須建立一套適合我們自己的內(nèi)存管理技術(shù)。現(xiàn)在就向大家說一說我在內(nèi)存管理方面的一些做法。
基本原理先用圖形表示一下:
回收內(nèi)存塊
超大塊內(nèi)存
現(xiàn)在要申請的內(nèi)存塊
上面的意思是:我們在服務(wù)器啟動過程中就為自己申請一塊比較大的內(nèi)存塊,而我們在服務(wù)器運(yùn)行過程中需要使用內(nèi)存我們就到這樣一塊比較大已經(jīng)申請好的內(nèi)存塊中去取。而使用完后要進(jìn)行回收。原理就是這么簡單。而最重要的是我們?nèi)绾喂芾磉@個(gè)大的內(nèi)存塊呢?
(非常復(fù)雜也比較難,呵呵)
首先 就內(nèi)存塊操作而言就只有申請(類似 new)和回收(類似 delete)。
其次 我們必須要清楚那些內(nèi)存我們在使用中,那些是可以申請的。
關(guān)于上面我簡單將這樣的一些數(shù)據(jù)結(jié)構(gòu)和class定義在下面供大家參考使用。
typedef struct MemoryBlock //內(nèi)存塊結(jié)構(gòu)
{
void *buffer; //內(nèi)存塊指針
int b_Size; //內(nèi)存塊尺寸
} MemoryBlock;
class CMemoryList //列表對象類(相當(dāng)于數(shù)組管理類)
{
public:
CMemoryList();
virtual ~ CMemoryList();
void InitList(int data_size,int data_num);//初始化列表數(shù)據(jù)結(jié)構(gòu)尺寸和數(shù)量
void AddToList(void *data); //加入列表中
void DeleteItem(int index); //刪除指定索引元素
……………..
private:
void Init();
void Release();
private:
void *memory;
int total_size;
int total_num;
protected:
};
classs CMemoryPool //內(nèi)存池處理類
{
public:
CMemoryPool();
virtual ~ CMemoryPool();
bool InitMemoryPool(int size); //初始化內(nèi)存池
void * ApplicationMemory(int size); //申請指定size內(nèi)存
void CallBackMemory(void *,int size); //回收指定size內(nèi)存
private:
void Init();
void Release():
MemoryBlock *UniteMemory(MemoryBlock *block_a,MemoryBlock * block_b); //合并內(nèi)存
private:
MemoryBlock memoryPool_Block; //內(nèi)存池塊
CMemoryList *callBackMemory_List; //回收內(nèi)存列表
CMemoryList *usingMemory_List; //使用中內(nèi)存列表
CMemoryList *spacingMemory_List; //空白內(nèi)存列表
protected:
};
以上就是這個(gè)內(nèi)存管理類的一些基本操作和數(shù)據(jù)定義,class CMemoryList 在這里不是重點(diǎn)暫且就不說了,有空再聊。而具體的內(nèi)存池處理方法簡單敘述如下:
函數(shù)InitMemoryPool(): 初始化申請一塊超大內(nèi)存。
函數(shù)ApplicationMemory():申請指定尺寸,申請內(nèi)存成功后,要將成功申請的內(nèi)存及其尺寸標(biāo)示到usingMemory_List列表,同時(shí)要將spacingMemory_List列表進(jìn)行重新分配。以便于正確管理。
函數(shù)CallBackMemory():回收指定尺寸內(nèi)存,成功回收后,要修改spacingMemory_List列表,同時(shí)如果有相鄰的內(nèi)存塊就要合并成一個(gè)大的內(nèi)存塊。usingMemory_List修改使用列表,要在使用列表中的這一項(xiàng)刪除。
以上就是一些簡單處理說明,更加詳細(xì)的就需要大家自己琢磨和處理了。我就不細(xì)說了。呵呵。不足之處就請大家進(jìn)行指正,以便讓我們大家都提高。先謝謝了。