操作系统课设文档格式.docx
《操作系统课设文档格式.docx》由会员分享,可在线阅读,更多相关《操作系统课设文档格式.docx(63页珍藏版)》请在冰豆网上搜索。
1.3使用的开发语言、开发环境
开发语言:
C++,开发环境:
vs2010(兼容2013)
1.4解决的主要问题
我们团队在完成了算法设计和编写、进程理解和代码实现、MFC理解和掌握的基础上,完成了题目中的10个基本要求。
用户可以在图形界面的提示下,完成输入,并考虑到了用户输入错误的几种情况,给出警告提示,以便用户可以正确输入。
在用户点击确定按钮后,在另一对话框展现四种算法的页面置换过程、运行结果以及每种算法的缺页中断情况和缺页率,结果直观,并增加了数据库操作,以便查询与比较。
2基本概念和原理
2.1多道程序
多道程序设计技术是在计算机内存中同时存放几道相互独立的程序,使它们在管理程序控制下,相互穿插运行,两个或两个以上程序在计算机系统中同处于开始到结束之间的状态。
2.2进程及线程
进程是操作系统结构的基础;
是一次程序的执行;
是一个程序及其数据在处理机上顺序执行时所发生的活动。
线程是程序执行流的最小单元。
一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。
另外,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。
一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。
由于线程之间的相互制约,致使线程在运行中呈现出间断性。
线程也有就绪、阻塞和运行三种基本状态。
每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。
2.3同步与互斥
进程同步:
进程同步也是进程之间直接的制约关系,是为完成某种任务而建立的两个或多个线程,这个线程需要在某些位置上协调他们的工作次序而等待、传递信息所产生的制约关系。
进程间的直接制约关系来源于他们之间的合作。
3总体设计
3.1软件总体流程
3.2四种算法
FIFO算法
FIFO算法总是淘汰最先调入主存的页面,即淘汰在主存中驻留时间最长的页面,认为驻留时间最长的页不再使用的可能性较大。
当页面已经在内存中时,进行下一个逻辑页面的判断;
当页面不在内存中时,判断内存中是否有空闲,如果有,则将当前页面调入下一个物理块,缺页次数+1;
如果无空闲,则将最先进入的页面置换出,同时缺页次数+1,内存页面指向下一个;
然后,进行下一个逻辑页面的判断。
LRU算法
LRU算法淘汰的页面是最近一段时间内最久未被访问的那一页,它是基于程序局部性原理来考虑的,认为那些刚被使用过的页面可能还要立即被使用,而那些在较长时间内未被使用的页面可能不会立即使用。
设立一个时间记录数组,当页面已经在内存中时,将这个页面时间对应的时间记录数组的值置为0,进行下一个逻辑页面的判断;
当页面不在内存中时,判断内存中是否有空闲,如果有,则将当前页面调入下一个物理块,同时,将这个页面时间对应的时间记录数组的值置为0;
如果无空闲,通过比较时间记录数组的大小,时间记录值越小,说明使用时间越接近于当前,找出时间记录值最大的(即最久未使用的页面),将该页面页面置换出,同时将这个页面时间对应的时间记录数组的值置为0,缺页次数+1,内存页面指向下一个;
LFU算法
LFU算法即最不经常使用页置换算法,要求在页置换时换引用计数最小的页,因为经常使用的页应该有一个较大的引用次数。
设立一个时间记录数组和使用次数记录数组,当页面已经在内存中时,将这个页面时间对应的时间记录数组的值置为0,并将该页面对应的次数记录数组+1,进行下一个逻辑页面的判断;
当页面不在内存中时,把此页面的次数记录数组+1,判断内存中是否有空闲,如果有,则将当前页面调入下一个物理块,同时,将这个页面时间对应的时间记录数组的值置为0,并将该页面对应的次数记录数组+1;
如果无空闲,通过比较次数记录数组的大小找出次数记录值最小的对应的页面,将该页面页面置换出,如果存在次数记录值相同的情况,则比较时间记录数组的大小,把进入页面最久的置换出,同时将这个页面时间对应的时间记录数组的值置为0,缺页次数+1,内存页面指向下一个;
OPT算法
OPT算法即页面最优置换算法,要求在页面置换时,选择那些永不使用的,或者是在最长时间内不再被访问的页面。
该算法的基本思想是:
发生缺页时,有些页面在内存中,其中有一页将很快被访问(也包含紧接着的下一条指令的那页),而其他页面则可能要到10、100或者1000条指令后才会被访问,每个页面都可以用在该页面首次被访问前所要执行的指令数进行标记,标记最大的页应该被置换。
如果无空闲,外后看,如果物理块中的数有等于后面页面值的,置物理块中页面的相对时间差为逻辑页面在序列中的位置,如果物理块中的数不等于后面页面值,则置页面的相对时间差为999(即一个很大的值),比较页面的相对时间差,时间差越大说明将来使用情况越靠后,置换出时间差最大的页面,同时缺页次数+1,内存页面指向下一个;
4详细设计
4.1数据输入对话框设计及表述
(一)设计过程:
以课设要求为依据,完成FIFO、LRU、LFU、OPT等四种页面置换算法同时对同一逻辑序列进行排序,并且达到可以设置参数,同时显示结果,暂停和恢复线程,保存数据等功能。
首先是对话框设计,截图如下:
图4.1主界面
图4.2参数设置对话框
(二)构件说明:
在对话框中用到的控件主要有按钮控件,编辑框控件,列表框控件,单选框,静态文本框,组控件,菜单等。
(三)对象:
①参数设置中编辑框以及调用变量
DDX_Control(pDX,IDC_EDIT1,LogicPageNumMax);
//逻辑页面最大值编辑框
DDX_Control(pDX,IDC_EDIT2,LogicPageNum);
//逻辑页面数
DDX_Control(pDX,IDC_EDIT3,MemPageNum);
//内存页面个数
DDX_Control(pDX,IDC_EDIT4,AccessTime);
//内存存取时间
DDX_Control(pDX,IDC_EDIT5,TLB_time);
//快表查询时间
DDX_Control(pDX,IDC_EDIT6,Intertime);
//缺页中断时间
DDX_Control(pDX,IDC_EDIT7,Seq);
//逻辑页面访问序列
②参数设置中单选框以及调用变量
ON_BN_CLICKED(IDC_RADIO1,&
CXX:
:
OnBnClickedRadio1)//有无快表中‘有’
ON_BN_CLICKED(IDC_RADIO2,&
OnBnClickedRadio2)//有无快表中‘无’
ON_BN_CLICKED(IDC_RADIO3,&
OnBnClickedRadio3)//序列是否随机中‘是’
ON_BN_CLICKED(IDC_RADIO4,&
OnBnClickedRadio4)//序列是否随机中‘否’
③参数设置中按钮以及调用变量
ON_BN_CLICKED(IDC_BUTTON2,&
OnBnClickedButton1)//确定按钮
④PageReplace中菜单以及调用变量
ON_COMMAND(ID_32771,&
CPageReplaceDlg:
On32771)//弹出参数设置对话框
ON_COMMAND(ID_32776,&
On32776)//开始按钮
ON_COMMAND(ID_32777,&
On32777)//暂停按钮
ON_COMMAND(ID_32778,&
On32778)//继续按钮
ON_COMMAND(ID_32779,&
On32779)//终止按钮
ON_COMMAND(ID_32780,&
On32780)//退出对话框
⑤PageReplace中按钮以及调用变量
ON_BN_CLICKED(IDC_BUTTON1,&
OnBnClickedButton1)//FIFO暂停
ON_BN_CLICKED(IDC_BUTTON6,&
OnBnClickedButton6)//FIFO继续
ON_BN_CLICKED(IDC_BUTTON3,&
OnBnClickedButton3)//LRU暂停
ON_BN_CLICKED(IDC_BUTTON7,&
OnBnClickedButton7)//LRU继续
ON_BN_CLICKED(IDC_BUTTON8,&
OnBnClickedButton8)//LFU暂停
ON_BN_CLICKED(IDC_BUTTON4,&
OnBnClickedButton4)//LFU继续
ON_BN_CLICKED(IDC_BUTTON9,&
OnBnClickedButton9)//OPT暂停
ON_BN_CLICKED(IDC_BUTTON5,&
OnBnClickedButton5)//OPT继续
OnBnClickedButton2)//清空
ON_BN_CLICKED(IDC_BUTTON10,&
OnBnClickedButton10)//保存
4.2算法流程图
图4.3FIFO算法流程图
图4.4LRU算法流程图
图4.5LFU算法流程图
图4.6OPT算法流程图
4.3线程操作及描述
1.创建线程
_beginthreadex(
void*security,
unsignedstack_size,
unsigned(__stdcall*start_address)(void*),
void*arglist,
unsignedinitflag,
unsigned*thrdaddr)
参数:
Security:
安全属性,NULL为默认安全属性。
stack_size:
指定线程堆栈的大小。
如果为0,则线程堆栈大小和创建它的线程的堆栈大小相同。
一般用0。
start_address:
指定线程函数的地址,也就是线程调用执行的函数地址(用函数名称即可,函数名称就表示地址)。
Arglist:
传递给线程的参数的指针,可以通过传入对象的指针,在线程函数中再转化为对应类的指针。
Initflag:
线程初始状态。
0:
立即运行;
CREATE_SUSPEND:
线程初始状态为挂起状态。
Thrdaddr:
用于记录线程标识符的地址,为NULL时便是不使用此参数。
返回值:
如果创建线程成功,函数返回创建线程的句柄;
当发生错误时,函数返回0。
2.获取当前线程ID
函数:
GetCurrentThreadId()
无
一个32位有符号整数,它是当前线程的标识符。
3.挂起线程
DWORDSuspendThread(HANDLEhThread
)
hThread:
线程的句柄
DWORD类型,如果函数执行成功,返回值为此线程之前的挂起计数,如果函数执行失败,返回值为0xFFFFFFFF
4.恢复线程
DWORDResumeThread(HANDLEhThread)
·
hThread:
DWORD类型,如果函数执行成功,返回值为此线程之前的挂起计数;
如果函数执行失败,返回值为0xFFFFFFFF
5.强制退出线程
BOOLWINAPITerminateThread(_Inout_
HANDLEhThread,_In_
DWORDdwExitCode)
dwExitCode:
线程的退出码
函数执行成功,返回非零值;
函数执行失败,返回0
4.4连接数据库
4.4.1系统配置
1.设置SQLSERVER服务器为SQL登录方式,并且系统安全性中的sa用户要设置登录功能为“启用”,还有必须要有密码。
2.需要在ODBC中进行数据源配置,数据源选\”SQLSERVER”,登录方式使用“使用输入用户登录ID和密码的SQLSERVER验证”,并填写登录名(sa)和密码,注意一点,密码不能为空,这就意味着你的sa用户必须得有密码。
否则无法通过系统本身的安全策略。
测试通过就完成了配置。
4.4.2C++与SQL连接初始化
1.在所建立的C++项目中的stdafx.h头文件中引入ADO
具体代码如下:
#import“c:
\ProgramFiles\CommonFiles\System\ado\msado15.dll”
no_namespacerename(”EOF”,“adoEOF”)rename(”BOF”,“adoBOF”)
2.定义_ConnectionPtr变量后调用Connection对象的Open方法建立与服务器的连接。
数据类型_ConnectionPtr实际上是由类模板_com_ptr_t得到的一个具体的实例类。
_ConnectionPtr类封装了Connection对象的Idispatch接口指针及其一些必要的操作。
可以通过这个指针操纵Connection对象。
4.4.3简单的数据连接
连接SQLServer数据库,代码如下:
//ADO方式连接数据库
TESTHR(pConnection.CreateInstance(__uuidof(Connection)));
//设置连接数据库
pConnection->
ConnectionString="
Provider=SQLOLEDB.1;
IntegratedSecurity=SSPI;
PersistSecurityInfo=False;
UserID=sa;
InitialCatalog=Grades;
DataSource=PC-20130129LQVX"
;
//设置连接超时时间
ConnectionTimeout=10;
Open("
"
"
adModeUnknown);
printf("
Connectionstate:
%s\n"
(LPCSTR)GetState(pConnection->
State));
4.4.4执行SQL语句
//具体执行的SQL语句
CStringstrSql=”select*fromtb_condition”;
//将查询数据导入pRecordset数据容器
pRecordset=pConnection->
Execute(_bstr_t(strSql),NULL,adCmdText);
至此,SQL语句已经执行完成。
pRecordset内的数据是执行的结果,取得记录:
while(!
pRecordset->
adoEOF)//遍历并读取name列的记录并输出
{
CStringtemp=(TCHAR*)(_bstr_t)pRecordset->
GetFields()->
GetItem(”name”)->
Value;
AfxMessageBox(temp);
MoveNext();
}
插入记录
//首先要初始化指针再执行以下操作
CStringstrsql;
strsql.Format(”insertintotb_goods(no,name,price)
values(’%d’,'
%s’,%d)”,m_intNo,m_strName,m_intPrice);
//执行上面的SQL语句
Execute(_bstr_t(strsql),NULL,adCmdText);
修改记录
strsql.Format(”updatetb_goodssetname=’%s’,price=%dwhereno=%d“,m_strName,m_intPrice,m_intNo);
删除记录
strsql.Format(”deletefromtb_goodswhereno=‘%d’“,m_intNo);
5技术细节
5.1输入量类型转换
在MFC中我们用GetWindowTextW得到的编辑框中的变量为Cstring型,但是在算法中,我们需要以整型变量的形式对其进行逻辑运算和数学运算以及值的传递,查询网络及MSDN,我们用到了_ttoi用于Cstring型到int型的转换。
实现代码如下:
MemPageNum.GetWindowTextW(bSize);
//内存页面数
LogicPageNum.GetWindowTextW(pSize);
LogicPageNumMax.GetWindowTextW(PageSize);
//逻辑页面最大值
AccessTime.GetWindowTextW(memorytime);
Intertime.GetWindowTextW(breaktime);
//缺页中断时间
intbbsize=_ttoi(bSize);
//以下进行类型转换
intppsize=_ttoi(pSize);
intppagesize=_ttoi(PageSize);
intmmemorytime=_ttoi(memorytime);
intbbreaktime=_ttoi(breaktime);
5.2获取逻辑页面序列数组
基本要求中第3点提到能够使用户随机输入存取的逻辑页面的页号序,但是用户输入的序列是以空格作为页号之间的间隔的,我们需要滤去这些空格,而把页号存放在数组page中供四种算法的调用,通过查询MSDN,我们用到了Tokenize函数,借助Tokenize(_T("
"
),curPos)滤去空格,完成数组page的存储。
inti=0;
CStringlist;
Seq.GetWindowTextW(list);
CStringresToken;
intcurPos=0;
resToken=list.Tokenize(_T("
),curPos);
while(resToken!
=_T("
))
MessageBox(resToken);
intrresToken=_ttoi(resToken);
page[i]=rresToken;
i++;
resToken=list.Tokenize(_T("
};
5.3获取随机序列
基本要求中第4点提到能够随机产生存取的逻辑页面的页号序列,我们对此的设计为先判断逻辑页面产生序列是否随机,当用户按下“是”单选框后,在逻辑页面的页号序列编辑框中自动显示随机产生的序列,并以空格作页号之间的间隔。
在这个细节的设计上,我们的考虑是根据用户输入的逻辑页面页号的范围,在此范围内产生随机数,并根据用户输入的逻辑页面数pSize,产生pSize个随机数并存放在数组page中,最后把数组中的数外加空格连接起来组成字符串list。
其中,我们发现当使用rand函数时,当PageSize和pSize固定时,产生的随机序列也是固定的,这是因为rand函数产生的是伪随机数,为了避免这种情况,我们用到了srand函数,以当前时间作为随机种子,产生随机数。
voidCXX:
OnBnClickedRadio3()
{
//TODO:
在此添加控件通知处理程序代码
ppsize=_ttoi(pSize);
ppagesize=_ttoi(PageSize);
list="
CStrings;
srand((int)time(0));
for(inti=0;
i<
ppsize;
i++)
{
page[i]=rand()%ppagesize+1;
s.Format(_T("
%d"
),page[i]);
li