⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pagemanagedlg.cpp

📁 模拟操作系统的内存页式模拟
💻 CPP
字号:
// PageManageDlg.cpp : implementation file
//

#include "stdafx.h"
#include "PageManage.h"
#include "PageManageDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPageManageDlg dialog

CPageManageDlg::CPageManageDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CPageManageDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CPageManageDlg)
	m_pcbname = _T("");
	m_memoryNum = 0;
	m_pageRun = 0;
	m_memTotle = 0;
	m_memUsed = 0;
	m_memFree = 0;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CPageManageDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPageManageDlg)
	DDX_Control(pDX, IDC_LIST_MEMORY, m_memory);
	DDX_Control(pDX, IDC_LIST_READY, m_readylist);
	DDX_Control(pDX, IDC_LIST_PAGE, m_pagelist);
	DDX_Control(pDX, IDC_LIST_EXEC, m_execlist);
	DDX_Control(pDX, IDC_LIST_BLOCK, m_blocklist);
	DDX_Text(pDX, IDC_EDIT_NAME, m_pcbname);
	DDX_Text(pDX, IDC_EDIT_MEMORYNUM, m_memoryNum);
	DDX_Text(pDX, IDC_EDIT_RUN, m_pageRun);
	DDX_Text(pDX, IDC_EDIT_MEMTOTLE, m_memTotle);
	DDX_Text(pDX, IDC_EDIT_MEMUSED, m_memUsed);
	DDX_Text(pDX, IDC_EDIT_MEMFREE, m_memFree);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CPageManageDlg, CDialog)
	//{{AFX_MSG_MAP(CPageManageDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_BUILD, OnButtonBuild)
	ON_WM_TIMER()
	ON_BN_CLICKED(IDC_BUTTON_TURN, OnButtonTurn)
	ON_BN_CLICKED(IDC_BUTTON_BLOCK, OnButtonBlock)
	ON_BN_CLICKED(IDC_BUTTON_WAKEUP, OnButtonWakeup)
	ON_BN_CLICKED(IDC_BUTTON_END, OnButtonEnd)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPageManageDlg message handlers

BOOL CPageManageDlg::OnInitDialog()
{
	CDialog::OnInitDialog();
	m_memTotle = 50;
	m_memUsed = 0;
	m_memFree = 50;
	UpdateData(false);
	plink = new CProcessLink;
	pcbID = 0;
	//初始化各个ControlBox
	m_readylist.InsertColumn(0,"就绪队列",LVCFMT_LEFT,500);
	m_blocklist.InsertColumn(0,"阻塞队列",LVCFMT_LEFT,500);
	m_execlist.InsertColumn(0,"执行队列",LVCFMT_LEFT,500);
	m_pagelist.InsertColumn(0,"页号",LVCFMT_LEFT,133);
	m_pagelist.InsertColumn(1,"块号",LVCFMT_LEFT,133);
	m_pagelist.InsertColumn(2,"未使用时间",LVCFMT_LEFT,133);
	m_memory.InsertColumn(0,"物理块号",LVCFMT_LEFT,250);
	m_memory.InsertColumn(1,"状态",LVCFMT_LEFT,250);
	
	for(int i = 0;i<=49;i++)
	{
		memPhy[i].MemoryID = i;
		memPhy[i].state = false;
	}

	//设置时钟
	SetTimer(1,1000,NULL);

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);
	
	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CPageManageDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CPageManageDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CPageManageDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CPageManageDlg::OnButtonBuild() 
{
	// TODO: Add your control notification handler code here
	this->UpdateData(true);
	int needPage = (int)(m_memoryNum/3)+1;;		//1/3物理块
	if(m_pcbname == "")
	{
		MessageBox("请输入进程名!");
		return;
	}
	if(m_memoryNum <1 || m_memoryNum >147)
	{
		MessageBox("请输入一个1~147之间的一个数!");
		return;
	}
	if(m_memFree < needPage)		//小于最少要求
	{
		MessageBox("内存空间不够,未被创建阻塞!");
		return;
	}
	struct PCB *pcbNew = new struct PCB;
	struct PageTable *page = new struct PageTable;
	struct PageTable *p,*q;
	p = page;
	//初始化页表
	page->MemoryID = -1;
	page->PageID = 0;
	page->pNext = NULL;
	page->time = 0;
	for(int i = 1;i<m_memoryNum;i++)
	{
		q = new struct PageTable;
		q->MemoryID = -1;
		q->PageID = i;
		q->pNext = NULL;
		q->time = 0;
		p->pNext = q;
		p = p->pNext;
		q = NULL;
	}

	//初始化进程控制块
	pcbNew->pcbName = m_pcbname;
	pcbNew->pcbID = pcbID++;
	pcbNew->page = page;
	pcbNew->pagetotle = m_memoryNum;
	pcbNew->pageMin = needPage;
	pcbNew->lastPage = 0;
	pcbNew->pNext = NULL;
	p = page;
	int nextj = 0;
	for(i = 0;i<needPage;i++)
	{
		int j;
		for(j = nextj;j<=49;j++)
		{
			if(memPhy[j].state == false)
			{
				nextj = j;
				memPhy[j].state = true;
				goto L1;
			}
		}
L1:		p->MemoryID = nextj;
		p = p->pNext;
	}
	m_memFree = m_memFree-needPage;
	m_memUsed = m_memUsed + needPage;
//	UpdateData(false);
	if((plink->AddtoReady(pcbNew)) == TRUE)
	{
		SetTimer(2,10000,NULL);
		DisplayExec();
		DisplayPageTable();
	}
	else
		DisplayReady();
//	SetTimer(1,1000,NULL);
	DisplayMemory();
	UpdateData(false);
}




void CPageManageDlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	int nowPage;		//将要运行的页
//	int pagerun;
	struct PCB *p = plink->GetExec();;
	struct PageTable *t;
	switch(nIDEvent)
	{
	case 1:
		if(p != NULL)
		{
			for(t = p->page;t!=NULL;t=t->pNext)
			{
				if(t->MemoryID != -1 && t->PageID != p->lastPage)
				{
					t->time ++;
				}
			}
		}
	//	UpdateData(false);
		DisplayPageTable();
		break;
	case 2:
		nowPage = rand()%(plink->GetExec()->pagetotle);
		m_pageRun = nowPage;
		p->lastPage = nowPage;
		t = plink->GetExec()->page;
		for(int i = 0;i < nowPage;i++)
		{
			t = t->pNext;
		}
		if(t->MemoryID != -1)
		{
			t->time = 0;
		}
		else
		{
			AssignPage(nowPage);
			DisplayPageTable();		//这句可以不用
		}
		UpdateData(false);
		break;
	}
	CDialog::OnTimer(nIDEvent);
}


//请求分页
void CPageManageDlg::AssignPage(int now)
{
	struct PCB *p = plink->GetExec();
	int longestTime = 0;		//最久未被使用的页的时间
	int longestNum;			//最久未被使用的页的索引
	int lastMem;			//被取消的页所对应的物理块号,用于讲要执行的页的物理块号
	struct PageTable *t = p->page;
	for(int i = 0;i<p->pagetotle;i++)
	{
		if(t->MemoryID != -1 && (t->time)>longestTime)
		{
			longestTime = t->time;
			longestNum = i;
		}
		t = t->pNext;
	}
	//取消该页的分配,重新分配给其他页
	t = plink->GetExec()->page;
	for (i = 0;i<longestNum;i++)
	{
		t = t->pNext;
	}
	lastMem = t->MemoryID;
	t->MemoryID = -1;
	t->time = 0;
	//将该物理块分配给将要执行的页
	t = plink->GetExec()->page;
	for (i = 0;i<now;i++)
	{
		t = t->pNext;
	}
	t->MemoryID = lastMem;
}


//显示执行状态的进程信息
void CPageManageDlg::DisplayExec()
{
	m_execlist.DeleteAllItems();
	if(plink->GetExec() == NULL)
		return;
	struct PCB *pcb = plink->GetExec();
	CString str,str_ID;
	str_ID.Format(",ID号是%d",pcb->pcbID);
	str = pcb->pcbName + str_ID + pcb->state;
	m_execlist.InsertItem(0,"");
	m_execlist.SetItemText(0,0,str);
}


//显示执行进程的页表
void CPageManageDlg::DisplayPageTable()
{
	if(plink->GetExec() == NULL)
		return;
	struct PageTable *page = plink->GetExec()->page;
	int pageItem = 0;
//	struct PageTable *p = page;
	CString str_MemID,str_PageID,str_Time;
	m_pagelist.DeleteAllItems();
	for(;page != NULL;page = page->pNext )
	{
		m_pagelist.InsertItem(pageItem,"");
		str_PageID.Format("%d",page->PageID);
		m_pagelist.SetItemText(pageItem,0,str_PageID);
		str_MemID.Format("%d",page->MemoryID);
		m_pagelist.SetItemText(pageItem,1,str_MemID);
		str_Time.Format("%d",page->time);
		m_pagelist.SetItemText(pageItem++,2,str_Time);
	}
}


//手工实现时间片轮询
void CPageManageDlg::OnButtonTurn() 
{
	// TODO: Add your control notification handler code here
	if(plink->GetExec() == NULL)
	{
		MessageBox("没有进程处于执行状态!");
		return;
	}
	if(plink->GetReadyHead() == NULL)
	{
		MessageBox("就绪队列中没有进程,无需轮询!");
		return;
	}
	
	plink->ProcessRun();
	m_pageRun = plink->GetExec()->lastPage;
	DisplayExec();
	DisplayReady();
	UpdateData(false);
}

void CPageManageDlg::DisplayReady()
{
	m_readylist.DeleteAllItems();
	int readyItem = 0;		//记录当前进程所在行
	struct PCB *pcb = plink->GetReadyHead();
	CString str,str_ID;
	for(;pcb != NULL;pcb = pcb->pNext)
	{
		str_ID.Format(",ID号是%d",pcb->pcbID);
		str = pcb->pcbName + str_ID + pcb->state;
		m_readylist.InsertItem(readyItem,"");
		m_readylist.SetItemText(readyItem++,0,str);
	}
}

void CPageManageDlg::DisplayBlock()
{
	m_blocklist.DeleteAllItems();
	int blockItem = 0;
	struct PCB *pcb = plink->GetOtherBlockHead();
	CString str,str_ID;	
	for(;pcb != NULL;pcb = pcb->pNext)
	{
		str_ID.Format(",ID号是%d",pcb->pcbID);
		str = pcb->pcbName + str_ID + pcb->state;
		m_blocklist.InsertItem(blockItem,"");
		m_blocklist.SetItemText(blockItem++,0,str);
	}
}

void CPageManageDlg::OnButtonBlock() 
{
	// TODO: Add your control notification handler code here
	if(plink->GetExec() == NULL)
	{
		MessageBox("没有进程处于执行状态,不能执行阻塞过程!");
		return;
	}
	KillTimer(2);
	if(plink->Block_Other() == TRUE)
	{
		SetTimer(2,10000,NULL);
		DisplayReady();
	}
//	SetTimer(2,10000,NULL);
	DisplayBlock();
	DisplayExec();
//	DisplayPageTable();
}


void CPageManageDlg::OnButtonWakeup() 
{
	// TODO: Add your control notification handler code here
	if(plink->GetOtherBlockHead() == NULL)
	{
		MessageBox("阻塞队列为空,无进程可以被唤醒!");
		return;
	}
	POSITION pos = m_blocklist.GetFirstSelectedItemPosition();
	int cur = m_blocklist.GetNextSelectedItem(pos);
	if(plink->WakeUp(cur) == TRUE)
	{
		DisplayBlock();
		DisplayExec();
		DisplayReady();
		DisplayPageTable();
	}
	else
	{
		DisplayBlock();
		DisplayReady();
	}
}

void CPageManageDlg::OnButtonEnd() 
{
	// TODO: Add your control notification handler code here
	struct PageTable *page = plink->GetExec()->page;
	if(plink->GetExec() == NULL)
	{
		MessageBox("没有进程处于执行状态,不能执行该操作!");
		return;
	}
//	KillTimer(2);
	for(;page != NULL;page = page->pNext)
	{
		if(page->MemoryID != -1)
		{
			memPhy[page->MemoryID].state = false;
		}
	}
	plink->End();
	DisplayExec();
	DisplayReady();
	DisplayMemory();
}

void CPageManageDlg::DisplayMemory()
{
	m_memory.DeleteAllItems();
	int memItem = 0;
	CString str_ID,str_state;
	for(int i = 0;i<=49;i++)
	{
		m_memory.InsertItem(memItem,"");
		str_ID.Format("%d",memPhy[i].MemoryID);
		m_memory.SetItemText(memItem,0,str_ID);
		if(memPhy[i].state == false)
			str_state = "未被分配";
		else
			str_state = "已被分配";
		m_memory.SetItemText(memItem++,1,str_state);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -