免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2113 | 回复: 3
打印 上一主题 下一主题

基于用户程序buffer的内存分配 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-01-18 15:11 |只看该作者 |倒序浏览
这是,早时,我在写我的x86-64汇编语言编译器a64时,模拟C库函数malloc及free()的一个小函数

balloc(): buffer- alloc 基于用户的缓冲区的分配方案.
bfree(): 对应于balloc().
写这两个函数,当时只是想用在少量的动态分配方案上, 又想避免在系统的堆空间分配内存.这样不会
因为一点点的动态分配而造成系统内存的丢失.

代码很少:
头文件 "balloc.h"

  1. #ifndef _BALLOC_H_
  2. #define _BALLOC_H_

  3. typedef struct mem_link_struct {
  4.         unsigned int size;
  5.         void *head_ptr;
  6.         void *tail_ptr;

  7.         unsigned char used;                /* is used ? */       
  8.         struct mem_link_struct *next, *prev;
  9. } mem_link_t;


  10. typedef struct alloc_heap_struct {
  11.         unsigned int total_size;
  12.         unsigned int free_size;
  13.         mem_link_t *free_link;
  14.         mem_link_t *used_link;
  15.         void *heap;
  16. } alloc_heap_t;


  17. typedef unsigned int memlink_size_t;

  18. /* free-heap-link total value type, it's a 32-bit type */
  19. typedef unsigned int free_link_size_t;

  20. /* used-heap-link total value type, it's a 32-bit type */
  21. typedef unsigned int used_link_size_t;

  22. /* default user-program buffer pool 64K */
  23. #define POOLSIZE        65536

  24. #define LINKSIZE        256
  25. #define FREELINKSIZE        256
  26. #define USEDLINKSIZE        256


  27. #define EOK                0
  28. #define EINIT                -1
  29. #define EFULLNESS                        -2
  30. #define ENOMEM                -3
  31. #define EERROR                -4

  32. /*

  33. char *e_msg[] = {
  34.         "initialize error",
  35.         "the buffer pool fullness",
  36.         "the buffer pool not enough",

  37.         0
  38. };


  39. */

  40. int init_bheap(unsigned int size, void *ptr);
  41. void *balloc(unsigned int size);
  42. int bfree(void *ptr);


  43. #endif
复制代码



以下是: balloc.c

  1. /*
  2. *
  3. *        the file for mik's assmbler: a64 poject;
  4. *
  5. *
  6. */


  7. #include "balloc.h"

  8. /* free-memory-link buffer */
  9. static mem_link_t free_link_buf[FREELINKSIZE];

  10. /* used-memory-link buffer */
  11. static mem_link_t used_link_buf[USEDLINKSIZE];

  12. /* default buffer-heap for balloc() */
  13. static char buf_heap[POOLSIZE];

  14. /* alloc-heap-struct for balloc() */
  15. static alloc_heap_t alloc_heap, *alloc_heap_ptr = &alloc_heap;



  16. /*
  17. * this function for test....
  18. */


  19. void print_alloc_heap()
  20. {
  21.         mem_link_t *free_link = alloc_heap_ptr->free_link;
  22.         mem_link_t *used_link = alloc_heap_ptr->used_link;

  23.         int i = 1;

  24.         printf("\nfree_link_buf is %x\n", free_link_buf);
  25.         printf("used_link_buf is %x\n", used_link_buf);
  26.         printf("buffer heap is %x\n\n", alloc_heap_ptr->heap);
  27.        
  28.         printf("            free buffer-heap-link:                \n");       
  29.         printf("--------------------------------------------------\n");
  30.         printf("no.\tsize\thead\ttail\tused\n");       

  31.         while (free_link) {
  32.                 printf("%d\t%d\t%x\t%x\t%d\n", i++, free_link->size,
  33.                         free_link->head_ptr, free_link->tail_ptr,
  34.                         free_link->used);
  35.                 free_link = free_link->next;
  36.         }

  37.         puts("\n");
  38.         puts("              used buffer-heap-link:                  ");
  39.         puts("------------------------------------------------------");
  40.         printf("no.\tsize\thead\ttial\tused\n");
  41.        
  42.         i = 1;
  43.         while (used_link) {
  44.                 printf("%d\t%d\t%x\t%x\t%d\n", i++, used_link->size,
  45.                         used_link->head_ptr, used_link->tail_ptr,
  46.                         used_link->used);

  47.                 used_link = used_link->next;
  48.         }

  49. }


  50. __inline__ void init_mem_link()
  51. {
  52.         memset(free_link_buf, 0, sizeof(free_link_buf));
  53.         memset(used_link_buf, 0, sizeof(used_link_buf));
  54. }


  55. int init_alloc_heap(unsigned int size, void *bufptr)
  56. {
  57.         unsigned int poolsize;

  58.         /* initialize the free_link_buf & used_link_buf */
  59.         init_mem_link();       
  60.        
  61.         /* the buffer pool already initialize */
  62.         if (alloc_heap_ptr->heap && alloc_heap_ptr->heap == bufptr)
  63.                 return EOK;

  64.         if (!bufptr) {
  65.                 /* default buffer heap for user */
  66.                 alloc_heap_ptr->heap = (void *)buf_heap;

  67.                 poolsize = POOLSIZE;
  68.         } else {
  69.                 if (!size)
  70.                         return EINIT;
  71.                 alloc_heap_ptr->heap = (void *)bufptr;
  72.                 poolsize = size;
  73.         }

  74.         memset(alloc_heap_ptr->heap, 0, poolsize);
  75.         alloc_heap_ptr->total_size = poolsize;
  76.         alloc_heap_ptr->free_size = poolsize;
  77.         alloc_heap_ptr->used_link = 0;

  78.         alloc_heap_ptr->free_link = &free_link_buf[0];

  79.         /* free-heap-link initialize */
  80.         free_link_buf[0].size = alloc_heap_ptr->free_size;
  81.         free_link_buf[0].head_ptr = (void *)alloc_heap_ptr->heap;
  82.         free_link_buf[0].tail_ptr = (void *)alloc_heap_ptr->heap + poolsize;

  83.         free_link_buf[0].used = 1;
  84.         free_link_buf[0].next = 0;
  85.         free_link_buf[0].prev = 0;
  86.        
  87.                
  88.         /* successed */
  89.         return EOK;
  90. }


  91. /* allocate a mem-link */
  92. unsigned int alloc_memlink(mem_link_t *mem_link)
  93. {
  94.         int i = 0;
  95.         int linksize =
  96.                 mem_link == free_link_buf ? FREELINKSIZE : USEDLINKSIZE;

  97.         while (i < linksize)  {
  98.                 if (mem_link[i].used == 0)        /* free */
  99.                         return i;
  100.                 i++;
  101.         }
  102.        
  103.         return -1;
  104. }

  105. __inline__ unsigned int alloc_free_memlink()
  106. {
  107.         return alloc_memlink(free_link_buf);
  108. }

  109. __inline__ unsigned int alloc_used_memlink()
  110. {
  111.         return alloc_memlink(used_link_buf);
  112. }


  113. /**********************************************************************/

  114. unsigned int mount_link(mem_link_t *link, mem_link_t *new)
  115. {
  116.         int is_free_link = link == alloc_heap_ptr->free_link ? 1 : 0;

  117.         while (link) {
  118.                 if (is_free_link) {
  119.                         if ((link->tail_ptr + 1 == new->head_ptr)
  120.                                 && (link->next->head_ptr == new->tail_ptr + 1))
  121.                         {
  122.                                 link->tail_ptr += new->size + link->next->size;
  123.                                 link->next = link->next->next;
  124.                                 link->size += new->size + link->next->size;
  125.                                 memset(link->next, 0, sizeof(mem_link_t));
  126.                                 memset(new, 0, sizeof(mem_link_t));
  127.                                 return EOK;
  128.                         } else if (link->tail_ptr + 1 == new->head_ptr) {
  129.                                 link->tail_ptr += new->size;
  130.                                 link->size += new->size;
  131.                                 memset(new, 0, sizeof(mem_link_t));
  132.                                 return EOK;
  133.                         } else if (link->head_ptr == new->tail_ptr + 1) {
  134.                                 link->head_ptr -= new->size;
  135.                                 link->size += new->size;
  136.                                 memset(new, 0, sizeof(mem_link_t));
  137.                                 return EOK;
  138.                         }
  139.                 }

  140.                 if (!link->next) break;
  141.                 link = link->next;
  142.         }


  143.         link->next = new;
  144.         link->next->next = 0;
  145.         link->next->prev = link;

  146.         return EOK;
  147. }


  148. /* the function: mount the free memory link */
  149. unsigned int mount_free_link(void *ptr, unsigned int size)
  150. {
  151.         int number = alloc_free_memlink();

  152.         if (number == -1) return -1;
  153.        
  154.         free_link_buf[number].used = 1;
  155.         free_link_buf[number].head_ptr = ptr;
  156.         free_link_buf[number].tail_ptr = ptr + size - 1;
  157.         free_link_buf[number].size = size;

  158.         if (alloc_heap_ptr->free_link)
  159.                 return mount_link(alloc_heap_ptr->free_link,
  160.                         &free_link_buf[number]);
  161.        
  162.         free_link_buf[number].next = 0;
  163.         free_link_buf[number].prev = 0;

  164.         alloc_heap_ptr->free_link = &free_link_buf[number];
  165.        
  166.         return EOK;
  167. }


  168. /* the function: mount the used memory link */
  169. unsigned int mount_used_link(void *ptr, unsigned int size)
  170. {

  171.         int number = alloc_used_memlink();
  172.        
  173.         if (number == -1) return -1;

  174.         used_link_buf[number].used = 1;                /* used by alloc */
  175.         used_link_buf[number].size = size;
  176.         used_link_buf[number].head_ptr = ptr;
  177.         used_link_buf[number].tail_ptr = ptr + size - 1;

  178.         if (alloc_heap_ptr->used_link)
  179.                 return mount_link(alloc_heap_ptr->used_link,
  180.                         &used_link_buf[number]);

  181.         /* no used and full free */       
  182.         used_link_buf[number].next = 0;
  183.         used_link_buf[number].prev = 0;
  184.         alloc_heap_ptr->used_link = &used_link_buf[number];
  185.                
  186.         return EOK;
  187. }


  188. /***********************************************************************/
  189. __inline__ void do_umount_link(mem_link_t *old)
  190. {
  191.         if (old->prev)
  192.                 old->prev->next = old->next;
  193.                
  194.         if (old->next)
  195.                 old->next->prev = old->prev;
  196. }



  197. void umount_free_link(mem_link_t *old, unsigned int size)
  198. {
  199.         old->used = 0;
  200.         alloc_heap_ptr->free_size -= size;
  201.        
  202.         if (!old->prev && !old->next) {
  203.                 /* only 1-node */
  204.                 if (alloc_heap_ptr->free_size == 0)
  205.                         alloc_heap_ptr->free_link = 0;
  206.                 else {
  207.                         old->used = 1;
  208.                         old->size -= size;
  209.                         old->head_ptr += size;
  210.                 }
  211.                        
  212.         } else if (!old->prev) {
  213.                 alloc_heap_ptr->free_link = old->next;
  214.                 old->next->prev = 0;
  215.         } else
  216.                 do_umount_link(old);
  217. }


  218. void umount_used_link(mem_link_t *old)
  219. {
  220.         old->used = 0;
  221.         alloc_heap_ptr->free_size += old->size;

  222.         if (!old->prev && !old->next)
  223.                 if (alloc_heap_ptr->free_size == alloc_heap_ptr->total_size) {

  224.                         alloc_heap_ptr->used_link = 0;
  225.                 } else {
  226.                         old->used = 1;
  227.                 }

  228.         else if (!old->prev) {
  229.                 alloc_heap_ptr->used_link = old->next;
  230.                 old->next->prev = 0;
  231.         } else
  232.                 do_umount_link(old);
  233. }


  234. /***********************************************************************/




  235. /* the function same as C malloc */

  236. void *balloc(unsigned int size)
  237. {
  238.         mem_link_t *free_link = alloc_heap_ptr->free_link;
  239.         mem_link_t *used_link = alloc_heap_ptr->used_link;

  240.         while (free_link && (alloc_heap_ptr->free_size >= size)) {
  241.                 if (free_link->size >= size) {                /* OK */
  242.                         void *ret = free_link->head_ptr;

  243.                         /* mount at used link */
  244.                         if (mount_used_link(ret, size) == -1) {
  245.                                 return 0;
  246.                         }

  247.                         /* umount the free link */
  248.                         umount_free_link(free_link, size);

  249.                         return ret;
  250.                 }
  251.                 free_link = free_link->next;
  252.         }

  253.         return 0;
  254. }


  255. /* the function same as C free */
  256. int bfree(void *ptr)
  257. {
  258.         if (!ptr) return EOK;

  259.         mem_link_t *used_link = alloc_heap_ptr->used_link;
  260.         mem_link_t *free_link = alloc_heap_ptr->free_link;

  261.         while (used_link) {
  262.                 if ((ptr >= used_link->head_ptr) &&
  263.                         (ptr <= used_link->tail_ptr))
  264.                 {
  265.                         /* umount used link, so the memory block is free */
  266.                         umount_used_link(used_link);

  267.                         /* mount at free link*/
  268.                         mount_free_link(ptr, used_link->size);       

  269.                         return EOK;
  270.                 }

  271.                 used_link = used_link->next;
  272.         }

  273.         return EERROR;
  274. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2006-01-18 15:12 |只看该作者
代码很简单,思想是:预先用固定分配的buffer模拟malloc()
不同的,malloc()在系统堆空间分配内存, balloc()在用户buffer分配内存.

balloc()函数很简单,只在是free链里查找空闲的内存空间,找到了,将内存块挂在used链里.
找不到返回0,
bfree()函数,作balloc()的反操作,在used链里查找被分配过的内存,然后,将它挂回空闲链(free_link).

整个代码只是维护着两条链, free_link 及 used_link.

事实上,这段代码还是不完善,还有不少些毛病和缺陷. 在实际应用上,我已经修改过...


以下是测试文件:

test.c

  1. #include "balloc.h"

  2. char buf[1024];

  3. main()
  4. {

  5.         int i = 0;
  6.         char *pa, *pb, *pc;
  7.         if (init_alloc_heap(1024, buf) == EOK) {
  8.                 print_alloc_heap();
  9.                 puts("__________________________");

  10.                 pa = (char *)balloc(1024);
  11.                 print_alloc_heap();
  12.                 puts("___________________________");

  13.                 bfree(pa);
  14.                 pb = (char *)balloc(1000);
  15.                 pc = (char *)balloc(100);
  16.                 if (!pc) {
  17.                         printf("no enought memory\n");
  18.                 }
  19.                 print_alloc_heap();
  20.                 puts("________________________________");


  21.                 bfree(pb);
  22.                 print_alloc_heap();
  23.                 puts("__________________________________");       

  24.                 pa = (char *)balloc(100);
  25.                 pb = (char *)balloc(500);
  26.                 print_alloc_heap();
  27.                 puts("______________________________");

  28.                 bfree(pa);
  29.                 print_alloc_heap();
  30.                 puts("______________________________");

  31.                 bfree(pb);
  32.                 print_alloc_heap();
  33.                 puts("_________________________________");
  34.        
  35.         }

  36. }
复制代码



基本上能正常工作.

论坛徽章:
0
3 [报告]
发表于 2006-01-18 17:03 |只看该作者
不错,有时间研究一下,谢谢!

论坛徽章:
0
4 [报告]
发表于 2006-01-18 19:59 |只看该作者
加精啊!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP