(转)零零散散学算法之浅析内存管理的方式

解析内存管理的方式

正文

       说到内存分配,我们立刻就会想到malloc()、calloc()等申请内存的接口,说到内存分配的算法,我们会想到Buddy和Slab等分配算法。那么你有没有思考过,申请的内存是如何管理的呢?管理的方式都有哪些?这就是本文将要讨论的。

       本文将介绍两种内存管理的方法:链表法和比特位法。

第零节 问题初始化


       假设现有一坨大小为M的内存,我们将它分为N块,那么每块的大小就是BLOCK_SIZE = M/N,如下图所示:

第一节 链表法


       所谓链表法内存管理,就是说将已经分好的一坨内存分成了许多连续的小块,然后将每个小块以链表的形式串起来。如下图:

       从图中可看到,我们在每个小块中添加了名为link的链表节点,它表示为:
  1. struct list_head  
  2. {  
  3.     struct list_head *next, *prev;  
  4. };  
struct list_head
{
    struct list_head *next, *prev;
};
附注:在内核中该链表为双向链表,不过在上图中为了简洁,我将其表示为单链表。

       于是,我们就可以用一个名为head的头结点将这些小块串联起来了。当我们使用时,只需从链表上摘一个即可,用完之后就可还回。利用链表来管理内存的优点有以下两点:

       1. 即用即拿,用完即还(方便快捷):就是说当我们需要在这坨申请好的内存中使用一个或者几个小块时,我们就可根据需要,从链表上摘下来一个或者几个,用完之后直接还回链表中即可。

       2. 管理流与数据流的融合与分离(节省空间):当我们利用链表法管理内存时,我们只需知道每个块的link,这样我们就能利用link来管理每个块,我们说它们是融合的;当你要使用某个块时,将其从链表中摘下来,这个时候我们就用这个块来进行数据流操作,对于link我们并不关心,在这个角度上我们说它们是分离的。不论融合与分离,我们在操作时并没有用到额外的空间,而是在每个块的内部解决了管理流与数据流。

       好了,这就是链表法内存管理。节末,我还是给出链表法的代码:
  1. /** 
  2.  *  链表法内存管理:内存初始化 
  3.  
  4.  *  addr: 表示块的起始地址 
  5.  *  block_size: 表示每个块的大小 
  6.  *  block_number: 表示块的个数 
  7.  */  
  8. void MemoryInit(void* addr, unsigned long block_size, unsigned int block_number)  
  9. {  
  10.     int i = 0;  
  11.     struct list_head *link = (struct list_head*)addr;  
  12.   
  13.     for(; i < block_number; i++)  
  14.     {  
  15.         list_add_tail(link, head);//添加到链表尾部   
  16.         addr += block_size;  
  17.         link = (struct list_head*)addr;  
  18.     }  
  19. }  
/**
 *  链表法内存管理:内存初始化

 *  addr: 表示块的起始地址
 *  block_size: 表示每个块的大小
 *  block_number: 表示块的个数
 */
void MemoryInit(void* addr, unsigned long block_size, unsigned int block_number)
{
    int	i = 0;
    struct list_head *link = (struct list_head*)addr;

    for(; i < block_number; i++)
    {
        list_add_tail(link, head);//添加到链表尾部
        addr += block_size;
        link = (struct list_head*)addr;
    }
}
  1. /** 
  2.  *  链表法内存管理:内存块分配 
  3.  */  
  4. void* alloc_blkmem(void)  
  5. {  
  6.     struct list_head *link = NULL;  
  7.     if(!list_empty(head))//链表不为空   
  8.     {  
  9.         link = head->next;  
  10.         list_del_init(link);//从链表中摘除   
  11.     }  
  12.     return link;  
  13. }  
/**
 *  链表法内存管理:内存块分配
 */
void* alloc_blkmem(void)
{
    struct list_head *link = NULL;
    if(!list_empty(head))//链表不为空
    {
        link = head->next;
        list_del_init(link);//从链表中摘除
    }
    return link;
}
  1. /** 
  2.  *  链表法内存管理:内存块释放 
  3.  * 
  4.  *  addr: 表示块的起始地址 
  5.  */  
  6. void free_blkmem(void* addr)  
  7. {  
  8.     struct list_head *link = (struct list_head*)addr;  
  9.     list_add_tail(link, head);//还回到链表中   
  10. }  
/**
 *  链表法内存管理:内存块释放
 *
 *  addr: 表示块的起始地址
 */
void free_blkmem(void* addr)
{
    struct list_head *link = (struct list_head*)addr;
    list_add_tail(link, head);//还回到链表中
}

第二节 比特位法


       和链表法相比,比特位法就更简单了。比特位的思想很简单,就是说当某个块没有被使用时,我们让该块对应位置的bit位为0,当这个块被使用时,就将它的bit位置为1。如下图:

       比特位法的确很直观,这是它的优点,但是和链表法相比,它在时间和空间上都不及链表法。我们来看看:

       在时间上:链表法是即用即拿,而比特位法则不然,它必须对bit表进行遍历,当bit位为0时方可取用;

       在空间上:链表法不需额外的空间,而比特位法则取额外的空间来存储bitmap表,有一个块就得对应一个bit位,当数据块很多时,这也是一笔不消的开销。

       虽然比特位法在时间上和空间上都不是很理想,但是它很直观,易理解。它也很常用!

       好了,比特位法就是个这,因为它很直观,所以我用很简单的几句话就说完了。节末,还是老办法,给出比特位法的代码,纵然它很简单!
  1. /** 设置bitmap的指定位 
  2.  * 
  3.  *  src: 表示bitmap 
  4.  *  index:表示指定位 
  5.  */  
  6. void bitmap_set_bit(void *src, unsigned int index)  
  7. {  
  8.     unsigned short*    data_bitmap = (unsigned short *)src;  
  9.     data_bitmap[index] |= 1 << index;  
  10. }  
/** 设置bitmap的指定位
 *
 *  src: 表示bitmap
 *  index:表示指定位
 */
void bitmap_set_bit(void *src, unsigned int index)
{
    unsigned short*    data_bitmap = (unsigned short *)src;
    data_bitmap[index] |= 1 << index;
}
  1. /** 清除bitmap的指定位 
  2.  * 
  3.  *  src: 表示bitmap 
  4.  *  index:表示指定位 
  5.  */  
  6. void bitmap_clear_bit(void *src, unsigned int index)  
  7. {  
  8.     unsigned short*    data_bitmap = (unsigned short *)src;  
  9.     data_bitmap[index]  &=  ~(1 << index);  
  10. }  
/** 清除bitmap的指定位
 *
 *  src: 表示bitmap
 *  index:表示指定位
 */
void bitmap_clear_bit(void *src, unsigned int index)
{
    unsigned short*    data_bitmap = (unsigned short *)src;
    data_bitmap[index]  &=  ~(1 << index);
}

第三节 结束语


       想想、写写、画画......

13
0
查看评论
5楼 h825503721 昨天 15:24发表 [回复] [引用] [举报]
【事件触发一致性】研究多智能体网络如何通过分布式事件驱动控制实现有限时间内的共识(Matlab代码实现)内容概要:本文围绕多智能体网络中的事件触发一致性问题,研究如何通过分布式事件驱动控制实现有限时间内的共识,并提供了相应的Matlab代码实现方案。文中探讨了事件触发机制在降低通信负担、提升系统效率方面的优势,重点分析了多智能体系统在有限时间收敛的一致性控制策略,涉及系统模型构建、触发条件设计、稳定性与收敛性分析等核心技术环节。此外,文档还展示了该技术在航空航天、电力系统、机器人协同、无人机编队等多个前沿领域的潜在应用,体现了其跨科的研究价值和工程实用性。; 适合人群:具备一定控制理论基础和Matlab编程能力的研究生、科研人员及从事自动化、智能系统、多智能体协同控制等相关领域的工程技术人员。; 使用场景及目标:①用于理解和实现多智能体系统在有限时间内达成一致的分布式控制方法;②为事件触发控制、分布式优化、协同控制等课题提供算法设计与仿真验证的技术参考;③支撑科研项目开发、术论文复现及工程原型系统搭建; 阅读建议:建议结合文中提供的Matlab代码进行实践操作,重点关注事件触发条件的设计逻辑与系统收敛性证明之间的关系,同时可延伸至其他应用场景进行二次开发与性能优化。
【四旋翼无人机】具备螺旋桨倾斜机构的全驱动四旋翼无人机:建模与控制研究(Matlab代码、Simulink仿真实现)内容概要:本文围绕具备螺旋桨倾斜机构的全驱动四旋翼无人机展开,重点研究其动力建模与控制系统设计。通过Matlab代码与Simulink仿真实现,详细阐述了该类无人机的运动与动力模型构建过程,分析了螺旋桨倾斜机构如何提升无人机的全向机动能力与姿态控制性能,并设计相应的控制策略以实现稳定飞行与精确轨迹跟踪。文中涵盖了从系统建模、控制器设计到仿真验证的完整流程,突出了全驱动结构相较于传统四旋翼在欠驱动问题上的优势。; 适合人群:具备一定控制理论基础和Matlab/Simulink使用经验的自动化、航空航天及相关专业的研究生、科研人员或无人机开发工程师。; 使用场景及目标:①习全驱动四旋翼无人机的动力建模方法;②掌握基于Matlab/Simulink的无人机控制系统设计与仿真技术;③深入理解螺旋桨倾斜机构对飞行性能的影响及其控制实现;④为相关课题研究或工程开发提供可复现的技术参考与代码支持。; 阅读建议:建议读者结合提供的Matlab代码与Simulink模型,逐步跟进文档中的建模与控制设计步骤,动手实践仿真过程,以加深对全驱动无人机控制原理的理解,并可根据实际需求对模型与控制器进行修改与优化。
在当代软件开发领域,Java与Python作为主流编程语言具有显著的技术价值。Java凭借其卓越的跨平台兼容性及严谨的面向对象体系,在商业系统构建中持续发挥核心作用;Python则依托其精炼的语法结构与高效的数据处理库,在机器习、统计建模等前沿计算领域展现独特优势。 本项目文档系统整理了针对算法训练平台的编程实践内容,重点阐释了如何运用双语言范式解决计算问题。文档体系包含以下核心组成部分: 首先,对各类算法命题进行多维度解析,涵盖基础原理推演、时间复杂度量化比较、内存占用评估等关键技术指标。针对特定问题场景,文档会提供经过优化的数据结构选型方案,并论证不同架构对执行效能的潜在影响。 其次,每个算法案例均配备完整的双语言实现版本。Java实施方案注重类型安全与企业级规范,Python版本则突出代码简洁性与函数式特性。所有示例均包含详尽的执行注释,并附有运行时性能对比数据。 特别需要说明的是,文档中的时序编号体系反映了持续更新的内容组织结构,这种编排方式便于追踪不同阶段的算法实践演进。对于初级开发者,可通过对比两种语言的实现差异深化编程思维;对于资深工程师,则能从中获取系统优化的方法论参考。 在实践应用层面,本文档揭示了理论知识与工程落地的衔接路径:Java方案演示了如何通过合理的数据架构提升分布式系统吞吐量,Python案例则展示了数值计算中算法选择对处理效率的倍增效应。这种跨语言的技术对照,为术研究与产业实践提供了可复用的设计范式。 通过系统化的算法实践,开发者能够建立完整的计算思维框架,掌握在不同业务场景下进行技术选型的决策依据,最终形成解决复杂工程问题的核心能力。 资源来源于网络分享,仅用于习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值