網絡遊戲製作技術(四)

 

服務器程序設計部分

續上在這裏我將要向大家簡單介紹一下游戲服務器中必須要處理另外一項主要技術:
內存分配處理技術也可以稱爲內存池處理技術(這個比較洋氣,前面通俗的好,呵呵)

開始向大家介紹一般情況下我們對於內存的一些基本操作。簡單而言,內存操作就只有三個步驟:申請、使用、銷燬。而對於這些操作我們在C和C++中的處理方式略有不同:

在C中我們一般用malloc(….)函數來進行申請,而對應銷燬已經申請的內存使用free(…)函數。
在C++我們一般使用new操作符和delete操作符進行處理申請和銷燬。
大家一定要問了,我們一般都是這樣處理的呀!!沒有什麼可以說的哦!!呵呵,我感覺就有還是有一些東東和大家聊的哦。先聊簡單幾條吧!!
1.Malloc(…..)和free(….), new ….和 delete …必須成對出現不可以混雜哦,混雜的話,後果就不可以想了哦!!(也沒有什麼,就是內存被泄漏了,呵呵)
2.在我們使用new …和delete ….一定要注意一些細節,否則後果同上哦!!什麼細節呢?下面看一個簡單的例子:
char  *block_memory  = NULL;
block_memory  = new  char[1024];
delete  block_memory;
block_memory = NULL;
大家沉思一會。。。。。。。。。
大家看有錯嗎?沒有錯吧!!
如果說沒有錯的,就要好好補補課了,是有錯的,上面實際申請的內存是沒有完全被釋放的,爲什麼呢?因爲大家沒有注意第一條的完全匹配原則哦,在new 的時候有[ ],我們在delete 怎麼就沒有看見[ ] 的影子呢? 這就造成了大錯有1023個字節沒有被釋放。正確的是 : delete []block_memory;

關於內存基本操作的我是說這兩條,其他要注意還是有的,基本就源於此了。

瞭解了上面那些接下來就想大家說說服務器內存處理技術了。上面都沒有弄清楚了,就算了。呵呵。

大家都知道,我們的服務器要頻繁的響應客戶端的消息同時要將消息發送到客戶端,並且還要處理服務器後臺遊戲World的運行。這樣我們就必須要大量的使用內存,並且要進行大量的內存操作(申請和銷燬)。而在這樣的操作中,我們還必須要保證我們的絕對正確無誤,否則就會造成內存的泄漏,而內存泄漏對於服務器而言是非常可怕的,也可能就是我們服務器設計失敗的毒藥。而我們如何進行服務器內存的正確和合理的管理呢?那就是我們
必須建立一套適合我們自己的內存管理技術。現在就向大家說一說我在內存管理方面的一些做法。
基本原理先用圖形表示一下:

 

 

 

 

回收內存塊
超大塊內存
       現在要申請的內存塊

上面的意思是:我們在服務器啓動過程中就爲自己申請一塊比較大的內存塊,而我們在服務器運行過程中需要使用內存我們就到這樣一塊比較大已經申請好的內存塊中去取。而使用完後要進行回收。原理就是這麼簡單。而最重要的是我們如何管理這個大的內存塊呢?
(非常複雜也比較難,呵呵)
首先 就內存塊操作而言就只有申請(類似 new)和回收(類似 delete)。
其次 我們必須要清楚那些內存我們在使用中,那些是可以申請的。

關於上面我簡單將這樣的一些數據結構和class定義在下面供大家參考使用。

   typedef  struct  MemoryBlock           //內存塊結構
{
    void  *buffer;                      //內存塊指針
    int    b_Size;                      //內存塊尺寸
} MemoryBlock;

class   CMemoryList                  //列表對象類(相當於數組管理類)
{
    public:
        CMemoryList();
        virtual ~ CMemoryList();
        void   InitList(int  data_size,int data_num);//初始化列表數據結構尺寸和數量
        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                                   //內存池處理類
{
    public:
        CMemoryPool(); 
        virtual ~ CMemoryPool();
        bool   InitMemoryPool(int  size);                 //初始化內存池
void *  ApplicationMemory(int size);               //申請指定size內存
void   CallBackMemory(void *,int size);            //回收指定size內存

    private:
        void   Init();
        void   Release():
        MemoryBlock  *UniteMemory(MemoryBlock  *block_a,MemoryBlock  * block_b);                                                  //合併內存


    private:
       MemoryBlock  memoryPool_Block;                 //內存池塊
       CMemoryList  *callBackMemory_List;              //回收內存列表
       CMemoryList  *usingMemory_List;                 //使用中內存列表
       CMemoryList  *spacingMemory_List;               //空白內存列表
    protected:
};

以上就是這個內存管理類的一些基本操作和數據定義,class  CMemoryList  在這裏不是重點暫且就不說了,有空再聊。而具體的內存池處理方法簡單敘述如下:

   函數InitMemoryPool():  初始化申請一塊超大內存。
   函數ApplicationMemory():申請指定尺寸,申請內存成功後,要將成功申請的內存及其尺寸標示到usingMemory_List列表,同時要將spacingMemory_List列表進行重新分配。以便於正確管理。
   函數CallBackMemory():回收指定尺寸內存,成功回收後,要修改spacingMemory_List列表,同時如果有相鄰的內存塊就要合併成一個大的內存塊。usingMemory_List修改使用列表,要在使用列表中的這一項刪除。

以上就是一些簡單處理說明,更加詳細的就需要大家自己琢磨和處理了。我就不細說了。呵呵。不足之處就請大家進行指正,以便讓我們大家都提高。先謝謝了。

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