欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
內存管理 - 動(dòng)態(tài)開(kāi)辟內存
關(guān)于內存管理,以前我在PC機上研究系統內核時(shí)接觸過(guò)。那要求在把CPU設置為32位后統一給內存做影射,而我們今天要討論的內存管理比那是要簡(jiǎn)單多了。
    前兩天拿朋友的51單片機開(kāi)發(fā)板玩(用的Keil),突然萌發(fā)做個(gè)貪食蛇的想法,經(jīng)過(guò)考慮我打算用鏈表來(lái)做(當然,結果證明用鏈表做很不值得)可在快完工的時(shí)候我傻眼啦,蛇在吃了食物后整個(gè)屏幕都花啦(用的LCD12864的液晶屏)。本來(lái)蛇每吃一個(gè)食物其實(shí)就是動(dòng)態(tài)再開(kāi)辟一段蛇身。這樣看來(lái)顯然是動(dòng)態(tài)開(kāi)辟內存失敗,導致繪制蛇身函數在逐個(gè)查找鏈表的每個(gè)節點(diǎn)的時(shí)候有一環(huán)被破壞沒(méi)有連接到下一環(huán)。
    再追查下去,應該就是 malloc() 函數沒(méi)有發(fā)揮作用,可是很納悶 Keil 編譯器并沒(méi)有報告錯誤?,F在問(wèn)題找到了,可要解決這個(gè)問(wèn)題那就必須自己能構造一個(gè) malloc() 函數。后來(lái)我查看了 malloc() 函數,具體實(shí)現如下:
    
    struct __mem__
    {
         struct __mem__ _MALLOC_MEM_ *next;        /* single-linked list */
         unsigned int                len;                              /* length of following block */
    };

    typedef struct __mem__         __memt__;
    typedef __memt__ _MALLOC_MEM_ *__memp__;
    #define    HLEN    (sizeof(__memt__))
    extern __memt__ _MALLOC_MEM_ __mem_avail__ [];
    #define AVAIL    (__mem_avail__[0])
    #define MIN_BLOCK    (HLEN * 4)

    void _MALLOC_MEM_ *malloc (unsigned int size)
    {
        __memp__ q;             /* ptr to free block */
        __memp__ p;             /* q->next */
        unsigned int k;            /* space remaining in the allocated block */

        q = &AVAIL;
        while (1)
        {
            if ((p = q->next) == NULL)
            {
                return (NULL);        /* FAILURE */
            }
           if (p->len >= size)
               break;
           q = p;
       }
       k = p->len - size;        /* calc. remaining bytes in block */
       if (k < MIN_BLOCK)        /* rem. bytes too small for new block */
       {
           q->next = p->next;
           return (&p[1]);        /* SUCCESS */
       }
       k -= HLEN;
       p->len = k;
       q = (__memp__ ) (((char _MALLOC_MEM_ *) (&p [1])) + k);
       q->len = size;

       return (&q[1]);            /* SUCCESS */
    }

在這我們可以看到其實(shí)他就是利用一個(gè)鏈表在內存中去搜索一段連續的空閑內存,并把首地址傳回??蔀槭裁此谖沂褂玫?1單片機開(kāi)發(fā)板上沒(méi)有發(fā)揮作用呢?經(jīng)過(guò)分析,我恍然大悟。大家試想一下如果讓你去分配一段內存,那么我們就必須有個(gè)紀錄哪些內存在使用哪些內存空閑的機制。拿TC或VC在PC機上實(shí)驗一下使用 malloc() 函數看看?它作用發(fā)揮良好,看來(lái)這個(gè)機制是由OS來(lái)完成的,而在我們那51單片機的裸機上有個(gè)毛的OS啊,也難怪 malloc() 函數不能成功的分配內存?,F在找到問(wèn)題的本質(zhì),那我們就來(lái)自己構造 malloc() 函數。


    建立自己的數據類(lèi)型:
    文件名:MY_Type.h
    內容:
    /* 自定義類(lèi)型,方便書(shū)寫(xiě)與在不同平臺進(jìn)行移植 */
    typedef char            INT8;
    typedef int               INT16;
    long                         INT32;
    /*typedef float          F32;
    typedef double         F64;*/
        }
                            /* i, j 兩層for循環(huán)用于查找管理列表目前的空閑內存         */
        for (i = 0; i < MEM_LIST; i++)
        {
        Enter = 128;
        for (j = 0; j < 7; j++)
        {
            if ((Mem.list[i] & Enter) != Enter)    /* 查找管理列表,直至查早到空閑內存                */
            {
            for (k = (i<<3)+j; k < (i<<3)+j+Size; k++)
            {
                Set_bit(k, 1);            /* 從空閑內存首地址開(kāi)始按Size大小設置被使用的內存        */
            }
            return &Mem.mem[(i << 3) + j];    /* 內存開(kāi)辟成功,返回首地址                    */
               }   
            Enter >>= 1;
        }
        }

        return NULL;                    /* 內存開(kāi)辟失敗,返回空指針                    */
    }

此函數通過(guò)檢查管理列表,找到空閑內存的啟始地址,并把管理列表對應的位置1,并返回空閑內存啟始地址。


    釋放內存:

    void Free(UINT8 *Mem1, UINT8 Size);            /* 釋放開(kāi)辟的內存                        */
    void Free(UINT8 *Mem1, UINT8 Size)
    {
        UINT8 i;
      
                            /* Mem1 - &Mem.mem[0] 計算出Mem1指向的地址為Mem.mem的第幾元素    */
        for (i = (Mem1 - &Mem.mem[0]); i < (Mem1 - &Mem.mem[0] + Size); i++)
        {
        Set_bit(i, 0);                /* 從指定內存首地址開(kāi)始按Size大小設置被內存空閑            */ 
        }
    }

此函數可以“釋放”掉被開(kāi)辟的內存空間。當然,這個(gè)釋放不是真正意義上的釋放,只是把管理列表的相對應位設置為0,表示內存空閑。

    
    好了,到此這個(gè)內存管理技術(shù)全部介紹完畢。他全部也就四個(gè)函數,我們可以做個(gè)小實(shí)驗。

#include <stdio.h>
#include "MY_Mem.h"

int main()
{
    INT32 *i;
    UINT8 *j;

    Init_mem();                        /* 初始化內存管理機制                         */
    j = (UINT8 *)Malloc(sizeof(UINT8));
    i = (INT32 *)Malloc(sizeof(INT32));

    *j = 30;
    *i = 6789324;

    printf("%d %d\n", *j, j);                /* 打印j所指向地址存放的元素和j                    */
    printf("%d %d\n", Mem.mem[0], &Mem.mem[0]);        /* 打印Mem.mem[0]和Mem.mem[0]的地址                */

    printf("%ld %d\n", *i, i);                /* 打印i所指向地址存放的元素和i                    */
    printf("%d", &Mem.mem[1]);                /* 打印Mem.mem[1]的地址                        */
   
    Free(j, sizeof(UINT8));
    Free(i, sizeof(UINT8));
    
    getch();
}

你可以用TC或VC編譯,我用TC編譯的結果是:
30 1121
30 1121
6789324 1122
1122

用不同的編譯器結構可能有點(diǎn)不同,但 j = &Mem.mem[0], i = &Mem.mem[1];卻是絕對成立的,這說(shuō)明我們的內存管理機制起作用了,我們成功的實(shí)現內存的統一管理,并實(shí)現了動(dòng)態(tài)開(kāi)辟內存。


    總結:
    以上闡述的思路,其實(shí)很簡(jiǎn)單。也許大家在看到這時(shí)就覺(jué)得這個(gè)很小兒科了。我也承認這的確很小兒科。說(shuō)到底,其實(shí)就是先開(kāi)辟好內存然后再來(lái)使用,但作為一個(gè)思路我希望對您有一定啟發(fā)和幫助,同時(shí)也希望和大家共同交流和探討。當然,任何事物和方法都有兩面性,這個(gè)內存管理也不列外。
    缺點(diǎn):由于要開(kāi)辟一個(gè)列表來(lái)紀錄內存的使用狀態(tài),所以增大了內存的開(kāi)銷(xiāo),如上所示,40個(gè)字節的內存就需要5個(gè)字節的管理列表。
    優(yōu)點(diǎn):這個(gè)方法簡(jiǎn)單方便,在單片機這樣的平臺上你想像在PC機上那樣花大力氣去做內存的影射嗎?而且那樣做內存的額外開(kāi)銷(xiāo)也不一定比此方法的少。并且是按字節大小以順序方式開(kāi)辟內存,不存在什么所謂的內存碎片。
    當然,大家在使用著(zhù)套方法的時(shí)候一定主要將Malloc()和Free()函數配套使用,并且要保證里面的Size參數一樣。當然你也可以進(jìn)一步改進(jìn)此方法,讓他使用的更合理更安全。
    typedef unsigned char      UINT8;
    typedef unsigned int         UINT16;
    typedef unsigned long      UINT32;
    /*typedef unsigned float    UF32;
    typedef unsigned double    UF64;*/


    總體具體分析:
    為了能有效果的對內存進(jìn)行管理,我們必須保證內存時(shí)時(shí)刻刻都能被指定并被紀錄是否空閑,那么最好的做法就是先開(kāi)辟好一定空間再統一管理。當然這段內存空間也必須是全局的。然后我們必須建立一個(gè)紀錄列表,紀錄下內存的使用狀態(tài),以便管理。


    建立管理機制:
    我們可以構造一個(gè)結構,將紀錄列表和實(shí)際使用內存綁定起來(lái)。具體代碼如下:

    #define    MEM_COUNT    40            /* 實(shí)際使用內存40個(gè)字節                     */
    #define    MEM_LIST    MEM_COUNT >> 3        /* 管理列表 40/8 = 5個(gè)字節                    */

    typedef struct
    {
        UINT8    list[MEM_LIST];                /* 管理列表共40位與實(shí)際使用內存一一對應,1表示使用中,0表示空閑    */
        INT8    mem[MEM_COUNT];                /* 實(shí)際使用內存40個(gè)字節                        */
    }MEM;                        /* 管理機制結構                            */
    MEM Mem;                        /* 管理機制數據                            */

