C语言内存池使用模型-2

上一篇 / 下一篇  2012-10-08 10:19:11 / 个人分类:C语言

51Testing软件测试网"fR*nQ)E:g

  五、内存池管理内存机制(单链表管理结构)

1A[-Ww.SM(V051Testing软件测试网6}F,u-_ \B q

  这里主要是讨论,从内存块申请开始,就是申请了一个pheap结构指向内存块,然后内存池以什么形式将内存块组织起来,这一个很重要的结构是struct pfree结构。51Testing软件测试网DO)Qiu5I:Q

^)j\j;Aq0  看一下前面申请内存块之后,这时还只是一个pheap结构,没有和内存池关联起来,在前方我们看到,是通过下面代码进行关联的

9XO{#?HA S051Testing软件测试网)v(M+^ ctG'Kg

_Wu {5E0
    clean = _pool_free(p, _pool_heap_free, (void *)ret);51Testing软件测试网,[0i d&Y3s
    clean->heap = ret; /* for future use in finding used mem for pstrdup */51Testing软件测试网)Ec*i6|D@)qav q0e
    _pool_cleanup_append(p, clean);

\v/J-t TS0  _pool_free为该内存块定义的一个结构进行初始化,如下调用

sNG|#`Y W}051Testing软件测试网UTMr sOu

s$N/S&f"gv#p~0
51Testing软件测试网3joOBP9F%C)W

static struct pfree *_pool_free(pool_t p, pool_cleanup_t f, void *arg)
vq/x"Uo-H[?d0{51Testing软件测试网/f&zs)_/sw$g
    struct pfree *ret;51Testing软件测试网v!s^J;rK[7j}
    while((ret = malloc(sizeof(struct pfree))) == NULL) sleep(1);51Testing软件测试网w?k!O;ai Z
    ret->f = f;
*rU$? ?cS5^0    ret->arg = arg;51Testing软件测试网kA H:`x7r*s'Qc
    ret->next = NULL;

%R,X ? t fIi0

\(s(sbp5Uj7P\2_0    return ret;
cI-{zhUM4lJ0}
51Testing软件测试网8U7R E2t d3[HT

51Testing软件测试网G3j-UtacO])o.J"^Fh j

  这个函数只是定义了一个sturct pfree结构,基本上是用struct pheap这个结构对其进行初始化的,可以看出这个结构的arg和heap域都是指向struct pheap结构。这是很重要的一步,内存池主要是管理这个结构的。51Testing软件测试网Io$uMv;i6m

)e^;p&^k)z}*A3wy0  注意这里的pool_cleanup_t是一个函数指针,在我们这里,它是_pool_heap_free。用于指示如何释放这个内存块,实现很简单,如下:51Testing软件测试网1v-}bu7l

w3h@B.p$g0

~5x+A.C9E.U%g5u0
static void _pool_heap_free(void *arg)
ms}u#P%Y'r0{51Testing软件测试网,s/Q"@ [&UuW]
    struct pheap *h = (struct pheap *)arg;51Testing软件测试网+m!OX\$K|8B| o
    free(h->block);51Testing软件测试网1EkC0mz Q? ]^&}s.P
    free(h);
H}0O,AR ` ['G zDoR0}

"_s V5}4g6p4IKiv0  这个释放函数就很简单了吧,下面继续我们话题。51Testing软件测试网M(vaf,l/f

6h2D Fj U0N]e z0  前文说了内存池包含链表,管理内存块,那接下来的操作是不是要将这个内存块【struct pfree】加到链表上。看一下_pool_cleanup_append函数做哪些工作51Testing软件测试网n&Jb)\6Ha9b

51Testing软件测试网VG*@.z+I6\ t(RB

51Testing软件测试网H B!B"]g

51Testing软件测试网)Wc UyV1@u

static void _pool_cleanup_append(pool_t p, struct pfree *pf)51Testing软件测试网H `y;Y9CB5K
{51Testing软件测试网3Saf*R!Tb T;s9Pv-^2k
    struct pfree *cur;
51Testing软件测试网8pQ3kW:~ V6[

[5U3|}P$MSTo0    if(p->cleanup == NULL)
.Fo7G6~_+BfhMl2?0    {51Testing软件测试网_}^#T5x+b+jX
        p->cleanup = pf;51Testing软件测试网h gHJ$mScAG
        p->cleanup_tail = pf;
T G{j]0        return;51Testing软件测试网'j2u3J{_
    }
51Testing软件测试网;]euf;Y%s G

s6V!tTK;{tB#A0    cur = p->cleanup_tail;
/P'aBB6|+E0    cur->next = pf;51Testing软件测试网U8b \`(p Aq
    p->cleanup_tail = pf;
+c^OH8`b\W+a0}
51Testing软件测试网zQH^:e$i:e

51Testing软件测试网 VFB M/G ]!wt

  这个函数很简单,将struct pfree结构加到内存池的cleanup_tail链表的末尾,并将新的cleanup_tail指向刚加入的pfree结构。

^2|kw!Y;r u0

w)hfj@?9ld }:G0  到这里,就完成了内存从调用malloc分配至加入到内存池的过程,再回顾一下:51Testing软件测试网 RkvU,?T1V Ik4so

51Testing软件测试网D PmE)PCC

  1、调用malloc分配内存块,并赋值给struct pheap结构。

.WjKYD+LV051Testing软件测试网H|6s;E&?RxT

  2、将struct pheap结构封装成struct pfree结构,这样struct pheap结构就可以成为链表上的元素。

2G'b3r,v.N051Testing软件测试网)Z+X^9H0g7@

  3、将struct pfree结构加入到struct pool_sturct结构【这是内存池的结构】的链表末尾。51Testing软件测试网*LPu-u!M1^l eK|

51Testing软件测试网4FoG*S8i

  六、内存池的释放

*c/xdz)]SZw Y0

Fi xu;H7I0  在内存池的使命结束后,我们需要释放内存池,不仅仅是struct pool_struct这个结构,还包括链表上的内存块。

*`)AY8_)w[.i.D0

xhu-G|*N8F051Testing软件测试网 sIn n.R+P(ta~$FH

y!V8a*Y2o@BO#L0void pool_free(pool_t p)51Testing软件测试网^+^rVdT}
{
^U3WJe4F7O;`2v(OS0    struct pfree *cur, *stub;

ttQ5NGu[u7T0

$K _'p!C(\7`0    if(p == NULL) return;51Testing软件测试网:W6[-x e jZ[

51Testing软件测试网o|o5CM)e

    cur = p->cleanup;51Testing软件测试网.@A)JsC;\7u`A
    while(cur != NULL)51Testing软件测试网3u/Gef2[vSt
    {51Testing软件测试网oF'\QK3^
        (*cur->f)(cur->arg); // 这会释放用malloc分配的内存块和struct pheap结构所占用的内存。这就是前文的_pool_heap_free函数51Testing软件测试网zV9w-o a5_
 stub = cur->next;51Testing软件测试网$G'B"Ko)UW
 free(cur);  // 释放pfree结构。
/WrQpYE0 cur = stub;51Testing软件测试网*dJ/{]2`V
    }
N1w&w~:B]Y}s g0    free(p); //释放pool_struct结构所占用的内存。51Testing软件测试网&[[2c0u-f1\ _
}
51Testing软件测试网1Y4ER~n0wZx*p

51Testing软件测试网H};bznl0uU

  七、从内存池分配内存51Testing软件测试网m_0U*wzd h]'? @

51Testing软件测试网 f-aLL!B:x/h.~

  这个才是本文的重点,如何从内存池中分配一个没有被使用的内存,先看代码,表示从内存池中分配size大小的内存,这个机制也是本文的重点。51Testing软件测试网;a'P'U g?U#|J Z

51Testing软件测试网*qsD%\!HgY

51Testing软件测试网XZ1g%U'~:QbS.S

51Testing软件测试网8G#a%W9f^D.O'QI

void *pool_malloc(pool_t p, int size)51Testing软件测试网'}\uA7] Y G
{51Testing软件测试网)` K |!b}o
    void *block;

z%J pX)@$k x9M;f9X0

?)AA^w7h\0    if(p == NULL)
fn7~{4xj0    {51Testing软件测试网D;s&xr}Z
        fprintf(stderr,"Memory Leak! [pmalloc received NULL pool, unable to track allocation, exiting]\n");51Testing软件测试网e)?:Nfq.d}:`+YO7Q
        abort();51Testing软件测试网wn;TAc cV3TI
    }
51Testing软件测试网Ct:J I2z)h8Pt:o S

"h!h:Mm UWJ0    if(p->heap == NULL || size > (p->heap->size / 2))
"_5?2@gD,tpt0    {51Testing软件测试网DzGd4[b)^
        while((block = malloc(size)) == NULL) sleep(1);51Testing软件测试网$}5D J)fc wEO
        p->size += size;51Testing软件测试网$iO^V1M5wQ
        _pool_cleanup_append(p, _pool_free(p, _pool__free, block));
a4N2q#^1|\%G8D0        return block;
VE DC P0{}0    }

(w5_`$Gu2vZ051Testing软件测试网"n6iK3Y&}-f#f/k3i

    if(size >= 4)51Testing软件测试网 TB4qtr0D%t"L6h hr
        while(p->heap->used&7) p->heap->used++; // 这一步是个对齐操作,如果已经使用的不是8的倍数,就会跳过,直到为8的倍数。
51Testing软件测试网(|{:PgA8f*e1k6IP%K

51Testing软件测试网 |BR|B[

    if(size > (p->heap->size - p->heap->used))51Testing软件测试网}1[#\G-`6^
        p->heap = _pool_heap(p, p->heap->size);

Y+~@a}I&I5tK8}051Testing软件测试网7k ] qj`\BL,C

    block = (char *)p->heap->block + p->heap->used;
K TG0O"T$Qk0    p->heap->used += size; //已经使用部分增加,也会使得内存分配的偏移值指针增加。51Testing软件测试网6Yi;X'}$d_,H pq
    return block;51Testing软件测试网 Vsm2j%`*rKB
}
51Testing软件测试网"x iLS}ps2P;[kx

2S:]p5UKGR0  从上面的代码中,可以看出分配内存的策略如下:51Testing软件测试网 l'Jp2C#C9aF9P

`Q8U@k6u`3gpTmo"| i0  1、如果内存池中没有内存或者将要分配的内存比内存池中总的内存数一半还要大,会调用malloc向系统请求内存。并把分配的内存加入到内存池中。

%_)Edz8JO)WO#ZIS051Testing软件测试网/w!\Wt+i;Uz0nZ"K

  2、已分配的内存按字对齐,如果没有对齐,就会跳过不对齐部分,不对齐的部分标识为已经使用。

U#h1~agb051Testing软件测试网vbP#OL oJ.P$l

  3、如果链表最新的内存块内存剩余的大小不足于分配size字节,会重新请求新的内存块,并加入内存池。51Testing软件测试网{/r?.N D\K&YS

51Testing软件测试网j.F1GS];]

  4、从链表的最后内存块分配,p->heap->used,表示内存块中已经使用的一个偏移,从这里开始分配。

K'| v%kg1O|'C0

TAG:

 

评分:0

我来说两句

Open Toolbar