操作系统的完整代码——内存管理代码ycmm.cpp

本文深入解析ycmm内存管理模块的源代码,探讨其malloc(), realloc()和free()函数的实现细节。ycmm模块通过复杂的链表操作,高效地管理物理内存,支持不同场景下的内存分配与回收。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#define YCORG -1          //该设置使编译器生成头部为YCEXE结构的可执行文件
#include "ycio.cpp"
#define PgTail(pLink) (((unsigned)pLink + pLink->size + PAGE_SIZE-1) & PAGE_MASK)

ycmmCLASS YCMM;
YMEM *phyHead,*maxHead;

void main(void **pObj)
{
    phyHead = *(YMEM**)(KERNEL_POS + DATA_POS + 8);   //可用内存链表头
    maxHead = *(YMEM**)(KERNEL_POS + DATA_POS + 12);  //可用内存链表最大地址
    *pObj = &YCMM;
}

YMEM *ycmmCLASS::malloc(YMEM *pHead,unsigned int _Size,int isHigh)
{
    YMEM *pLink;
    unsigned int memPos;
    int alloc_size = sizeof(YMEM) + (_Size + 15) & ~15;  //实际要分配的内存大小
    int alignSize = (alloc_size + PAGE_SIZE - 1) & PAGE_MASK;//要分配的内存页长度

    if(isHigh)                 //驱动程序申请高端内存, 其线性地址 > KERNEL_POS
      {
        pLink = phyHead;       //可用内存链表头
        while(pLink)           //查看是否还有不小于alignSize的可用内存
          {
            pLink = pLink->pLast;                      //从物理内存尾部开始搜索
            if(pLink->size >= alignSize)  break;       //搜到pLink项满足所需内存
            if(pLink == phyHead)  return nullptr; //没有可分配的内存,返回空指针
          }
        memPos = pLink->addr + pLink->size - alignSize + KERNEL_POS;//分配的内存
      }
    else                    //用户程序进程申请低端内存, 其线性地址 < KERNEL_POS
      {
        if(alloc_size < PAGE_SIZE)     //处理小内存, 即所需内存小于一个物理页框
          {
            pLink = pHead;             //进程内存链表头
            while(pLink)
              {
                memPos = (unsigned int)pLink + pLink->size;
                int taiPos = PgTail(pLink);                 //所占内存页尾部位置
                if(taiPos - memPos >= alloc_size) //尾页所剩内存不小于所需内存时
                  {
                    YMEM *qLink = pLink->pNext;
                    while(qLink)                 //检查尾页所剩内存是否被分配掉
                      {
                        if(taiPos==PgTail(qLink) && qLink > pLink)  break;
                        qLink = qLink->pNext;
                        if(qLink == pLink)  goto  ma_p_end; //尾页所剩内存可用
                      }
                  }
                pLink = pLink->pNext;        //检查下一项
                if(pLink == pHead)  break;   //pLink回到头部, 退出循环
              }
          }

        pLink = phyHead;       //可用内存链表头
        while(pLink)           //查看是否有不小于alloc_size的可用内存
          {
            if(pLink->size >= alloc_size)  break;
            pLink = pLink->pNext;
            if(pLink == phyHead)  return nullptr; //没有可分配的内存,返回空指针
          }

        memPos = pLink->addr;   //分配到的内存地址
        pLink->addr = memPos + alignSize;
      }

    pLink->size -= alignSize;  //调整可用内存链表项的内存大小
    if(!pLink->size)  delete_a_phy_link(pLink); //若链表项内存大小为0, 则删除

    ma_p_end:
    pLink = (YMEM*)memPos;
    pLink->size = alloc_size;
    pLink->flag = 0;
    return pLink;
}

void ycmmCLASS::free(YMEM *pLink)
{
    pLink->flag = 1;
    unsigned int memPos = (unsigned int)pLink;
    if(memPos >= KERNEL_POS)  memPos -= KERNEL_POS;
    int pg_num = (pLink->size + PAGE_SIZE - 1) / PAGE_SIZE;

    unsigned int endPos = PgTail(pLink);
    YMEM *qLink = pLink->pNext;
    if(memPos % PAGE_SIZE)
      {
        while(qLink)  //处理小内存
          {
            if(endPos == PgTail(qLink) && !qLink->flag)  return;  //有在用内存
            qLink = qLink->pNext;
            if(qLink == pLink)   break;
          }
        memPos &= PAGE_MASK;    //被释放内存地址进行页对齐
      }
    else
      {
        while(qLink)
          {
            if(endPos == PgTail(qLink) && !qLink->flag)
              {
                pg_num--;     //尾页所剩内存在用, 不释放尾页
                break;
              }
            qLink = qLink->pNext;
            if(qLink == pLink)  break;
          }
      }
    add_to_phy_link(memPos, pg_num * PAGE_SIZE);  //被释放内存加到可用内存链表
}