到此我們就把內存管理機制的核心部分建立起來(lái)了,我們可以作這樣一個(gè)表來(lái)說(shuō)明他的工作方式:

                     Mem.list[0]           ... ...        Mem.list[5]       
           ┏━┳━┳━┳┻┳━┳━┳━┓        ┏━┳━┳━┳┻┳━┳━┳━┓    
位         7   6   5   4   3   2   1   0         7   6   5   4   3   2   1   0    
           ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃        ┃  ┃  ┃  ┃  ┃  ┃  ┃  ┃
Mem.mem[]     0   1   2   3   4   5   6   7          32  33  34  35  36  37  38  39  (表一)

從上表一可以很直觀(guān)的理解 Mem.list 的5個(gè)字節共40位,與 Mem.mem 的40個(gè)字節一一對應,我們就是通過(guò)檢查 Mem.list 各位的狀態(tài)來(lái)確定哪些內存在使用哪些內存空閑。


    初始化管理系統:
    這個(gè)很簡(jiǎn)單,初始化即是內存全部可用,Mem.list 全部置0,具體實(shí)現函數:

    void Init_mem(void);
    void Init_mem()
    {
        UINT8 i;
    
        for (i = 0; i < MEM_LIST; i++)
        {
        Mem.list[i] = 0;                /* 管理列表共40位全部置0,表示內存可用                */
        }
    }
經(jīng)過(guò)此函數,Mem.mem 的40個(gè)字節內存被標記為可使用。


    動(dòng)態(tài)開(kāi)辟內存:
    即像 malloc() 函數那樣,分配指定字節的內存,具體實(shí)現函數:
    
    void Set_bit(UINT8 Bit, UINT8 mode);        /* 設置管理列表的第Bit位為mode                    */ 
    void *Malloc(UINT8 Size);                /* 分配Size字節大小的內存,返回首地址                */

    void Set_bit(UINT8 Bit, UINT8 mode)
    {
        UINT8 Enter = 128;

        Enter >>= (Bit % 8);    
        if (mode)
        {
            Mem.list[Bit >> 3] |= Enter;        /* 將管理列表的第Bit位置1,表示已被使用                */
        }
        else
        {
        Mem.list[Bit >> 3] ^= Enter;        /* 將管理列表的第Bit位置0,表示處于空閑                */
        }
    }

    void *Malloc(UINT8 Size)
    {
        UINT8 i, j, k, Enter;

    
        if (Size > MEM_COUNT || Size < 1)
        {
        return NULL;                /* 內存開(kāi)辟失敗,返回空指針                    */
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
C++常用庫函數atoi,itoa,strcpy,strcmp,malloc,free的實(shí)現
vxWorks內核解讀-5
處理動(dòng)態(tài)鏈表所需的函數
C基礎—指針/指針與動(dòng)態(tài)變量/指針與數組/指針與函數
一文搞懂棧(stack)、堆(heap)、單片機裸機內存管理malloc
C語(yǔ)言中手把手教你動(dòng)態(tài)內存分配
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久