`
totoxian
  • 浏览: 1095704 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

一个基于链表的内存管理方案

 
阅读更多

在OpenVPN中,一种很不错的内存管理方案是基于链表的,该方案的实现使用了一个gc_arena结构体,该结构体的作用就是将所有的动态分配的内存块收集汇集起来,然后就可以在一个地方统一释放,c语言对动态内存管理的劣势就是无法跟踪动态内存,因此也就将管理动态内存的事情交给了程序员来完成,然后就有了无数次的由于内存泄露导致的bug,虽然c++实现了很多内存管理方案,比如智能指针之类的,但是其复杂性无不揉进了c++这种重量级语言本身,使得本已复杂的语言带上特定的库之后更加臃肿,并且在c++中实现的动态内存管理无非就是使用了构造函数,析构函数之类的,规范相当地复杂,如果有人觉得不复杂,那么他要么是一个初学c++的人,要么是一个学了c但是没有学好的人。
如果将这个话题展开谈,动态内存管理其实并不是很复杂,其唯一的技术难题就是跟踪动态内存的分配,而不是具体的释放时机,一旦所有的动态分配被成功跟踪了,那么释放时机就是程序员的事情了,以前程序员由于跟踪不了动态内存分配而导致内存泄露,那实在不是程序员的错,毕竟程序越来越大越不可控,而每个人也不一定都是高手,但是如果你时刻都能得到当前分配了哪些内存,但是还是泄露,那就是你个人问题了,所以说,只要做到动态内存分配的汇总即可。OpenVPN的内存管理方案就是巧妙地将动态分配的内存组织成了链表,然后在“合适”的时机来统一释放,这个释放不是释放某一个内存块,而是释放被收集的所有的内存块。首先看一下这个机制的基础设施:
struct gc_entry { //gc机制的单向链表
struct gc_entry *next;
};
struct gc_arena {//最重要的外层结构体,gc机制构建于之上
struct gc_entry *list;
};
static inline struct gc_arena gc_new (void)
{ //分配一个gc,注意是inline,否则返回栈上的缓冲区是错误的
struct gc_arena ret;
ret.list = NULL; //初始化
return ret;
}
static inline void gc_free (struct gc_arena *a)
{ //链表的释放,释放掉链表上所有的动态内存区域
if (a->list)
x_gc_free (a);
}
void x_gc_free (struct gc_arena *a)
{ //具体的释放动作
struct gc_entry *e;
e = a->list;
a->list = NULL;
while (e != NULL) { //遍历链表的元素,逐个释放之
struct gc_entry *next = e->next;
free (e);
e = next;
}
}
void *gc_malloc (size_t size, bool clear, struct gc_arena *a)
{ //重要的分配函数
void *ret;
if (a) {
struct gc_entry *e; //注意下面分配的空间大小要加上gc_entry的大小,gc_entry负责管理
e = (struct gc_entry *) malloc (size + sizeof (struct gc_entry));
check_malloc_return (e);
ret = (char *) e + sizeof (struct gc_entry); //只把除去管理数据的内存返回给调用者
e->next = a->list; //将该块内存链接入链表
a->list = e;
}
...
if (clear) //分配一块清0内存
memset (ret, 0, size);
return ret;
}
以上代码很清晰,下面则是使用上述机制的一个例子:
int mmalloc(struct gc_arena *gc)
{//如果下面的换成malloc(1000)的话,则瞬间就完蛋了。
char *buf = (char *)gc_malloc (1000, 1, gc);
}
int main(int argc, char **argv)
{
struct gc_arena gc = gc_new();
gc.list = NULL;
int i = 0, j = 0;
while (1) {
i++;
while (j++ < 10) {
mmalloc(&gc);
}
j = 0;
gc_free(&gc);
}

}
何谓“合适”的时机,到底在什么时候释放呢?这实际上是个问题,答案就是需要你自己掌握,也就是说你必须知道什么时候那些分配的缓冲区没有用了,这个gc机制所做的仅仅是帮你搜集到所有的缓冲区,而不是负责帮你决定释放的时机,如果你理解linux kernel的计数器机制的话,那么一定会为这种内存管理机制叹为观止,不过说实话,即使是计数器机制也是需要程序员自己把握什么时候调用free,而在free中递减计数器,计数器机制为你做的只是控制计数器为当前正在使用该内存的路径数量,具体何时该释放还是需要程序员自己控制,实际上不要贪图任何毫无代价的自动内存管理机制,也没有那样的机制,目前实现的需要付出代价的内存管理机制主要有两种,一种是c++牺牲了简单性原则实现的利用诸如构造函数/析构函数之类的机制,它实质上是利用一些c++的固定标准来实现的,另一种则是牺牲了性能和可控性的垃圾收集机制,java使用该种方式,java虚拟机需要维护一个对象引用图,定期触发垃圾收集而将游离的图节点内存回收。可见唯一不需要付出系统代价的就是c的实现了,可是却需要程序员在写代码时付出代价,不管怎样,就简单就是美的原则来讲我宁可使用C的方法也不喜欢c++或者java那种看似简单实则臃肿的方式

分享到:
评论

相关推荐

    基于多链表结构的嵌入式系统内存管理

    ### 基于多链表结构的嵌入式系统内存管理 #### 摘要与研究背景 ...综上所述,基于多链表结构的动态内存管理方法为嵌入式系统提供了一个灵活高效的内存管理解决方案,对于推动嵌入式技术的发展具有重要意义。

    c语言基于链表的学生成绩管理系统

    综上所述,本系统通过链表的灵活运用,提供了一个全面的学生成绩管理解决方案。它不仅包括了基础的增删改查功能,还涉及到了数据排序、文件操作等高级应用。这一系统可以作为学习C语言和数据结构管理的综合性实验...

    C语言程序的设计_基于链表的学生成绩管理系统方案.doc

    在C语言程序设计中,构建一个基于链表的学生成绩管理系统是一个典型的实践项目,它涵盖了数据结构、文件操作和用户交互等多个方面的重要知识。以下是对这个系统设计中涉及的关键点的详细解释: 1. **链表的理解与...

    C语言程序设计实训 基于链表的学生信息管理系统

    总之,"基于链表的学生信息管理系统"是一个综合性的实践项目,涵盖了C语言和C++的基础知识,通过这个项目,开发者不仅能深入理解链表和文件操作,还能提升程序设计能力,为今后的软件开发打下坚实基础。

    基于链表的城市数据库系统

    总之,基于链表的城市数据库系统利用了链表的数据结构优势,为城市数据的存储和管理提供了一种灵活且高效的解决方案。通过深入理解链表的工作原理和实现这些基本操作,我们可以构建出一个功能齐全且易于扩展的系统。...

    基于链表的列车站点信息系统数据结构课设

    在本项目"基于链表的列车站点信息系统数据结构课设"中,我们主要探讨的是如何利用C++编程语言实现一个高效、灵活的数据结构——链表,来管理列车站点信息。链表是一种重要的数据结构,它在内存中并不连续存放元素,...

    堆内存管理在linux上的实现原理

    简单的堆管理解决方案是使用一个链表来管理堆内存区域。在这个链表中,每个节点代表一个分区,包括分区的大小和状态。当进程请求分配内存时,堆管理器会遍历链表,找到合适的分区,并将其分配给进程。 GNU malloc ...

    基于链表的两个非递减有序序列的合并.docx

    ### 基于链表的两个非递减有序序列的合并 #### 问题背景与目标 本篇文章讨论的问题是:给定两个递增的整数序列A和B,利用链表来表示这两个序列,并实现一个算法,将这两个序列合并成一个新的递增有序序列C。在合并...

    内核双向链表航班管理系统(嵌入式项目)

    总之,"内核双向链表航班管理系统"是一个综合性的嵌入式项目,涵盖了数据结构、操作系统原理、软件工程、安全性等多个IT领域的知识点。通过学习和实践这个项目,开发者可以提升在嵌入式系统开发、数据管理以及系统...

    C语言链表课程设计——仓库管理系统.rar

    在本项目中,"C语言链表课程设计——仓库管理系统.rar"是一个基于C语言实现的仓库管理系统的源代码压缩包。这个系统利用了链表数据结构来存储和管理仓库中的物品信息,包括入库、出库、查询等操作。链表是计算机科学...

    链表-使用Python基于链表实现栈数据结构.zip

    与数组不同,链表的元素不需要在内存中连续存储,每个元素(节点)包含数据以及指向下一个元素的引用。这使得链表在动态插入和删除操作上具有较高的效率。 在Python中,链表通常通过定义一个类来实现,该类包含节点...

    职工信息管理系统-链表实现.zip

    本项目“职工信息管理系统-链表实现.zip”便是一个采用C语言编写的实例,通过链表数据结构来实现对职工信息的录入、删除、查询、修改以及统计等功能,同时也具备文件的读写能力,确保数据的安全性和持久性。...

    实时系统内存管理方案的设计与实现1

    本课题旨在探讨并设计一个高效、可靠的内存管理系统,以适应实时操作系统的严格需求。 首先,实时内存管理系统是实时操作系统的重要组成部分,它负责内存的分配、释放以及对内存对象的引用。内存管理的目标是优化...

    行业-18 基于冷热数据分离方案优化后的LRU链表,是如何解决之前的问题的.rar

    LRU(Least Recently Used)链表是一种常用的缓存淘汰策略,它通过维护一个有序的数据结构,将最近最少使用的数据优先淘汰。在很多IT系统中,如数据库、内存管理系统等,LRU链表被广泛用于存储和管理有限的内存资源...

    1-7.2 基于工作集冷内存回收方案1

    工作集(Working Set)基于的内存回收方案是操作系统管理内存的一种策略,特别是在Linux内核中,它被用来优化内存的使用效率,确保系统的稳定性和响应性。工作集主要关注的是在一段时间内被频繁访问的数据页集合,...

    双向链表双向链表双向链表

    与单链表相比,双向链表的主要特点是每个节点不仅包含指向下一个节点的指针,还包含一个指向前一个节点的指针。这种设计使得双向链表在数据操作上具有更高的灵活性,比如可以方便地进行前向和后向遍历。 在双向链表...

    18 基于冷热数据分离方案优化后的LRU链表,是如何解决之前的问题的.pdf

    优化后的LRU链表将冷数据和热数据分开放置,通常通过两个链表分别管理,一个用于冷数据,另一个用于热数据。 具体来说,预读机制和全表扫描加载进来的缓存页,会首先被放置在冷数据区域的前端。这样做的原因在于,...

    约瑟夫环 C++ 链表

    链表是一种线性数据结构,它不依赖于内存的连续性,每个元素称为节点,包含数据和指向下一个节点的指针。对于约瑟夫环问题,我们可以创建一个单链表,每个节点代表一个人,节点的值表示人的编号。我们需要实现链表的...

Global site tag (gtag.js) - Google Analytics