YMEM *ycmmCLASS::realloc(YMEM *oldLink,unsigned int _NewSize)
{
    YMEM *pLink;
    unsigned int memPos = (unsigned int)oldLink;

    if((memPos % PAGE_SIZE) == 0)  //检查是否能在旧分配内存的尾部调整
      {
        int alloc_size = sizeof(YMEM) + (_NewSize + 15) & ~15;
        unsigned int endPos = PgTail(oldLink);         //旧内存尾部页框对齐位置
        unsigned int newPos = ((unsigned)oldLink + alloc_size + PAGE_SIZE - 1)
                                          & PAGE_MASK; //新内存尾部页框对齐位置

        if(newPos <= endPos)  //新内存小于旧内存直接去掉后部
          {
            oldLink->size = alloc_size;
            if(newPos < endPos)   add_to_phy_link(newPos, endPos - newPos);
            return oldLink;
          }

        pLink = phyHead;
        while(pLink)
          {
            if(pLink->addr == endPos)       //新内存大于旧内存时,
              {                             //检查其后是否有足够大的可用内存
                if(pLink->size >= newPos - endPos)
                  {
                    pLink->size -= newPos - endPos;
                    pLink->addr += newPos - endPos;
                    if(!pLink->size)  delete_a_phy_link(pLink); //删除链表项
                    oldLink->size = alloc_size; //有足够大可用内存,直接加到后部
                    return oldLink;
                  }
                break;
              }
            pLink = pLink->pNext;
            if(pLink == phyHead)   break;
          }
      }

    //重新分配所需大小的内存, 并把旧内存内容拷贝到新内存
    pLink = YCMM.malloc(oldLink,_NewSize);
    if(pLink)   memcpy(to_memPtr(pLink), to_memPtr(oldLink), oldLink->size);
    return pLink;
}

YMEM *merge_phy_link(unsigned int memPos,unsigned int msize)
{
    unsigned int endPos = memPos + msize;
    YMEM *pLink = phyHead;
    while(pLink)
      {
        if(pLink->addr == endPos)  //链表项pLink与内存memPos右边相邻,合并
          {
            pLink->addr = memPos;
            pLink->size += msize;
            return pLink;
          }
        if(pLink->addr + pLink->size == memPos)  //链表项与memPos左边相邻,合并
          {
            pLink->size += msize;
            return pLink;
          }
        pLink = pLink->pNext;
        if(pLink == phyHead)  break;
      }
    return nullptr;
}

void add_to_phy_link(unsigned int memPos,unsigned int msize)
{
    YMEM *pLink = merge_phy_link(memPos,msize);
    if(!pLink)  //没有可与内存memPos合并的链表项, 则增加一项
      {
        for(pLink=(YMEM*)freeMemLINK_POS; pLink<maxHead; pLink++)
                                                       if(!pLink->pNext) break;
        if(pLink >= maxHead)
          {
            pLink = maxHead++;
            if(maxHead >= (YMEM*)freeMemLink_NUM) {  }
          }
        pLink->addr = memPos;
        pLink->size = msize;
        yc_add_link(pLink,phyHead);
        return;
      }

    while(1)
      {
        YMEM *qLink = pLink;
        pLink = merge_phy_link(pLink->addr,pLink->size);
        if(!pLink)  break;
        delete_a_phy_link(qLink);   //删除被合并的链表项
      }
}

void delete_a_phy_link(YMEM *pLink)
{
    yc_delete_link(pLink,phyHead);
    pLink->pNext = nullptr;
}

YMEM *ycmmCLASS::get_head()
{
    return phyHead;
}

                      C/C++代码文件: ycmm.cpp

    ycmm.cpp只是简单实现malloc(),realloc()和free()函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值