实 验 目 录
一、 实验目的与要求:
1、熟悉操作系统的基本概念和基本结构;
2、通过观察系统中进程的创建、运行和终止的程序设计和调试操作,进一步熟悉操作系统中进程的特点;
3、加深掌握程序在Visual C++6.0环境下的编译、调试和运行。
二、 实验内容:
通过在Visual C++6.0环境下编写程序,完成对进程的创建、运行和终止过程的实现。通过实验进一步理解进程的基本概念和进程的三个基本状态。熟悉操作系统中是如何对进程进行控制的。
三、 实验器材:
微机+windows操作系统+VC++6.0
四、 实验步骤:
1、创建进程
//创建子进程
# include <windows.h>
# include <iostream>
# include <stdio.h>
void StartClone(int nCloneID)
{
TCHAR szFilename[MAX_PATH] ;
:: GetModuleFileName(NULL, szFilename, MAX_PATH) ;
TCHAR szCmdLine[MAX_PATH] ;
:: sprintf(szCmdLine, “\”%s\” %d”, szFilename, nCloneID) ;
STARTUPINFO si;
:: ZeroMemory(reinterpret_cast <void*> (&si) , sizeof(si) ) ;
si.cb = sizeof(si) ;
PROCESS_INFORMATION pi;
BOOL bCreateOK = :: CreateProcess(
szFilename,
szCmdLine,
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi) ;
if (bCreateOK)
{ :: CloseHandle(pi.hProcess) ;
:: CloseHandle(pi.hThread) ;
}}
int main(int argc, char* argv[] )
{
int nClone(0) ;
if (argc > 1)
{ :: sscanf(argv[1] , “%d” , &nClone) ;}
std :: cout << “Process ID: “ << :: GetCurrentProcessId()
<< “, Clone ID: “ << nClone
<< std :: endl;
const int c_nCloneMax = 25;
if (nClone < c_nCloneMax)
{
StartClone(++nClone) ;
}
:: Sleep(500) ;
return 0;
}
2、正在运行的进程
使用进程和操作系统的版本信息
// version项目
# include <windows.h>
# include <iostream>
void main()
{
DWORD dwIdThis = :: GetCurrentProcessId() ;
DWORD dwVerReq = :: GetProcessVersion(dwIdThis) ;
WORD wMajorReq =( (WORD) dwVerReq > 16) ;
WORD wMinorReq = ((WORD) dwVerReq & 0xffff) ;
std :: cout << “Process ID: “ << dwIdThis
<< “, requires OS: “ << wMajorReq << wMinorReq << std :: endl ;
OSVERSIONINFOEX osvix;
:: ZeroMemory(&osvix, sizeof(osvix) ) ;
osvix.dwOSVersionInfoSize = sizeof(osvix) ;
:: GetVersionEx(reinterpret_cast < LPOSVERSIONINFO > (&osvix) ) ;
std :: cout << “Running on OS: “ << osvix.dwMajorVersion << “.”
<< osvix.dwMinorVersion << std :: endl;
if (osvix.dwPlatformId == VER_PLATFORM_WIN32_NT &&
osvix.dwMajorVersion >= 5)
{
:: SetPriorityClass(
:: GetCurrentProcess() ,
HIGH_PRIORITY_CLASS) ;
std :: cout << “Task Manager should now now indicate this”
“process is high priority.” << std :: endl;
}
}
3、终止进程:
指令其子进程来“杀掉”自己的父进程
// procterm项目
# include <windows.h>
# include <iostream>
# include <stdio.h>
static LPCTSTR g_szMutexName = “w2kdg.ProcTerm.mutex.Suicide” ;
void StartClone()
{
TCHAR szFilename [MAX_PATH] ;
:: GetModuleFileName(NULL, szFilename, MAX_PATH) ;
TCHAR szCmdLine[MAX_PATH] ;
:: sprintf(szCmdLine, “\” %s\“ child” , szFilename) ;
STARTUPINFO si;
:: ZeroMemory(reinterpret_cast < void* > (&si) , sizeof(si) ) ;
si.cb = sizeof(si) ;
PROCESS_INFORMATION pi;
BOOL bCreateOK = :: CreateProcess(
szFilename,
szCmdLine,
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi ) ;
if (bCreateOK)
{ :: CloseHandle(pi.hProcess) ;
:: CloseHandle(pi.hThread) ;}
}
void Parent()
{ HANDLE hMutexSuicide = :: CreateMutex(
NULL,
TRUE,
g_szMutexName) ;
if (hMutexSuicide != NULL)
{
std :: cout << “Creating the child process.” << std :: endl;
:: StartClone() ;
:: Sleep(5000) ;
std :: cout << “Telling the child process to quit. ” << std :: endl;
:: ReleaseMutex(hMutexSuicide) ;
:: CloseHandle(hMutexSuicide) ;}
}
void Child()
{// 打开“自杀”互斥体
HANDLE hMutexSuicide = :: OpenMutex(
SYNCHRONIZE,
FALSE,
g_szMutexName) ;
if (hMutexSuicide != NULL)
{
std :: cout << “Child waiting for suicide instructions. ” << std :: endl;
:: WaitForSingleObject(hMutexSuicide, INFINITE) ;
std :: cout << “Child quiting. ” << std :: endl;
:: CloseHandle(hMutexSuicide) ;
}}
int main(int argc, char* argv[] )
{
if (argc >1&& :: strcmp(argv[1] , “child” ) == 0)
{ Child() ; }
else
{Parent() ;}
return 0;
}
五、实验结果:
1、程序1展示的是一个简单的使用CreateProcess() API函数的例子。首先形成简单的命令行,提供当前的EXE文件的指定文件名和代表生成克隆进程的号码。大多数参数都可取缺省值,但是创建标志参数使用了: CREATE_NEW_CONSOLE 标志,指示新进程分配它自己的控制台,这使得运行示例程序时,在任务栏上产生许多活动标记。然后该克隆进程的创建方法关闭传递过来的句柄并返回main() 函数。在关闭程序之前,每一进程的执行主线程暂停一下,以便让用户看到其中的至少一个窗口。
2、实验结果窗口为:
![]() |
结果分析:
当前PID信息:_______1492______________________________________________
当前操作系统版本:___Running on OS:5.1_________________________________
系统提示信息:Task Manager should now indiate this process is high priority.
程序向读者表明了如何获得当前的PID和所需的进程版本信息。为了运行这一程序,系统处理了所有的版本不兼容问题。
接着,程序演示了如何使用GetVersionEx() API函数来提取OSVERSIONINFOEX结构。这一数据块中包括了操作系统的版本信息。其中,“OS : 5.0”表示当前运行的操作系统是:
____Windows2000_当前版本为_OS:5.0________________________________
最后一段程序利用了操作系统的版本信息,以确认运行的是Windows 2000。代码接着将当前进程的优先级提高到比正常级别高。
3、程序3结果分析:
程序实现了一个进程从“生”到“死”的整个一生。第一次执行时,它创建一个子进程,其行为如同“父亲”。在创建子进程之前,先创建一个互斥的内核对象,其行为对于子进程来说,如同一个“自杀弹”。当创建子进程时,就打开了互斥体并在其他线程中进行别的处理工作,同时等待着父进程使用ReleaseMutex() API发出“死亡”信号。然后用Sleep() API调用来模拟父进程处理其他工作,等完成时,指令子进程终止。
在正常的终止操作中,进程的每个工作线程都要终止,由主线程调用ExitProcess()。接着,管理层对进程增加的所有对象释放引用,并将用 GetExitCodeProcess() 建立的退出代码从STILL_ACTIVE改变为在ExitProcess() 调用中返回的值。最后,主线程对象也如同进程对象一样转变为受信状态。
等到所有打开的句柄都关闭之后,管理层的对象管理器才销毁进程对象本身。还没有一种函数可取得终止后的进程对象为其参数,从而使其“复活”。当进程对象引用一个终止了的对象时,有好几个API函数仍然是有用的。进程可使用退出代码将终止方式通知给调用GetExitCodeProcess() 的其他进程。同时,GetProcessTimes() API函数可向主调者显示进程的终止时间。
六、实验小结:
一、 实验目的与要求:
二、 实验内容:
编写程序,用C语言来实现对N个进程采用动态优先权算法的进程调度。每个进程使用进程pcb结构来描述。优先数改变原则:进程在就绪队列中多呆一个时间片,优先数增加1;进程每运行一个时间片,优先数减3。
三、 实验器材:
微机+windows操作系统+VC++6.0
四、 实验步骤:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include "define.h"
using namespace std;
PCB READY_QUEUE; // 就绪队列
PCB BLOCK_QUEUE; // 阻塞队列
bool compare_priority(const PCB& p1, const PCB& p2)
{
return p1.PRIORITY > p2.PRIORITY;
}
bool compare_id(const PCB& p1, const PCB& p2)
{
return p1.ID < p2.ID;
}
// inital PCB data
PCB produces[5]=
{
{0,9,0,3,2,3,READY,NULL},
{1,38,0,3,-1,0,READY,NULL},
{2,30,0,6,-1,0,READY,NULL},
{3,29,0,3,-1,0,READY,NULL},
{4,0,0,4,-1,0,READY,NULL}
};
// inital queue( ready queue , block queue );
void inital_queue()
{
READY_QUEUE.NEXT = NULL;
BLOCK_QUEUE.NEXT = NULL;
PCB * r = &READY_QUEUE;
PCB * b = &BLOCK_QUEUE;
// sort order by PRIORITY (DEC)
sort(produces, &produces[4], compare_priority);
for(int i=0; i<5; i++)
{
if(produces[i].ALLTIME == 0)
{
produces[i].STATE = FINISH;
continue;
}
if(produces[i].STATE == BLOCK && produces[i].BLOCKTIME == 0)
{// block -> ready
r->NEXT = &produces[i];
produces[i].STATE = READY;
r = r->NEXT;
}
else if(produces[i].STATE == BLOCK && produces[i].BLOCKTIME != 0)
{// block -> blcok
b->NEXT = &produces[i];
produces[i].STATE = BLOCK;
b = b->NEXT;
}
else if(produces[i].STATE == READY && produces[i].STARTBLOCK == 0)
{// ready -> block
b->NEXT = &produces[i];
produces[i].STATE = BLOCK;
b = b->NEXT;
}
else if(produces[i].STATE == READY && produces[i].STARTBLOCK != 0)
{// ready -> ready
r->NEXT = &produces[i];
produces[i].STATE = READY;
r = r->NEXT;
}
}
}
void run()
{
PCB * r = READY_QUEUE.NEXT; // r point to the ready queue first pcb
PCB * b = BLOCK_QUEUE.NEXT; // b point to the block queue first pcb
PCB * running_pcb = r;
r = r->NEXT;
cout<<"--------------正在执行的进程--------------" << endl;
cout << "running produce's ID = " << running_pcb->ID << endl;
// update data
running_pcb->ALLTIME--;
running_pcb->CPUTIME++;
running_pcb->PRIORITY -= 3;
running_pcb->STARTBLOCK--;
while(r)
{
r->PRIORITY++;
r = r->NEXT;
}
while(b)
{
b->BLOCKTIME--;
b = b->NEXT;
}
}
void print_pcb()
{
cout<<"---------------就绪,阻塞队列-------------" << endl;
PCB * r = READY_QUEUE.NEXT;
cout << "READY_QUEUE -> ";
while(r!=NULL)
{
cout << "ID" << r->ID << " -> ";
r = r->NEXT;
}
cout << " NULL " << endl;
PCB * b = BLOCK_QUEUE.NEXT;
cout << "BLOCK_QUEUE -> ";
while(b!=NULL)
{
cout << "ID" << b->ID << " -> ";
b = b->NEXT;
}
cout << " NULL " << endl;
PCB temp[5];
memcpy(temp, produces, 5*sizeof(PCB));
ort(temp, &temp[4], compare_id);
cout <<"----------------所有进程信息--------------" << endl;
cout << setw(11) << "ID"
<< setw(11) << "PRIORITY"
<< setw(11) << "CPUTIME"
<< setw(11) << "ALLTIME"
<< setw(11) << "STARTBLOCK"
<< setw(11) << "BLOCKTIME"
<< setw(11) << "STATE" << endl;
for(int i=0; i<5; i++)
{
cout << setw(11) << temp[i].ID ;
cout << setw(11) << temp[i].PRIORITY ;
cout << setw(11) << temp[i].CPUTIME ;
cout << setw(11) << temp[i].ALLTIME ;
cout << setw(11) << temp[i].STARTBLOCK ;
cout << setw(11) << temp[i].BLOCKTIME ;
if(temp[i].STATE==READY)
cout << setw(11) << "READY" ;
else if(temp[i].STATE==BLOCK)
cout << setw(11) << "BLOCK" ;
else if(temp[i].STATE==FINISH)
cout << setw(11) << "FINISH" ;
cout << endl;
}
}
int main()
{
inital_queue();
while(READY_QUEUE.NEXT!=NULL)
{
run();
inital_queue();
print_pcb();
system("pause");
}
cout << "finish all produces" << endl;
return 0;
}
//头文件
#ifndef DEFINE_H
#define DEFINE_H
// STATE
#define READY 1
#define BLOCK 2
#define RUN 3
#define FINISH 4
// struct declaration
struct PCB
{int ID;
int PRIORITY;
int CPUTIME;
int ALLTIME;
int STARTBLOCK;
int BLOCKTIME;
int STATE;
PCB * NEXT;
};
void print_pcb();
void inital_queue();
void run();
#endif
五、 实验结果:
本次实验输入了5个进程,到达时间均为0。依PCB链接顺序从第一个进程PCB开始,使进程编号依次为0,1,2,3,4。每个PCB包含7项信息。就绪链表中的进程的数量,由常量num控制,模拟建立调度函数,取就绪链表表头PCB,每运行一次,ALLTIME减一,CPUTIME加一,PRIORITY减3。当ALLTIME等于O时,将此进程的PCB取出,放入FINISH链表。对BLOCK链表和就绪链表中的其余进程PCB还要将PRIORITY加一,BOLCKTIME减一,并通过INITIAL函数完成队列转换。按以上次序依完成链表中所有进程,并记录完成进程的完成时间,最后计算和打印进程调度信息并计算出进程周转时间及所有进程的平均周转时间。
六、 实验小结:(要能回答如下问题)
实验三 作业调度算法
组织输入作业流文件,其中存储的是一系列要执行的作业,每个作业包括三个数据项:作业号、作业进入系统的时间(用一整数表示,如10:10,表示成1010)、估计执行时间(单位分)优先级(0级最高)。
参数用空格隔开,下面是示例(输入文件名称:2job.txt,该文件要由学生在解题前自己设置。该文件内容为:(调度时间为第一个作业到达时间)
1 8:00 5 0
2 8:15 3 0
3 8:30 2 5
4 8:35 2 0
输出按照作业调度次序输出每一个作业流文件:“作业号”、“进入内存的时间”、“作业完成时间”、“周转时间”;每行输出一个作业信息,计算出均周转时间并输出。
微机+windows操作系统+VC++6.0
#include<stdio.h>
#include<iostream.h>
#include<iomanip.h>
#include<string.h>
const int MAXJOB=50; //定义最大作业
//定义数据结构体
typedef struct node{
int number;
int reach_time;
int reach_hour;
int reach_minite;
int need_time;
int privilege;
float excellent;
int start_time;
int wait_time;
int visited;
}job;
job jobs[MAXJOB];
int quantity;
//初始化函数
void initial()
{
int i;
for(i=0;i<MAXJOB;i++){
jobs[i].number=0;
jobs[i].reach_time=0;
jobs[i].reach_hour=0;
jobs[i].reach_minite=0;
jobs[i].privilege=0;
jobs[i].excellent=0;
jobs[i].start_time=0;
jobs[i].wait_time=0;
jobs[i].visited=0;
}
quantity=0;
}
//重置作业数据函数
void reset()
{ int i;
for(i=0;i<MAXJOB;i++){
jobs[i].start_time=0;
jobs[i].wait_time=0;
jobs[i].visited=0;
}
}
//读入作业数据函数
void readData()
{
FILE *fp;
char fname[20];
int i;
cout<<"请输入作业数据文件名:";
cin>>fname;
if((fp=fopen(fname,"r"))==NULL){
cout<<"错误,文件打不开,请检查文件名:)"<<endl;
}
else{
while(!feof(fp)){
fscanf(fp,"%d %d %d %d",&jobs[quantity].number,&jobs[quantity].reach_time,&jobs[quantity].need_time,&jobs[quantity].privilege);
jobs[quantity].reach_hour=jobs[quantity].reach_time/100;
jobs[quantity].reach_minite=jobs[quantity].reach_time%100;
quantity++;
}
//输出初始作业数据
cout<<"输出初始作业数据"<<endl;
cout<<"---------------------------------------------------------------"<<endl;
cout.setf(2);
cout<<setw(10)<<"作业号"<<setw(12)<<"到达时间"<<setw(14)<<"所需时间(分)"<<setw(14)<<"优先级(0>1)"<<endl;
for(i=0;i<quantity;i++){
// cout<<setw(10)<<jobs[i].number<<setw(12)<<jobs[i].reach_time<<setw(14)<<jobs[i].need_time<<setw(14)<<jobs[i].privilege<<endl;
cout<<setw(10)<<jobs[i].number<<setw(2)<<jobs[i].reach_hour<<":"<<setw(9)<<jobs[i].reach_minite<<setw(14)<<jobs[i].need_time<<setw(14)<<jobs[i].privilege<<endl;
}
}
}
//FIFO算法
void FIFO( )
{
int i;
int current_hour;
int current_minute;
int total_time=0;
//输出作业流
cout<<endl;
cout<<endl<<"FIFO算法作业流"<<endl;
cout<<"---------------------------------------------------------------"<<endl;
cout.setf(2);
cout<<setw(10)<<"作业号"<<setw(12)<<"到达时间"<<setw(12)<<"开始时间"<<setw(14)<<"周转时间(分)"<<endl;
current_hour=jobs[0].reach_hour;
current_minute=jobs[0].reach_minite;
for(i=0;i<quantity;i++){
jobs[i].start_time=current_hour*100+current_minute;
jobs[i].wait_time=(current_hour-jobs[i].reach_hour)*60+(current_minute-jobs[i].reach_minite)+jobs[i].need_time;
// cout<<setw(10)<<jobs[i].number<<setw(12)<<jobs[i].reach_time<<setw(12)<<jobs[i].start_time<<setw(14)<<jobs[i].wait_time<<endl;
cout<<setw(10)<<jobs[i].number<<setw(2)<<jobs[i].reach_hour<<":"<<setw(9)<<jobs[i].reach_minite<<setw(2)<<current_hour<<":"<<setw(9)<<current_minute<<setw(14)<<jobs[i].wait_time<<endl;
if(jobs[i+1].reach_time<(jobs[i].start_time+jobs[i].need_time))
{
current_hour=current_hour+(jobs[i].need_time+current_minute)/60;
current_minute=(jobs[i].need_time+current_minute)%60;
}
else
{
current_hour=jobs[i+1].reach_time/100;
current_minute=jobs[i+1].reach_time%100;
}
total_time+=jobs[i].wait_time;
}
cout<<endl<<"总周转时间:"<<total_time<<" 平均周转时间:"<<total_time/quantity<<endl;
}
//运算时间短的作业优先算法
void shorter()
{
int i,j,p;
int current_hour;
int current_minute;
int current_need_time;
int total_time=0;
//输出作业流
cout<<endl;
cout<<endl<<"时间短作业优先算法作业流(开始调度时刻为最后一个作业到达系统的时间)"<<endl;
cout<<"------------------------------------------------------------------------"<<endl;
cout.setf(2);
cout<<setw(10)<<"作业号"<<setw(12)<<"到达时间"<<setw(14)<<"所需时间(分)"<<setw(12)<<"开始时间"<<setw(14)<<"周转时间(分)"<<endl;
current_hour=jobs[quantity-1].reach_hour;
current_minute=jobs[quantity-1].reach_minite;
for(i=0;i<quantity;i++){
current_need_time=30000;
for(j=0;j<quantity;j++){
if((jobs[j].visited==0)&&(jobs[j].need_time<current_need_time)){
p=j;
current_need_time=jobs[j].need_time;
}
}
jobs[p].start_time=current_hour*100+current_minute;
jobs[p].wait_time=(current_hour-jobs[p].reach_hour)*60+(current_minute-jobs[p].reach_minite)+jobs[p].need_time;
// cout<<setw(10)<<jobs[p].number<<setw(12)<<jobs[p].reach_time<<setw(14)<<jobs[p].need_time<<setw(12)<<jobs[p].start_time<<setw(14)<<jobs[p].wait_time<<endl; cout<<setw(10)<<jobs[p].number<<setw(2)<<jobs[p].reach_hour<<":"<<setw(9)<<jobs[p].reach_minite<<setw(14)<<jobs[p].need_time<<setw(2)<<current_hour<<":"<<setw(9)<<current_minute<<setw(14)<<jobs[p].wait_time<<endl;
current_hour=current_hour+(jobs[p].need_time+current_minute)/60;
current_minute=(jobs[p].need_time+current_minute)%60;
jobs[p].visited=1;
total_time+=jobs[p].wait_time;
}
cout<<endl<<"总周转时间:"<<total_time<<" 平均周转时间:"<<total_time/quantity<<endl;
}
//优先数调度算法
void privilege()
{
int i,j,p;
int current_hour;
int current_minute;
int current_privilege;
int total_time=0;
//输出作业流
cout<<endl;
cout<<endl<<"优先数调度算法作业流(开始调度时刻为最后一个作业到达系统的时间)"<<endl;
cout<<"------------------------------------------------------------------------"<<endl;
cout.setf(2);
cout<<setw(10)<<"作业号"<<setw(12)<<"到达时间"<<setw(14)<<"优先级(0>1)"<<setw(12)<<"开始时间"<<setw(14)<<"周转时间(分)"<<endl;
current_hour=jobs[quantity-1].reach_hour;
current_minute=jobs[quantity-1].reach_minite;
for(i=0;i<quantity;i++){
current_privilege=30000;
for(j=0;j<quantity;j++){
if((jobs[j].visited==0)&&(jobs[j].privilege<current_privilege)){
p=j;
current_privilege=jobs[j].privilege;
}
}
jobs[p].start_time=current_hour*100+current_minute;
jobs[p].wait_time=(current_hour-jobs[p].reach_hour)*60+(current_minute-jobs[p].reach_minite)+jobs[p].need_time;
// cout<<setw(10)<<jobs[p].number<<setw(12)<<jobs[p].reach_time<<setw(14)<<jobs[p].privilege<<setw(12)<<jobs[p].start_time<<setw(14)<<jobs[p].wait_time<<endl;
cout<<setw(10)<<jobs[p].number<<setw(2)<<jobs[p].reach_hour<<":"<<setw(9)<<jobs[p].reach_minite<<setw(14)<<jobs[p].privilege<<setw(2)<<current_hour<<":"<<setw(9)<<current_minute<<setw(14)<<jobs[p].wait_time<<endl;
current_hour=current_hour+(jobs[p].need_time+current_minute)/60;
current_minute=(jobs[p].need_time+current_minute)%60;
jobs[p].visited=1;
total_time+=jobs[p].wait_time;
}
cout<<endl<<"总周转时间:"<<total_time<<" 平均周转时间:"<<total_time/quantity<<endl;
}
//响应比最高者优先调度算法
void excellent()
{
int i,j,p;
int current_hour;
int current_minute;
float current_excellent;
int total_time=0;
//输出作业流
cout<<endl;
cout<<endl<<"响应比高者优先调度算法作业流(开始调度时刻为最后一个作业到达系统的时间)"<<endl;
cout<<"------------------------------------------------------------------------"<<endl;
cout.setf(2);
cout<<setw(10)<<"作业号"<<setw(12)<<"到达时间"<<setw(12)<<"开始时间"<<setw(14)<<"周转时间(分)"<<endl;
current_hour=jobs[quantity-1].reach_hour;
current_minute=jobs[quantity-1].reach_minite;
for(i=0;i<quantity;i++){
current_excellent=-1;
for(j=0;j<quantity;j++){
if(jobs[j].visited==0){
jobs[j].wait_time=(current_hour-jobs[j].reach_hour)*60+(current_minute-jobs[j].reach_minite);
jobs[j].excellent=(float)(jobs[j].wait_time/jobs[j].need_time);
}
}
for(j=0;j<quantity;j++){
if((jobs[j].visited==0)&&(jobs[j].excellent>current_excellent)){
p=j;
current_excellent=jobs[j].excellent;
}
}
jobs[p].start_time=current_hour*100+current_minute;
jobs[p].wait_time=(current_hour-jobs[p].reach_hour)*60+(current_minute-jobs[p].reach_minite)+jobs[p].need_time;
// cout<<setw(10)<<jobs[p].number<<setw(12)<<jobs[p].reach_time<<setw(12)<<jobs[p].start_time<<setw(14)<<jobs[p].wait_time<<endl; cout<<setw(10)<<jobs[p].number<<setw(2)<<jobs[p].reach_hour<<":"<<setw(9)<<jobs[p].reach_minite<<setw(2)<<current_hour<<":"<<setw(9)<<current_minute<<setw(14)<<jobs[p].wait_time<<endl;
current_hour=current_hour+(jobs[p].need_time+current_minute)/60;
current_minute=(jobs[p].need_time+current_minute)%60;
jobs[p].visited=1;
total_time+=jobs[p].wait_time;
}
cout<<endl<<"总周转时间:"<<total_time<<" 平均周转时间:"<<total_time/quantity<<endl;
}
void main()
{
initial();
readData();
FIFO();
shorter();
reset();
privilege();
reset();
excellent();
}
![]() |
![]() |
了解动态分区分配方式中使用的数据结构和分配算法,并进一步加深对动态分区存储管理方式及其实现过程的理解。用C语言分别实现首次适应动态分区分配过程 alloc()和回收过程free()。
假设初始状态下可用内存空间为640KB,并按以下序列进行内存空间的请求和释放:作业1申请130kb空间;作业2申请60kb空间;作业3申请100kb空间;作业2释放60kb空间;作业4申请200kb空间;作业3释放100kb空间;作业1释放130kb空间;作业5申请140kb空间;作业6申请60kb空间;作业7申请50kb空间;作业6申请60kb空间。
三、 实验器材:
微机+windows操作系统+VC++6.0
#include<iostream.h>
#include<stdlib.h>
#define Free 0 //空闲状态
#define Busy 1 //已用状态
#define OK 1 //完成
#define ERROR 0 //出错
#define MAX_length 640 //最大内存空间为640KB
typedef int Status;
typedef struct freearea//定义一个空闲区说明表结构
{
int ID; //分区号
long size; //分区大小
long address; //分区地址
int state; //状态
}ElemType;
//---------- 线性表的双向链表存储结构 ------------
typedef struct DuLNode //double linked list
{
ElemType data;
struct DuLNode *prior; //前趋指针
struct DuLNode *next; //后继指针
}DuLNode,*DuLinkList;
DuLinkList block_first; //头结点
DuLinkList block_last; //尾结点
Status alloc(int);//内存分配
Status free(int); //内存回收
Status First_fit(int,int);//首次适应算法
void show();//查看分配
Status Initblock();//开创空间表
Status Initblock()//开创带头结点的内存空间链表
{
block_first=(DuLinkList)malloc(sizeof(DuLNode));
block_last=(DuLinkList)malloc(sizeof(DuLNode));
block_first->prior=NULL;
block_first->next=block_last;
block_last->prior=block_first;
block_last->next=NULL;
block_last->data.address=0;
block_last->data.size=MAX_length;
block_last->data.ID=0;
block_last->data.state=Free;
return OK;
}
//-----------------------分 配 主 存 -------------------------
Status alloc(int ch)
{
int ID,request;
cout<<"请输入作业(分区号):";
cin>>ID;
cout<<"请输入需要分配的主存大小(单位:KB):";
cin>>request;
if(request<0 ||request==0)
{cout<<"分配大小不合适,请重试!"<<endl;
return ERROR;
}
if(First_fit(ID,request)==OK) cout<<"分配成功!"<<endl;
else cout<<"内存不足,分配失败!"<<endl;
return OK;
}
//------------------首次适应算法 -----------------------
Status First_fit(int ID,int request)//传入作业名及申请量
{
//为申请作业开辟新空间且初始化
DuLinkList temp=(DuLinkList)malloc(sizeof(DuLNode));
temp->data.ID=ID;
temp->data.size=request;
temp->data.state=Busy;
DuLNode *p=block_first->next;
while(p)
{
if(p->data.state==Free && p->data.size==request)
{//有大小恰好合适的空闲块
p->data.state=Busy;
p->data.ID=ID;
return OK;
break;
}
if(p->data.state==Free && p->data.size>request)
{//有空闲块能满足需求且有剩余"
temp->prior=p->prior;
temp->next=p;
temp->data.address=p->data.address;
p->prior->next=temp;
p->prior=temp;
p->data.address=temp->data.address+temp->data.size;
p->data.size-=request;
return OK;
break;
}
p=p->next;
}
return ERROR;
}
//----------------------- 主 存 回 收 --------------------
Status free(int ID)
{
DuLNode *p=block_first;
while(p)
{
if(p->data.ID==ID)
{
p->data.state=Free;
p->data.ID=Free;
if(p->prior->data.state==Free)//与前面的空闲块相连
{
p->prior->data.size+=p->data.size;
p->prior->next=p->next;
p->next->prior=p->prior;
}
if(p->next->data.state==Free)//与后面的空闲块相连
{
p->data.size+=p->next->data.size;
p->next->next->prior=p;
p->next=p->next->next;
}
break;
}
p=p->next;
}
return OK;
}
//--------------- 显示主存分配情况 ------------------
void show()
{
cout<<"+++ 主 存 分 配 情 况 +++\n";
DuLNode *p=block_first->next;
while(p)
{
cout<<"分 区 号:";
if(p->data.ID==Free) cout<<"Free"<<endl;
else cout<<p->data.ID<<endl;
cout<<"起始地址:"<<p->data.address<<endl;
cout<<"分区大小:"<<p->data.size<<" KB"<<endl;
cout<<"状 态:";
if(p->data.state==Free) cout<<"空 闲"<<endl;
else cout<<"已分配"<<endl;
cout<<"——————————————"<<endl;
p=p->next;
}
}
//-----------------------主 函 数---------------------------
void main()
{
int ch;//算法选择标记
cout<<" 首次适应算法 \n";
Initblock(); //开创空间表
int choice; //操作选择标记
while(1)
{
cout<<"1:分配内存;2:回收内存;3:查看分配;0:退出;\n";
cout<<"请输入您的操作 :";
cin>>choice;
if(choice==1) alloc(ch); //分配内存
else if(choice==2) //内存回收
{
int ID;
cout<<"请输入您要释放的分区号:";
cin>>ID;
free(ID);
}
else if(choice==3) show();//显示主存
else if(choice==0) break; //退出
else //输入操作有误
{
cout<<"输入有误,请重试!"<<endl;
continue;
}
}
}
本程序的首次适应算法实现过程是:首先通过输入作业的ID号和申请空间大小,使用ALLOC函数分配内存空间,分配算法是在空闲分区链表中找到第一个足以满足要求的空闲分区就停止查找并将该分区分配出去。如果该空闲分区尺寸与所需空间大小一样,则从空闲分区表中取消该表项;如果还有剩余,则余下的部分仍留在空闲分区链表中,但应修改双向链表中的分区大小和分区始址。内存回收过程是将释放作业所在内存分区的状态改为空闲状态,删除其作业名,设置为空。并判断该空闲分区是否与其他空闲分区相连,若释放的内存空间与空闲分区相连时,则合并为同一个空闲分区,同时修改分区大小及起始地址。
用VC语言模拟一道作业的执行过程,可以选择的页面置换算法有先进先出FIFO、最佳置换算法OPT和最近最久未使用LRU三种算法中的一种实现。页面序列:2、3、2、1、5、2、4、5、3、2、5、2;定义的页面数为3页(输入文件名为:1job.txt),该文件内容为:2 3 2 1 5 2 4 5 3 2 5 2。该文件要由学生在解题前自己设置。
微机+windows操作系统+VC++6.0
#include<stdio.h>
#include<string.h>
#include<iostream.h>
const int MAXSIZE=1000;//定义最大页面数
const int MAXQUEUE=3;//定义页框数
typedef struct node{
int loaded;
int hit;
}page;
page pages[MAXQUEUE]; //定义页框表
int queue[MAXSIZE];
int quantity;
//初始化结构函数
void initial()
{
int i;
for(i=0;i<MAXQUEUE;i++){
pages[i].loaded=-1;
pages[i].hit=0;
}
for(i=0;i<MAXSIZE;i++){
queue[i]=-1;
}
quantity=0;
}
//初始化页框函数
void init()
{
int i;
for(i=0;i<MAXQUEUE;i++){
pages[i].loaded=-1;
pages[i].hit=0;
}
}
//读入页面流
void readData()
{
FILE *fp;
char fname[20];
int i;
cout<<"请输入页面流文件名:";
cin>>fname;
if((fp=fopen(fname,"r"))==NULL){
cout<<"错误,文件打不开,请检查文件名";
}
else{
while(!feof(fp)){
fscanf(fp,"%d ",&queue[quantity]);
quantity++;
}
}
cout<<"读入的页面流:";
for(i=0;i<quantity;i++){
cout<<queue[i]<<" ";
}
}
//FIFO调度算法
void FIFO()
{
int i,j,p,flag;
int absence=0;
p=0;
cout<<endl<<"----------------------------------------------------"<<endl;
cout<<"FIFO调度算法页面调出流:";
for(i=0;i<quantity;i++){
flag=0;
for(j=0;j<MAXQUEUE;j++){
if(pages[j].loaded==queue[i]){
flag=1;
}
}
if(flag==0){
if(absence>=MAXQUEUE){
cout<<pages[p].loaded<<" ";
}
pages[p].loaded=queue[i];
p=(p+1)%MAXQUEUE;
absence++;
}
}
absence-=MAXQUEUE;
cout<<endl<<"总缺页数:"<<absence<<endl;
}
//最近最少使用调度算法(LRU)
void LRU()
{
int absence=0;
int i,j;
int flag;
for(i=0;i<MAXQUEUE;i++){
pages[i].loaded=queue[i];
}
cout<<endl<<"----------------------------------------------------"<<endl;
cout<<"最近最少使用调度算法(LRU)页面流:";
for(i=MAXQUEUE;i<quantity;i++){
flag=-1;
for(j=0;j<MAXQUEUE;j++){
if(queue[i]==pages[j].loaded){
flag=j;
}
}
//CAUTION pages[0]是队列头
if(flag==-1){
//缺页处理
cout<<pages[0].loaded<<" ";
for(j=0;j<MAXQUEUE-1;j++){
pages[j]=pages[j+1];
}
pages[MAXQUEUE-1].loaded=queue[i];
absence++;
}
else{
//页面已载入
pages[quantity]=pages[flag];
for(j=flag;j<MAXQUEUE-1;j++){
pages[j]=pages[j+1];
}
pages[MAXQUEUE-1]=pages[quantity];
}
}
cout<<endl<<"总缺页数:"<<absence<<endl;
}
//最近最不常用调度算法(LFU)
void LFU()
{
int i,j,p;
int absence=0;
int flag;
for(i=0;i<MAXQUEUE;i++){
pages[i].loaded=queue[i];
}
cout<<endl<<"----------------------------------------------------"<<endl;
cout<<"最近最不常用调度算法(LFU)页面流:";
for(i=MAXQUEUE;i<quantity;i++){
flag=-1;
for(j=0;j<MAXQUEUE;j++){
if(pages[j].loaded==queue[i]){
flag=1;
pages[j].hit++;
}
}
if(flag==-1){
//缺页中断
p=0;
for(j=0;j<MAXQUEUE;j++){
if(pages[j].hit<pages[p].hit){
p=j;
}
}
cout<<pages[p].loaded<<" ";
pages[p].loaded=queue[i];
for(j=0;j<MAXQUEUE;j++){
pages[j].hit=0;
}
absence++;
}
}
cout<<endl<<"总缺页数:"<<absence<<endl;
}
//第二次机会算法
void second()
{
int i,j,t;
int absence=0;
int flag,temp;
for(i=0;i<MAXQUEUE;i++){
pages[i].loaded=queue[i];
}
cout<<endl<<"----------------------------------------------------"<<endl;
cout<<"第二次机会算法页面流:";
for(i=MAXQUEUE;i<quantity;i++){
flag=-1;
for(j=0;j<MAXQUEUE;j++){
if(pages[j].loaded==queue[i]){
flag=1;
pages[j].hit=1;
}
}
if(flag==-1){
//缺页处理
t=0;
while(t==0){
if(pages[0].hit==0){
cout<<pages[0].loaded<<" ";
for(j=0;j<MAXQUEUE-1;j++){
pages[j]=pages[j+1];
}
pages[MAXQUEUE-1].loaded=queue[i];
pages[MAXQUEUE-1].hit=0;
t=1;
}
else{
temp=pages[0].loaded;
for(j=0;j<MAXQUEUE-1;j++){
pages[j]=pages[j+1];
}
pages[MAXQUEUE-1].loaded=temp;
pages[MAXQUEUE-1].hit=0;
}
}
absence++;
}
}
cout<<endl<<"总缺页数:"<<absence<<endl;
}
void main()
{
initial();
readData();
FIFO();
init();
LRU();
init();
LFU();
init();
second();
}
![]() |
用VC语言模拟磁盘调度算法,分别实现先来先服务、最短寻道优先和电梯算法。磁盘访问序列为:2、10、8、1、14、3、9、16、20。输入文件名称:**.txt,该文件要由学生在解题前自己设置。假设当前磁头位于第4磁道。
微机+windows操作系统+VC++6.0
#include<stdio.h>
#include<iostream.h>
#include<string.h>
#include<math.h>
const int MAXQUEUE=200; //定义队列最大数
//结构体定义
typedef struct node{
int go;
int visited;
}qu;
qu queue[MAXQUEUE];
int quantity;
int start; //定义开始时磁头所在位置
//初始化函数
void initial()
{
int i;
for(i=0;i<MAXQUEUE;i++){
queue[i].go=-1;
queue[i].visited=0;
}
start=53;//磁头的初始位置
}
//读入磁道号流
void readData()
{
FILE *fp;
char fname[20];
int temp,i;
cout<<"请输入磁道号流文件名:";
cin>>fname;
if((fp=fopen(fname,"r"))==NULL){
cout<<"错误,文件打不开,请检查文件名:)"<<endl;
}
else{
while(!feof(fp)){
fscanf(fp,"%d ",&temp);
queue[quantity].go=temp;
quantity++;
}
cout<<endl<<"---------------------------------------------"<<endl;
cout<<"所读入的磁道号流:";
for(i=0;i<quantity;i++){
cout<<queue[i].go<<" ";
}
cout<<endl<<"请求数为:"<<quantity<<endl;
}
}
//FIFO算法
void FIFO()
{
int i;
int total=0;
int current;
cout<<endl<<"---------------------------------------------"<<endl;
cout<<"FIFO算法的访问磁道号顺序流:";
current=start;
for(i=0;i<quantity;i++){
cout<<queue[i].go<<" ";
total+=abs(queue[i].go-current);
current=queue[i].go;
}
cout<<endl<<"磁头移过的柱面数:"<<total;
}
//最短寻道优先调度算法
void shortest()
{
int i,j,p;
int total=0;
int current;
cout<<endl<<"---------------------------------------------"<<endl;
cout<<"最短寻道优先调度算法的访问磁道号顺序流:";
current=start;
for(i=0;i<quantity;i++){
p=0;
while(queue[p].visited!=0){
p++;
}
for(j=p;j<quantity;j++){
if((queue[j].visited==0)&&(abs(current-queue[p].go)>abs(current-queue[j].go))){
p=j;
}
}
cout<<queue[p].go<<" ";
total+=abs(queue[p].go-current);
queue[p].visited=1;
current=queue[p].go;
}
cout<<endl<<"磁头移过的柱面数:"<<total;
}
//电梯算法
void elevator()
{
int i,j,p,flag;
int total=0;
int current;
cout<<endl<<"---------------------------------------------"<<endl;
cout<<"电梯调度算法"<<endl;
//磁头初始向里
cout<<"磁头初始向里的访问磁道号顺序流:";
current=start;
for(i=0;i<quantity;i++){
flag=1000;
p=-1;
for(j=0;j<quantity;j++){
if((queue[j].visited==0)&&(queue[j].go>=current)){
if(abs(queue[j].go-current)<flag){
p=j;
flag=abs(queue[j].go-current);
}
}
}
if(p!=-1){
cout<<queue[p].go<<" ";
total+=abs(queue[p].go-current);
current=queue[p].go;
queue[p].visited=1;
}
else{
for(j=0;j<quantity;j++){
if((queue[j].visited==0)&&(queue[j].go<current)){
if(abs(queue[j].go-current)<flag){
p=j;
flag=abs(queue[j].go-current);
}
}
}
cout<<queue[p].go<<" ";
total+=abs(queue[p].go-current);
current=queue[p].go;
queue[p].visited=1;
}
}
cout<<endl<<"磁头移过的柱面数:"<<total<<endl;
//磁头初始向外
for(i=0;i<quantity;i++){
queue[i].visited=0;
}
total=0;
cout<<"磁头初始向外的访问磁道号顺序流:";
current=start;
for(i=0;i<quantity;i++){
flag=1000;
p=-1;
for(j=0;j<quantity;j++){
if((queue[j].visited==0)&&(queue[j].go<=current)){
if(abs(queue[j].go-current)<flag){
p=j;
flag=abs(queue[j].go-current);
}
}
}
if(p!=-1){
cout<<queue[p].go<<" ";
total+=abs(queue[p].go-current);
current=queue[p].go;
queue[p].visited=1;
}
else{
for(j=0;j<quantity;j++){
if((queue[j].visited==0)&&(queue[j].go>current)){
if(abs(queue[j].go-current)<flag){
p=j;
flag=abs(queue[j].go-current);
}
}
}
cout<<queue[p].go<<" ";
total+=abs(queue[p].go-current);
current=queue[p].go;
queue[p].visited=1;
}
}
cout<<endl<<"磁头移过的柱面数:"<<total;
}
void main()
{
int i;
initial();
readData();
FIFO();
shortest();
for(i=0;i<quantity;i++){
queue[i].visited=0;
}
elevator();
}
五、实验结果:
六、实验小结:(要能回答如下问题)