#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()函数。