⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 malloc.c

📁 Linux0.01存储管理代码 最精简的linux存储管理代码 适合初学者
💻 C
字号:
/*****************************************************************************Simple mallocLast revised: Oct 30, 2002Features:- First-fit- free() coalesces adjacent free blocks- Uses variable-sized heap, enlarged with kbrk()/sbrk() function- Does not use mmap()- Can be easily modified to use fixed-size heap- Works with 16- or 32-bit compilersBuild this program with either of the two main() functions, then run it.Messages that indicate a software error will contain three asterisks (***).This code is public domain (no copyright).You can do whatever you want with it.Chris Giese <geezer@execpc.com>	http://www.execpc.com/~geezer*****************************************************************************/#include <string.h> /* memcpy(), memset() */#include <stdio.h> /* printf() */#if defined(__TURBOC__)/* nothing */#elif defined(__DJGPP__)#define	_32BIT	1#elif defined(__WATCOMC__)#if defined(__386__)#define	_32BIT	1#else/* nothing */#endif#else#error Unsupported compiler.#endif/* use small (32K) heap for 16-bit compilers,large (500K) heap for 32-bit compilers */#if defined(_32BIT)#define	HEAP_SIZE	500000uL#else#define	HEAP_SIZE	32768u#endif#define	MALLOC_MAGIC	0x6D92	/* must be < 0x8000 */typedef struct _malloc		/* Turbo C	DJGPP */{    size_t size;		/* 2 bytes	 4 bytes */    struct _malloc *next;	/* 2 bytes	 4 bytes */unsigned magic : 15;	/* 2 bytes total 4 bytes total */unsigned used : 1;} malloc_t;		/* total   6 bytes	12 bytes */static char *g_heap_bot, *g_kbrk, *g_heap_top;/**********************************************************************************************************************************************************/static void dump_heap(void){    unsigned blks_used = 0, blks_free = 0;    size_t bytes_used = 0, bytes_free = 0;    malloc_t *m;    int total;    printf("===============================================\n");    for(m = (malloc_t *)g_heap_bot; m != NULL; m = m->next)    {        printf("blk %5p: %6u bytes %s\n", m,               m->size, m->used ? "used" : "free");        if(m->used)        {            blks_used++;            bytes_used += m->size;        }        else        {            blks_free++;            bytes_free += m->size;        }    }    printf("blks:  %6u used, %6u free, %6u total\n", blks_used,           blks_free, blks_used + blks_free);    printf("bytes: %6u used, %6u free, %6u total\n", bytes_used,           bytes_free, bytes_used + bytes_free);    printf("g_heap_bot=0x%p, g_kbrk=0x%p, g_heap_top=0x%p\n",           g_heap_bot, g_kbrk, g_heap_top);    total = (bytes_used + bytes_free) +            (blks_used + blks_free) * sizeof(malloc_t);    if(total != g_kbrk - g_heap_bot)        printf("*** some heap memory is not accounted for\n");    printf("===============================================\n");}/*****************************************************************************POSIX sbrk() looks like this	void *sbrk(int incr);Mine is a bit different so I can signal the calling functionif more memory than desired was allocated (e.g. in a system with paging)If your kbrk()/sbrk() always allocates the amount of memory you ask for,this code can be easily changed.			int brk(	void *sbrk(		void *kbrk(function		 void *adr);	 int delta);		 int *delta);----------------------	------------	------------		-------------POSIX?			yes		yes			NOreturn value if error	-1		-1			NULLget break value		.		sbrk(0)			int x=0; kbrk(&x);set break value to X	brk(X)		sbrk(X - sbrk(0))	int x=X, y=0; kbrk(&x) - kbrk(&y);enlarge heap by N bytes	.		sbrk(+N)		int x=N; kbrk(&x);shrink heap by N bytes	.		sbrk(-N)		int x=-N; kbrk(&x);can you tell if you're  given more memory  than you wanted?	no		no			yes*****************************************************************************/static void *kbrk(int *delta){    static char heap[HEAP_SIZE];    /**/    char *new_brk, *old_brk;    /* heap doesn't exist yet */    if(g_heap_bot == NULL)    {        g_heap_bot = g_kbrk = heap;        g_heap_top = g_heap_bot + HEAP_SIZE;    }    new_brk = g_kbrk + (*delta);    /* too low: return NULL */    if(new_brk < g_heap_bot)        return NULL;    /* too high: return NULL */    if(new_brk >= g_heap_top)        return NULL;    /* success: adjust brk value... */    old_brk = g_kbrk;    g_kbrk = new_brk;    /* ...return actual delta... (for this sbrk(), they are the same)    	(*delta) = (*delta); */    /* ...return old brk value */    return old_brk;}/*****************************************************************************kmalloc() and kfree() use g_heap_bot, but not g_kbrk nor g_heap_top*****************************************************************************/void *kmalloc(size_t size){    unsigned total_size;    malloc_t *m, *n;    int delta;    if(size == 0)        return NULL;    total_size = size + sizeof(malloc_t);    /* search heap for free block (FIRST FIT) */    m = (malloc_t *)g_heap_bot;    /* g_heap_bot == 0 == NULL if heap does not yet exist */    if(m != NULL)    {        if(m->magic != MALLOC_MAGIC)            //			panic("kernel heap is corrupt in kmalloc()");        {            printf("*** kernel heap is corrupt in kmalloc()\n");            return NULL;        }        for(; m->next != NULL; m = m->next)        {            if(m->used)                continue;            /* size == m->size is a perfect fit */            if(size == m->size)                m->used = 1;            else            {                /* otherwise, we need an extra sizeof(malloc_t) bytes for the header                of a second, free block */                if(total_size > m->size)                    continue;                /* create a new, smaller free block after this one */                n = (malloc_t *)((char *)m + total_size);                n->size = m->size - total_size;                n->next = m->next;                n->magic = MALLOC_MAGIC;                n->used = 0;                /* reduce the size of this block and mark it used */                m->size = size;                m->next = n;                m->used = 1;            }            return (char *)m + sizeof(malloc_t);        }    }    /* use kbrk() to enlarge (or create!) heap */    delta = total_size;    n = kbrk(&delta);    /* uh-oh */    if(n == NULL)        return NULL;    if(m != NULL)        m->next = n;    n->size = size;    n->magic = MALLOC_MAGIC;    n->used = 1;    /* did kbrk() return the exact amount of memory we wanted?    cast to make "gcc -Wall -W ..." shut the hell up */    if((int)total_size == delta)        n->next = NULL;    else    {        /* it returned more than we wanted (it will never return less):        create a new, free block */        m = (malloc_t *)((char *)n + total_size);        m->size = delta - total_size - sizeof(malloc_t);        m->next = NULL;        m->magic = MALLOC_MAGIC;        m->used = 0;        n->next = m;    }    return (char *)n + sizeof(malloc_t);}/**********************************************************************************************************************************************************/void kfree(void *blk){    malloc_t *m, *n;    /* get address of header */    m = (malloc_t *)((char *)blk - sizeof(malloc_t));    if(m->magic != MALLOC_MAGIC)        //		panic("attempt to kfree() block at 0x%p "        //			"with bad magic value", blk);    {        printf("*** attempt to kfree() block at 0x%p "               "with bad magic value\n", blk);        return;    }    /* find this block in the heap */    n = (malloc_t *)g_heap_bot;    if(n->magic != MALLOC_MAGIC)        //		panic("kernel heap is corrupt in kfree()");    {        printf("*** kernel heap is corrupt in kfree()\n");        return;    }    for(; n != NULL; n = n->next)    {        if(n == m)            break;    }    /* not found? bad pointer or no heap or something else? */    if(n == NULL)        //		panic("attempt to kfree() block at 0x%p "        //			"that is not in the heap", blk);    {        printf("*** attempt to kfree() block at 0x%p "               "that is not in the heap\n", blk);        return;    }    /* free the block */    m->used = 0;    /* coalesce adjacent free blocks    Hard to spell, hard to do */    for(m = (malloc_t *)g_heap_bot; m != NULL; m = m->next)    {        while(!m->used && m->next != NULL && !m->next->used)        {            /* resize this block */            m->size += sizeof(malloc_t) + m->next->size;            /* merge with next block */            m->next = m->next->next;        }    }}/**********************************************************************************************************************************************************/void *krealloc(void *blk, size_t size){    void *new_blk;    malloc_t *m;    /* size == 0: free block */    if(size == 0)    {        if(blk != NULL)            kfree(blk);        new_blk = NULL;    }    else    {        /* allocate new block */        new_blk = kmalloc(size);        /* if allocation OK, and if old block exists, copy old block to new */        if(new_blk != NULL && blk != NULL)        {            m = (malloc_t *)((char *)blk - sizeof(malloc_t));            if(m->magic != MALLOC_MAGIC)                //				panic("attempt to krealloc() block at "                //					"0x%p with bad magic value", blk);            {                printf("*** attempt to krealloc() block at "                       "0x%p with bad magic value\n", blk);                return NULL;            }            /* copy minimum of old and new block sizes */            if(size > m->size)                size = m->size;            memcpy(new_blk, blk, size);            /* free the old block */            kfree(blk);        }    }    return new_blk;}/**********************************************************************************************************************************************************/#include <stdlib.h> /* rand() */#if 0#define	SLOTS	17int main(void){    unsigned lifetime[SLOTS];    void *blk[SLOTS];    int i, j, k;    dump_heap();    memset(lifetime, 0, sizeof(lifetime));    memset(blk, 0, sizeof(blk));    for(i = 0; i < 1000; i++)    {        printf("Pass %6u\n", i);        for(j = 0; j < SLOTS; j++)        {            /* age the block */            if(lifetime[j] != 0)            {                (lifetime[j])--;                continue;            }            /* too old; free it */            if(blk[j] != NULL)            {                kfree(blk[j]);                blk[j] = NULL;            }            /* alloc new block of random size            Note that size_t==unsigned, but kmalloc() uses integer math,            so block size must be positive integer */#if defined(_32BIT)            k = rand() % 40960 + 1;#else            k = rand() % 4096 + 1;#endif            blk[j] = kmalloc(k);            if(blk[j] == NULL)                printf("failed to alloc %u bytes\n", k);            else                /* give it a random lifetime 0-20 */                lifetime[j] = rand() % 21;        }    }    /* let's see what we've wrought */    printf("\n\n");    dump_heap();    /* free everything */    for(j = 0; j < SLOTS; j++)    {        if(blk[j] != NULL)        {            kfree(blk[j]);            blk[j] = NULL;        }        (lifetime[j]) = 0;    }    /* after all that, we should have a single, unused block */    dump_heap();    return 0;}/**********************************************************************************************************************************************************/#elseint main(void){    void *b1, *b2, *b3;    dump_heap();    b1 = kmalloc(42);    dump_heap();    getch();    b2 = kmalloc(23);    dump_heap();    getch();    b3 = kmalloc(7);    dump_heap();    getch();    b2 = krealloc(b2, 24);    dump_heap();    getch();    kfree(b1);    dump_heap();    getch();    b1 = kmalloc(5);    dump_heap();    getch();    kfree(b2);    dump_heap();    getch();    kfree(b3);    dump_heap();    getch();    kfree(b1);    dump_heap();    return 0;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -