[RTT例程练习] 3.3 静态内存管理,内存池mempool

内存池是一种静态的内存管理方法。它预先将一块固定连续的内存区域划分成几个大小不同的块。使用者申请时就将对应大小的内存块给他。这种方法的优点是不会有内存碎片,但不够灵活,适用于需要频繁存取的场合,例如buffer。

这个例子有两个线程。thread1不停分配内存块,但其中并没有使用delay() 来使自己挂起,所以thread2 由于优先级低于 thread1 而一直得不到运行。thread1 分配完所有内存块以后,又试着再取得一个内存块,由于内存块已经被分配完,所以thread1 会因为得不到资源而被挂起。此时thread2 开始运行,释放内存块,释放了一个以后,thread1 的等待条件满足而执行了一次,然后thread2 继续运行直至结束。

程序:

#include <rtthread.h>

static rt_uint8_t *ptr[48];
static rt_uint8_t mempool[4096];
static struct rt_mempool mp;

static rt_thread_t tid1 = RT_NULL;
static rt_thread_t tid2 = RT_NULL;

static void thread1_entry(void* parameter)
{
    int i,j = 1;
    char *block;

    while(j--)
    {
        for (i = 0; i < 48; i++)
        {
            /* 申请内存块 */
            rt_kprintf("allocate No.%d\n", i);
            if (ptr[i] == RT_NULL)
            {
                ptr[i] = rt_mp_alloc(&mp, RT_WAITING_FOREVER);
            }
        }

        /* 继续申请一个内存块,因为已经没有内存块,线程应该被挂起 */
        block = rt_mp_alloc(&mp, RT_WAITING_FOREVER);
        rt_kprintf("allocate the block mem\n");
        /* 释放这个内存块 */
        rt_mp_free(block);
        block = RT_NULL;
    }
}

static void thread2_entry(void *parameter)
{
    int i,j = 1;

    while(j--)
    {
        rt_kprintf("try to release block\n");

        for (i = 0 ; i < 48; i ++)
        {
            /* 释放所有分配成功的内存块 */
            if (ptr[i] != RT_NULL)
            {
                rt_kprintf("release block %d\n", i);

                rt_mp_free(ptr[i]);
                ptr[i] = RT_NULL;
            }
        }

        /* 休眠10个OS Tick */
        rt_thread_delay(10);
    }
}



int rt_application_init()
{
    int i;
    for (i = 0; i < 48; i ++) ptr[i] = RT_NULL;

    /* 初始化内存池对象 ,每块分配的大小为80,但是另外还有大小为4的控制头,所以实际大小为84*/
    rt_mp_init(&mp, "mp1", &mempool[0], sizeof(mempool), 80);

    /* 创建线程1 */
    tid1 = rt_thread_create("t1",
        thread1_entry, RT_NULL, 512, 8, 10);
    if (tid1 != RT_NULL)
        rt_thread_startup(tid1);

    /* 创建线程2 */
    tid2 = rt_thread_create("t2",
    thread2_entry, RT_NULL, 512, 9, 10);
    if (tid2 != RT_NULL)
        rt_thread_startup(tid2);

    return 0;
}

结果:

allocate No.0
allocate No.1
allocate No.2
allocate No.3
allocate No.4
allocate No.5
allocate No.6
allocate No.7
allocate No.8
allocate No.9
allocate No.10
allocate No.11
allocate No.12
allocate No.13
allocate No.14
allocate No.15
allocate No.16
allocate No.17
allocate No.18
allocate No.19
allocate No.20
allocate No.21
allocate No.22
allocate No.23
allocate No.24
allocate No.25
allocate No.26
allocate No.27
allocate No.28
allocate No.29
allocate No.30
allocate No.31
allocate No.32
allocate No.33
allocate No.34
allocate No.35
allocate No.36
allocate No.37
allocate No.38
allocate No.39
allocate No.40
allocate No.41
allocate No.42
allocate No.43
allocate No.44
allocate No.45
allocate No.46
allocate No.47
try to release block
release block 0
allocate the block mem
release block 1
release block 2
release block 3
release block 4
release block 5
release block 6
release block 7
release block 8
release block 9
release block 10
release block 11
release block 12
release block 13
release block 14
release block 15
release block 16
release block 17
release block 18
release block 19
release block 20
release block 21
release block 22
release block 23
release block 24
release block 25
release block 26
release block 27
release block 28
release block 29
release block 30
release block 31
release block 32
release block 33
release block 34
release block 35
release block 36
release block 37
release block 38
release block 39
release block 40
release block 41
release block 42
release block 43
release block 44
release block 45
release block 46
release block 47


下载时请看下面说明,对写一个动态的内存池很有帮助。 这是一个用C++语言链表的方法实现的一个静态内存池代源码。原理就是先向系统申请一块大内存,然后把这一大块分隔成相等的很多小块,然后在这这些小块的首地址部份放一个结构体,结构体中有一个值是用来标明这一小块是否使用中。在这里存放你要放存的数据就是用结构体首地址加结构体自身长度就得到要放数据的首地址了.具体看代码的实现吧。我说一下动态内存池的写法。那是我给公司写的就不能上传了。结构体和静态内存池的这个差不多一样,只是增加了一个成员用来记录每一节点到大块内存的首地址在到本节点的一个尺寸长度值,做法也是先申请一块大内存。我先从释放说起吧,释放本节点时看自己的相邻节点是不是有释放掉的,如果有则合并掉他们成为一个块,如果碰到相邻的节点是另外的一个大块的话就不用合并了,原因他和自己所在的这一个大块内存上物理地址不是连续,这里一定要记住,释放过程算法怎么去写就看你的了。下面是分配写法要考虑的。在分配一小块内存给高层使用时,如果是分配在尾节点去分配的情况,那好办啊,尾节点如果不够分配了就直接从系统去申请一块大内存,节点连起来在分配,这里有可能会浪费掉一小块以结构体大小的一块内存,如果够分配就直接分配了。如果是在中间节点去分配,这里就要将释放时合并的如果大于现在要分配的就拆开来用,如果拆开剩余的那一部份只有结构体大小就不用在拆开了。这些都是要考虑的东西,优化加快速度就看你自己了.可能看时不些不明白,看静态内存的写法后你就明白了.有时我也要下载其他人共享的东西,所以就一分吧.哈哈~~~~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值