功能:为内核部件提供简单的内存管理接口,主要是管理动态表数组。
公共函数:
-获取空闲项 Result Table::GetFreeItem(u32 *Index);
功能:遍历页指针数组,直到遇到空指针,然后遍历页表里的表项,搜索空闲项,用Index指针返回。
返回值:成功返回 S_OK;失败返回 E_NOITEM 。
-添加新项 Result Table::AddNewItem(u32 Index,point *Item);
功能:把第Index项的 使用位 置为1。Item指针返回新项的地址。
返回值:成功返回 S_OK;失败返回 E_USED 。
-获取项指针 Result Table::GetItem(u32 Index,point *Item);
功能:获取第Index项的指针。相应页未分配时,分配新页。
返回值:成功返回 S_OK; Index超过表最大值时返回 E_MAX ,或无法申请新表时返回 E_NOFREE。
-释放项 Result Table::FreeItem(u32 Index);
功能:把Index项的 使用位 置为0。
返回值:成功时返回 S_OK。
地址映射图:
这个类库结合了数组和链表的优势,既能按下标访问项,又能动态分配内存,只是内存碎片较多,最好用于相对稳定的表,而内存管理相关部件则可尽量多使用此类库,然后再为上层提供接口。
代码(尚未测试,不稳定,请有兴趣的高手帮忙测试下)在我的代码里可以看到。
/*===============================================================
* Table.h
* 表类 定义
*作用:帮助内核部件管理动态表数组,例如:进程表,句柄表等。
*公共方法:
-获取空闲项
-添加新项
-获取项指针
-释放项
===============================================================*/
#include "KernelMsg.h"
#include "Type.h"
#include "Kernel.h"
#include "Setbit.h"
#define PageSize 4096 // 页大小
#define MaxPage 64 // 最多占用的页大小
#define UseBit 7 // 用来表示项是否使用的位
//--------------------------表类定义-----------------------------
class Table
{
public:
Table(u32 ItemSize,u32 ItemMax); // -初始化
Result GetFreeItem(u32 *Index); // -获取空闲项
Result AddNewItem(u32 Index,point *Item); // -添加新项
Result GetItem(u32 Index,point *Item); // -获取项指针
Result FreeItem(u32 Index); // -释放项
private:
u32 item_size; // 项大小
u32 item_max; // 项数最大值
point page_point[MaxPage]; // 储存页表指针的数组
private:
Result AllocPage(point *Item); // 申请一个新的页
};
/*===============================================================
* Table.cc
* 表类 实现
*作用:帮助内核部件管理动态表数组,例如:进程表,句柄表等。
*公共方法:
-获取空闲项
-添加新项
-获取项指针
-释放项
===============================================================*/
#include "Table.h"
/************************************************************************/
/* 初始化 */
/************************************************************************/
Table::Table(u32 ItemSize,u32 ItemMax)
{
int i=0;
this->item_max = ItemMax;
// 清理指针
for(i=0;i<MaxPage;i++)
page_point[i] = '\0';
// 项大小对其为2的幂
for(i=2;i<PageSize;i *=2)
{
if (ItemSize < i)
{
ItemSize = i;
break;
}
}
this->item_size = ItemSize;
return;
}
/************************************************************************/
/* 获取空闲项 */
/************************************************************************/
Result Table::GetFreeItem(u32 *Index)
{
point tmp;
for (int i=0;i<item_max;i++)
{
if (GetItem(i,&tmp) != S_OK) return E_MAX;
if (!(BitTest((u8*)tmp,UseBit)))
{
*Index = i;
return S_OK;
}
}
return E_NOITEM;
}
/************************************************************************/
/* 添加新项 */
/************************************************************************/
Result Table::AddNewItem(u32 Index,point *Item)
{
point tmp;
if (GetItem(Index,&tmp) != S_OK) return E_MAX;
if (!(BitTest((u8*)tmp,UseBit)))
{
BitSet((u8*)tmp,UseBit);
*Item = tmp;
return S_OK;
}
return E_USED;
}
/************************************************************************/
/* 获取项指针 */
/************************************************************************/
Result Table::GetItem(u32 Index,point *Item)
{
// 如果要获取的项大于最大
if (Index >= item_max)
{
return E_MAX;
}
int realaddr = Index * item_size; // 计算绝对地址
int page = realaddr/PageSize; // 计算页号
// 计算是否需要申请新页
if (page > MaxPage) return E_MAX;
if (page_point[page] == '\0')
{
if (AllocPage(&page_point[page]) != S_OK) return E_NOFREE;
}
// 计算偏移
*Item = (((u8*)page_point[page]) + (realaddr % PageSize)); // 返回地址
return S_OK;
}
/************************************************************************/
/* 释放项 */
/************************************************************************/
Result Table::FreeItem(u32 Index)
{
point tmp;
if (GetItem(Index,&tmp) != S_OK) return E_MAX;
BitClear((u8*)tmp,UseBit);
return S_OK;
}
/************************************************************************/
/* 申请新页 */
/************************************************************************/
#ifdef _DEBUG
// 调试模式
Result Table::AllocPage(point *Item)
{
u8 *tmp = new u8[PageSize];
*Item = (point*)tmp;
return S_OK;
}
#else
// 内核模式
Result Table::AllocPage(point *Item)
{
struct message msg;
msg.msg = MSG_SYSCALL_ALLOCPAGE;
msg.param = Item;
memory.SendMessage(msg);
return S_OK;
}
#endif // _DEBUG