所谓“随机+顺序”的内存块分配方式就是用随机数来确定一个起始探测的开始块号,如果其已经被分配,则向下一块探测,如果还是已经分配,则继续下探,直到找到可用块,如果已经到内存的尾部则回到操作系统分界处继续下探。
操作系统采用固定可用块数的方式给每个进程使用和分配内存块,并且规定最大内存块数为x,当某个进程已经用完了它的最大内存块数后就要淘汰页面了。
模拟计算机系统允许最大并发进程数为y,假设目前进程数已经达到最大进程数。
为了模拟某个进程,其所需的页面数z由随机数产生(m/10,页面推进的过程采用随机数方式给出访存地址a,逻辑地址a应该在0到zKB-1之间,操作系统负责对逻辑地址a进行地址变换,并维护整个系统内存管理的所有数据结构,保证进程的顺利推进,使内存得以共享,实现虚拟存储器的功能。
要求课设实现的系统能够配置上述参数,并按照配置参数的规模来系统的模拟系统的运行过程。
希望可以可视化的展示系统内部的变化。
课设的方案
1构造页面、进程、内存管理所需的数据结构,动态管理系统中的有关信息。
#defineMAX_MEMORY_FRAME_COUNT200//最大允许设置的内存大小<以块为单位)
classCPage:
publicCObject//逻辑页的信息
{
DECLARE_DYNCREATE(CPage>
public:
CPage(>。
boolbInMemoryFlag。
//该页是否在内存
intnFrameNo。
//内存的快号
intnDiskRelBlockNo。
//磁盘的相对块号<可以随机给定)
intnNextPageNo。
//下一调进内存页的页号
boolbModifiedFlag。
//修改位<可以随机给定)
//...
}。
classCProcess:
publicCObject//进程的信息
{
DECLARE_DYNCREATE(CProcess>
public:
CProcess(>。
voidInitProcessParameter(intno,intpagetotal,intruntime>。
intGetOneLogicalAddress(>。
//得到下一要访问的页的页号
voidAddressMapping(intLogicalAddress>。
intnPID。
//进程标识符
charszProcessName[20]。
//进程名
intnControlNo。
intnStatus。
intnPageCountLogicalSpace。
//逻辑地址空间的页数
intnPageCountInMemory。
//调入内存的页数
intnRunTime。
//运行时间<运行步数)
intnPageNoHead。
//调入内存的首页
intnPageNoTail。
//调入内存的末页
//其他信息,如就绪或阻塞队列指针----自己可以根据自己的能力与爱好进一步完善下去
CPage*PageTable。
}。
intMaxFrameCount。
intGetOneRandDiskNo(>//随机产生一个虚页在磁盘的相对块号
{
returnrand(>%(1024*1024>。
}
CPage:
:
CPage(>
{
bInMemoryFlag=0。
//该页是否在内存
nFrameNo=0。
//内存的快号
nDiskRelBlockNo=GetOneRandDiskNo(>。
//磁盘的相对块号<可以随机给定)
nNextPageNo=0。
//下一调进内存页的页号
bModifiedFlag=0。
//修改位<可以随机给定)
}
IMPLEMENT_DYNCREATE(CPage,CObject>
CProcess:
:
CProcess(>
{
nPID=(int>this。
nPageCountInMemory=0。
nStatus=0。
nPageNoHead=0。
nPageNoTail=0。
PageTable=NULL。
}
voidCProcess:
:
InitProcessParameter(intno,intpagetotal,intruntime>
{
sprintf(szProcessName,"ProcName%1d",no>。
//进程名
nControlNo=no。
nPageCountLogicalSpace=pagetotal。
//逻辑地址空间的页数
nRunTime=runtime。
//运行时间<运行步数)
PageTable=newCPage[nPageCountLogicalSpace]。
//根据实际需要创建页表
}
intCProcess:
:
GetOneLogicalAddress(>//得到下一要访问的页的页号
{
intran_num。
ran_num=rand(>%nPageCountLogicalSpace。
returnran_num。
}
voidCProcess:
:
AddressMapping(intLogicalAddress>
{
intnIndexIn=LogicalAddress。
//正在访问到的页的页号
intnIndexOut。
intnFrameNoReused。
//
if(PageTable[nIndexIn].bInMemoryFlag==0>//未装入内存
{
if(nPageCountInMemory//本进程使用的内存块数未达最大块数
{
PageTable[nIndexIn].nFrameNo=COsExamDlg:
:
AllocateMemoryFrame(nControlNo>。
//请求分配一块
PageTable[nIndexIn].bInMemoryFlag=true。
//维护链表
if(nPageCountInMemory==0>//第一个页面装入内存
{
PageTable[nIndexIn].nNextPageNo=-1。
this->nPageNoHead=nIndexIn。
this->nPageNoTail=nIndexIn。
}
else
{
PageTable[nIndexIn].nNextPageNo=-1。
//刚装入的页面的Next指针设为-1<终点)
PageTable[this->nPageNoTail].nNextPageNo=nIndexIn。
this->nPageNoTail=nIndexIn。
}
nPageCountInMemory++。
}
else//本进程使用的内存块数已达最大块数
{
//淘汰一页
nIndexOut=this->nPageNoHead。
nFrameNoReused=PageTable[nIndexOut].nFrameNo。
//暂存被重用的内存块的块号
this->nPageNoHead=PageTable[nIndexOut].nNextPageNo。
//把首页设到原来的第二个顺序页
PageTable[nIndexOut].nFrameNo=-1。
//原来的页设成不在内存
PageTable[nIndexOut].bInMemoryFlag=false。
PageTable[nIndexIn].nFrameNo=nFrameNoReused。
//访问页装入腾出的块
PageTable[nIndexIn].bInMemoryFlag=true。
//设为“已装入”
PageTable[nIndexIn].nNextPageNo=-1。
//刚访问的页面的Next指针设为-1<终点)
PageTable[this->nPageNoTail].nNextPageNo=nIndexIn。
//附加到链表
this->nPageNoTail=nIndexIn。
//设置为新的“链尾”
//
}
//设置内存映像的显示串
//。
。
。
。
。
。
}
else//访问地址对应的页已在内存
{
//直接访问
}
}
2设计使用上述数据结构来实现请求分页模拟系统
下面的例子是用VC的对话框应用程序来实现的测试或应用系统模型。
进程的推进由windows的线程来模拟的,这里进程的内容是由随机数产生运行轨迹。
intCOsExamDlg:
:
m_sMemoryFrameCount=120。
intCOsExamDlg:
:
m_sOsFrameCount=40。
boolbMemoryBitmap[MAX_MEMORY_FRAME_COUNT]。
//内存空间管理的位示图
CStringcsMemoryBitmap。
//用于显示内存使用情况的字符串
intGetOneLogicalAddress(>
{
return0。
}
UINTBarryProcessThreadProc(LPVOIDpParam>//模拟进程的线程函数
{
CProcess*pProcess=(CProcess*>pParam。
if(pProcess==NULL||!
pProcess->IsKindOf(RUNTIME_CLASS(CProcess>>>
return1。
//如果pObject无效,则返回1
//添加执行代码
CStringcsOutputInfo=""。
inti。
intLA。
for(i=0。
inRunTime。
i++>//执行每个操作步
{
//随机产生一个访问地址
LA=GetOneLogicalAddress(>。
//地址变换--改变数据结构,改变用户界面
pProcess->AddressMapping(LA>。
csOutputInfo+="M"。
//构造显示页表信息的串
CWnd*pMainWnd。
pMainWnd=AfxGetMainWnd(>。
switch(pProcess->nControlNo>
{
case0:
pMainWnd->GetDlgItem(IDC_STATIC_PROCESS0>->SetWindowText(csOutputInfo>。
break。
case1:
pMainWnd->GetDlgItem(IDC_STATIC_PROCESS1>->SetWindowText(csOutputInfo>。
break。
case2:
pMainWnd->GetDlgItem(IDC_STATIC_PROCESS2>->SetWindowText(csOutputInfo>。
break。
case3:
pMainWnd->GetDlgItem(IDC_STATIC_PROCESS3>->SetWindowText(csOutputInfo>。
break。
}
//延时
Sleep(1000>。
}
return0。
//threadcompletedsuccessfully!
}
CProcess*ProcessPool。
voidCOsExamDlg:
:
OsInitialization(>
{
inti。
csMemoryBitmap=""。
for(i=0。
ii++>
{
bMemoryBitmap[i]=false。
csMemoryBitmap+=""。
}
}
intCOsExamDlg:
:
AllocateMemoryFrame(intnProcessNo>
{
intnFrameNoStart。
nFrameNoStart=m_sOsFrameCount+rand(>%(m_sMemoryFrameCount-m_sOsFrameCount>。
while(bMemoryBitmap[nFrameNoStart]==true>
{
nFrameNoStart=nFrameNoStart+1。
if(nFrameNoStart==m_sMemoryFrameCount>
nFrameNoStart=m_sOsFrameCount。
}
returnnFrameNoStart。
}
COsExamDlg:
:
COsExamDlg(CWnd*pParent/*=NULL*/>
:
CDialog(COsExamDlg:
:
IDD,pParent>
{
//{{AFX_DATA_INIT(COsExamDlg>
m_nProcessCount=0。
m_nMemoryFrameCount=0。
m_nOsFrameCount=0。
m_nMaxFrameForOneProcess=0。
//}}AFX_DATA_INIT
//NotethatLoadIcondoesnotrequireasubsequentDestroyIconinWin32
m_hIcon=AfxGetApp(>->LoadIcon(IDR_MAINFRAME>。
m_nProcessCount=3。
m_nMaxFrameForOneProcess=16。
m_nMemoryFrameCount=64。
m_nOsFrameCount=16。
}
voidCOsExamDlg:
:
DoDataExchange(CDataExchange*pDX>
{
CDialog:
:
DoDataExchange(pDX>。
//{{AFX_DATA_MAP(COsExamDlg>
DDX_Text(pDX,IDC_EDIT_PROCESS_COUNT,m_nProcessCount>。
DDX_Text(pDX,IDC_EDIT_MEMORY_FRAME_COUNT,m_nMemoryFrameCount>。
DDV_MinMaxInt(pDX,m_nMemoryFrameCount,64,128>。
DDX_Text(pDX,IDC_EDIT_OS_FRAME_COUNT,m_nOsFrameCount>。
DDV_MinMaxInt(pDX,m_nOsFrameCount,16,32>。
DDX_Text(pDX,IDC_EDIT_MAX_FRAME_COUNT_PER_PROCESS,m_nMaxFrameForOneProcess>。
DDV_MinMaxInt(pDX,m_nMaxFrameForOneProcess,4,16>。
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(COsExamDlg,CDialog>
//{{AFX_MSG_MAP(COsExamDlg>
ON_WM_SYSCOMMAND(>
ON_WM_PAINT(>
ON_WM_QUERYDRAGICON(>
ON_BN_CLICKED(IDC_BUTTON_ACCEPT,OnButtonAccept>
ON_BN_CLICKED(IDC_BUTTON_SIMU,OnButtonSimu>
//}}AFX_MSG_MAP
END_MESSAGE_MAP(>
/////////////////////////////////////////////////////////////////////////////
//COsExamDlgmessagehandlers
BOOLCOsExamDlg:
:
OnInitDialog(>
{
CDialog:
:
OnInitDialog(>。
//Add"About..."menuitemtosystemmenu.
//IDM_ABOUTBOXmustbeinthesystemcommandrange.
ASSERT((IDM_ABOUTBOX&0xFFF0>==IDM_ABOUTBOX>。
ASSERT(IDM_ABOUTBOX<0xF000>。
CMenu*pSysMenu=GetSystemMenu(FALSE>。
if(pSysMenu!
=NULL>
{
CStringstrAboutMenu。
strAboutMenu.LoadString(IDS_ABOUTBOX>。
if(!
strAboutMenu.IsEmpty(>>
{
pSysMenu->AppendMenu(MF_SEPARATOR>。
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu>。
}
}
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE>。
//Setbigicon
SetIcon(m_hIcon,FALSE>。
//Setsmallicon
//TODO:
Addextrainitializationhere
GetDlgItem(IDC_EDIT_PAGE_COUNT0>->SetWindowText("12">。
GetDlgItem(IDC_EDIT_PAGE_COUNT0>->SetWindowText("12">。
GetDlgItem(IDC_EDIT_RUN_TIME0>->SetWindowText("12">。
GetDlgItem(IDC_EDIT_PAGE_COUNT1>->SetWindowText("8">。
GetDlgItem(IDC_EDIT_RUN_TIME1>->SetWindowText("12">。
GetDlgItem(IDC_EDIT_PAGE_COUNT2>->SetWindowText("16">。
GetDlgItem(IDC_EDIT_RUN_TIME2>->SetWindowText("12">。
GetDlgItem(IDC_EDIT_PAGE_COUNT3>->SetWindowText("9">。
GetDlgItem(IDC_EDIT_RUN_TIME3>->SetWindowText("12">。
srand(time(0>>。
returnTRUE。
//returnTRUEunlessyousetthefocustoacontrol
}
voidCOsExamDlg:
:
OnSysCommand(UINTnID,LPARAMlParam>
{
if((nID&0xFFF0>==IDM_ABOUTBOX>
{
CAboutDlgdlgAbout。
dlgAbout.DoModal(>。
}
else
{
CDialog:
:
OnSysCommand(nID,lParam>。
}
}
//Ifyouaddaminimizebuttontoyourdialog,youwillneedthecodebelow
//todrawtheicon.ForMFCapplicationsusingthedocument/viewmodel,
//thisisautomaticallydoneforyoubytheframework.
voidCOsExamDlg:
:
OnPaint(>
{
if(IsIconic(>>
{
CPaintDCdc(this>。
//devicecontextforpainting
SendMessage(WM_ICONERASEBKGND,(WPARAM>dc.GetSafeHdc(>,0>。
//Centericoninclientrectangle
intcxIcon=GetSystemMetrics(SM_CXICON>。
intcyIcon=GetSystemMetrics(SM_CYICON>。
CRectrect。
GetClientRect(&rect>。
intx=(rect.Width(>-cxIcon+1>/2。
inty=(rect.Height(>-cyIcon+1>/2。
//Drawtheicon
dc.DrawIcon(x,y,m_hIcon>。
}
else
{
CDialog:
:
OnPaint(>。
}
}