资源描述
学生课程设计报告
实验课名称:操作系统
实验项目名称: 进程管理模拟系统
专 业 名 称: 软件工程
班 级:********
组 长:猪十万
组 员:*********
教 师 姓 名:李芳
2011 年 6 月 27 日
一、 小组成员及分工
成员姓名:
工作:
****
分析算法及整合代码。
****
共同讨论,实现部分编写。
****
共同讨论,实现部分编码。
****
共同讨论,实现部分编码。
二、 系统采用语言及支撑平台
语言:C++语言
平台:linux系统
三、 实验原理:
进程管理包括进程的控制、阻塞、唤醒与撤消。进程在运行过程中状态在不断的变化。进程运行过程中,因为竞争资源而需对它们进行同步控制。所有这些在操作系统中用数据结构PCB来记录,系统通过PCB控制进程的运行。
在单处理机系统中,多道程序的引入,需要进程的调度程序来选择一个进程进行运行。比如常用的先来先服务、短进程优和优先级优先等等,也可以选择它们的结合调度算法。
四、 设计思想
1、问题描述
本系统的同步机构采用的信号量上的P、V操作的机制;控制机构包括阻塞和唤醒操作;时间片中断处理程序处理模拟的时间片中断;进程调度程序负责为各进程分配处理机。
系统中设计了3个并发进程.它们之间有如下同步关系:3个进程需要互斥使用临界资源s2,进程1和进程2又需互斥使用临界资源s1。本系统在运行过程中随机打印出各进程的状态变换过程,系统的调度过程及公共交量的变化情况。
2、算法
系统为进程设置了5种运行状态:e——执行态;r——高就绪态;t——低就绪态(执行进程因时间片到限而转入):w——等待态;c——完成态。各进程的初始状态均设置为r。
系统分时执行各进程。通过产生随机数x来模拟时间片(每一个时间片并不相同)。当进程processl访问随机数x时,若x≥0.33;当进程proccss2访问x时,若x<0.33或x≥0.66;当进程process3访问x时,若x<0.66,则分别认为各进程的执行时间片到限,产生“时间片中断”面转入低就绪态t。
进程调度算法采用剥夺式最高优先数法。各进程的优先数通过键盘输入予以静态设置。调度程序每次总是选择优先数最小(优先权最高)的就绪进程投入执行。先从r状态进程中选择,再从t状态进程中选择。当现行进程唤醒某个等待进程,且被唤醒进程的比先数小于现行进程时,则剥夺现行进程的执行权。
各进程在使用临界资源s1和s2时,通过调用信号量sem1和sem2上的P、V操作来实现同步。阻塞和唤醒操作负责完成从进程的执行态到等待态以及从就绪态的转变。
系统启动后,在完成必要的系统初始化后便执行进程调度程序。当执行因“时间片中断”,或者被排斥使用临界资源,或唤醒某个等待进程时,立即进行进程调度。当3个进程都处于完成状态后,系统退出运行。
3、数据结构
①每个进程一个PCB,内容:
id 进程标识
status 进程状态
priority 进程优先数
nextwr 等待队链指针,指示在同一信号量上等待的下一个进程的标识。
②信号量。对应于临界资源s1和s2分别有sem1和sem2,均为互斥号量,内容包括:
value 信号量值,初值为1
firstwr 等待 链指针,指示在该信号量上第一个等待进程的标识数。
③保留区。用数组saveaera[3][4]表示。即每个进程都有一个大小为4个单元的保留区,用来保存被“中断”时的现场信息,如通用寄存器的内容和断点地址等。
④全程变量。
exe 执行进程指针,其值为进程标识数
i 用来模拟一个通用寄存器。
五、 程序流程图
六、 程序功能段的说明及代码解释
系统界面:
输入三个进程优先数,并点击“开始”:
执行完成的界面:
main.cpp文件:程序的主要入口,主函数。
#include "operate.h"
#include "uiOp.h"
#include <QApplication>
int main(int args,char**argv)
{
QApplication app(args,argv);
operate op;
op.setVisible(true);
return app.exec();
}
operate.h文件:操作的头文件
#ifndef OPERATE_H
#define OPERATE_H
#include <QDialog>
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include "uiOp.h"
using namespace std;
#define MAXPRI 100
#define NIL -1
class operate : public QDialog
{
Q_OBJECT
private:
Ui_Dialog ui;
QWidget wid;
static int a;
int ba[3];
char savearea[3][4],addr;
int i;//模拟通用寄存器
int s1=0,s2=0;//两个临界资源
int seed;
int exe=NIL;//执行进程指针 其值为进程标示数
public:
operate();
public slots:
void start();
void reset();
public:
void init(int pri[],int n);
float random1();
bool timeint(char ad);
int scheduler();
int find();
bool p(int se,char ad);
void block(int se);
bool v(int se,char ad);
void wakeup(int se);
void process1();
void process2();
void process3();
void eexit(int n);
float random2();
void run(int pri[],int n);
struct{
int id;
char status;
int nextwr; //等待队列指针,指示在同一个信号上等待的下一个进程标识
int priority;
}pcb[3];
struct
{
int value;
int firstwr; //等待链指针,指示在该信号量上第一个等待进程的表示数
}sem[2];
};
#endif
operate.cpp文件:操作的实现文件。
#include"operate.h"
operate::operate()
{
ui.setupUi(this);
connect(ui.pushButton,SIGNAL(clicked()),
this,SLOT(start()));
connect(ui.pushButton_2,SIGNAL(clicked()),
this,SLOT(reset()));
}
void operate::start(){
QString str1=ui.lineEdit1->text();
QString str2=ui.lineEdit2->text();
QString str3=ui.lineEdit3->text();
ba[0]=str1.toInt();
ba[1]=str2.toInt();
ba[2]=str3.toInt();
run(ba,3);
}
void operate::reset()//閲嶆柊寮€濮?{
ui.lineEdit1->clear();
ui.lineEdit2->clear();
ui.lineEdit3->clear();
ui.plainTextEdit->clear();
update();
}
void operate::run(int pri[],int n)
{
int j=0;
int k;
ui.plainTextEdit->appendPlainText("* * * * process management * * * *");
init(pri,n);
ui.plainTextEdit->appendPlainText("s1="+QString::number(s1)+" s2="+QString::number(s2));
ui.plainTextEdit->appendPlainText("process1,process2,process3 are all in ready!");
for(;;)
{
j=j+1;
ui.plainTextEdit->appendPlainText(QString::number(j)+"th Scheduler to continue!");
repaint();
sleep(1);
ui.plainTextEdit->appendPlainText(NULL);
if((k=scheduler())!=NIL)
{
switch(k)
{
case 0:
process1();
break;
case 1:
process2();
break;
case 2:
process3();
break;
default:
ui.plainTextEdit->appendPlainText("process identifer error!");
break;
}
}
else break;
}
ui.plainTextEdit->appendPlainText("s1="+QString::number(s1)+" s2="+QString::number(s2));
ui.plainTextEdit->appendPlainText(NULL);
ui.plainTextEdit->appendPlainText("* * * * END * * * *");
}
void operate::init(int pri[],int n)
{
int j;
for(j=0;j<3;j++)
{
pcb[j].id=j;
pcb[j].status='r';
pcb[j].nextwr=NIL;
pcb[j].priority=pri[j];
}
sem[0].value=1; sem[0].firstwr=NIL;
sem[1].value=1; sem[1].firstwr=NIL;
for(i=0;i<3;i++)
for(j=0;j<4;j++)
savearea[i][j]='0';
}
float operate::random1()
{
float m;
srand(time(0));
m=(1+rand()%3)%3-0.1;
ui.plainTextEdit->appendPlainText("random"+QString::number(m));
repaint();
sleep(1);
return(m);
}
float operate::random2()
{
float m;
srand(time(0));
m=rand()%1;
return m;
}
bool operate::timeint(char ad)
{
float x;
x=random1();
if((x<0.33)&&(exe==0))
return false;
if((x<0.66)&&(exe==1))
return false;
if((x<1.0)&&(exe==2))
return false;
savearea[exe][0]=i;
savearea[exe][1]=ad;
pcb[exe].status='t';
ui.plainTextEdit->appendPlainText("This times slice interrupt process"+QString::number(exe+1)+" enter into ready!");
exe=NIL;
return true;
}
int operate::scheduler()
{
int pd;
if((pd=find())==NIL&&exe==NIL)
return(NIL); /*quit system*/
if(pd!=NIL)
{
if(exe==NIL)
{
pcb[pd].status='e';
exe=pd;
ui.plainTextEdit->appendPlainText("process"+QString::number(exe+1)+" is executing!");
}
else if(pcb[pd].priority<pcb[exe].priority)
{
pcb[exe].status='r';
ui.plainTextEdit->appendPlainText("process"+QString::number(exe+1)+" enter into ready!");
pcb[pd].status='e';
exe=pd;
ui.plainTextEdit->appendPlainText("process"+QString::number(exe+1)+" is executing!");
}
}
i=savearea[exe][0];
addr=savearea[exe][1];
return exe;
}
int operate::find()
{
int j,pd=NIL,w=MAXPRI;
for(j=0;j<3;j++)
{
if(pcb[j].status=='r')
if(pcb[j].priority<w)
{
w=pcb[j].priority;
pd=j;
}
}
if (pd==NIL)
for(j=0;j<3;j++)
{
if(pcb[j].status=='t')
if(pcb[j].priority<w)
{
w=pcb[j].priority;
pd=j;
}
}
return pd;
}
bool operate::p(int se,char ad)
{
if(--sem[se].value>=0)
return false;
block(se);
savearea[exe][0]=i;
savearea[exe][1]=ad;
exe=NIL;
return true;
}
void operate::block(int se)
{
int w;
ui.plainTextEdit->appendPlainText("process"+QString::number(exe+1)+" is blocked!");
pcb[exe].status='w';
pcb[exe].nextwr=NIL;
if((w=sem[se].firstwr)==NIL)
sem[se].firstwr=exe;
else
{
while(pcb[w].nextwr!=NIL)
w=pcb[w].nextwr;
pcb[w].nextwr=exe;
}
}
bool operate::v(int se,char ad)
{
if(++sem[se].value>0)
return false;
wakeup(se);
savearea[exe][1]=ad;
savearea[exe][0]=i;
return true;
}
void operate::wakeup(int se)
{
int w;
w=sem[se].firstwr;
if(w!=NIL)
{
sem[se].firstwr=pcb[w].nextwr;
pcb[w].status='r';
ui.plainTextEdit->appendPlainText("process"+QString::number(exe+1)+" is waken up!");
}
}
void operate::process1()
{
if(addr=='a') goto a1;
if(addr=='b') goto b1;
if(addr=='c') goto c1;
if(addr=='d') goto d1;
if(addr=='e') goto e1;
if(addr=='f') goto f1;
for(i=0; i<3;i++) {
ui.plainTextEdit->appendPlainText("process1 calls P on the semaphore 1");
if(p(0,'a')) break; /*process 1 is blocked*/
a1: ui.plainTextEdit->appendPlainText("process1 is executing in the cretical section 1");
if(timeint('b')) break; /*time silce interrupt*/
b1: ui.plainTextEdit->appendPlainText("s1="+QString::number(++s1));
ui.plainTextEdit->appendPlainText("process1 calls V on semaphore1 and quit cretical section 1");
if(v(0,'c')) break; /*wake up a blocked process*/
c1: ui.plainTextEdit->appendPlainText("process1 calls P on the semaphore 2");
if(p(1,'d')) break;
d1: ui.plainTextEdit->appendPlainText("process1 is execting cretical section 2.");
if(timeint('e')) break;
e1: ui.plainTextEdit->appendPlainText("s1="+QString::number(++s2));
ui.plainTextEdit->appendPlainText("process1 calls V on semaphore2 and quit cretical section 2");
if(v(1,'f')) break; /*wake up a block process*/
f1: ui.plainTextEdit->appendPlainText("process1 cycle count="+QString::number(i));
}
if(i<3) return;
eexit(0);
}
void operate::process2()
{
if(addr=='a') goto a2;
if(addr=='b') goto b2;
if(addr=='c') goto c2;
if(addr=='d') goto d2;
if(addr=='e') goto e2;
if(addr=='f') goto f2;
for(i=1;i<6;++i)
{
ui.plainTextEdit->appendPlainText("process1 calls P on the semaphore 2");
if(p(1,'a')) break; /*process2 is blocked*/
a2: ui.plainTextEdit->appendPlainText("process2 is executing on the cretical setion2");
if(timeint('b')) break;
b2: ui.plainTextEdit->appendPlainText("s2="+QString::number(++s2));
ui.plainTextEdit->appendPlainText("process2 calls V on semaphore2 and quit cretical section 2");
if(v(1,'c')) break; /*wake up a blocked process*/
c2: ui.plainTextEdit->appendPlainText("process2 calls P on the semaphore 1");
if(p(0,'d')) break; /*process2 is blocked*/
d2: ui.plainTextEdit->appendPlainText("process2 is executing cretical setion1");
if(timeint('e')) break;
e2: ui.plainTextEdit->appendPlainText("s1="+QString::number(++s1));
ui.plainTextEdit->appendPlainText("process2 calls V on semaphore2 and quit cretical section 2");
if(v(0,'f')) break; /*wkup up a block process*/
f2: ui.plainTextEdit->appendPlainText("process2 cycle count="+QString::number(i));
}
if(i<6) return;
eexit(1);
}
void operate::process3()
{
if(addr=='a') goto a3;
if(addr=='b') goto b3;
if(addr=='c') goto c3;
for(i=1;i<6;++i)
{
ui.plainTextEdit->appendPlainText("process3 call P on semaphore2");
if(p(1,'a'))
break; /*process3 is blocked*/
a3:ui.plainTextEdit->appendPlainText("process3 is executing on its cretical section.");
if(timeint('b'))
break;
b3: ui.plainTextEdit->appendPlainText("s2="+QString::number(++s2));
ui.plainTextEdit->appendPlainText("process3 calls V on semaphore2 and quit cretical section.");
if(v(1,'c'))
break; /*wake up a blocked process */
c3: ui.plainTextEdit->appendPlainText("process3 cycle count="+QString::number(i));
}
if(i<6) return;
eexit(2);
}
void operate::eexit(int n)
{
pcb[n].status='c';
ui.plainTextEdit->appendPlainText("process"+QString::number(n+1)+" is completed");
exe=NIL;
}
uiOP.h文件:绘制窗口的QT文件生成的.h文件。
#ifndef UIOP_H
#define UIOP_H
#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QDialog>
#include <QtGui/QHeaderView>
#include <QtGui/QLabel>
#include <QtGui/QLineEdit>
#include <QtGui/QPlainTextEdit>
#include <QtGui/QPushButton>
QT_BEGIN_NAMESPACE
class Ui_Dialog
{
public:
QLabel *label;
QLabel *label_2;
QLineEdit *lineEdit1;
QPlainTextEdit *plainTextEdit;
QPushButton *pushButton;
QLabel *label_3;
QLabel *label_4;
QLabel *label_5;
QLineEdit *lineEdit2;
QLabel *label_6;
QLineEdit *lineEdit3;
QPushButton *pushButton_2;
void setupUi(QDialog *Dialog)
{
if (Dialog->objectName().isEmpty())
Dialog->setObjectName(QString::fromUtf8("Dialog"));
Dialog->resize(501, 505);
label = new QLabel(Dialog);
label->setObjectName(QString::fromUtf8("label"));
label->setGeometry(QRect(230, 10, 62, 17));
label_2 = new QLabel(Dialog);
label_2->setObjectName(QString::fromUtf8("label_2"));
label_2->setGeometry(QRect(20, 40, 141, 17));
lineEdit1 = new QLineEdit(Dialog);
lineEdit1->setObjectName(QString::fromUtf8("lineEdit1"));
lineEdit1->setGeometry(QRect(70, 80, 61, 27));
plainTextEdit = new QPlainTextEdit(Dialog);
plainTextEdit->setObjectName(QString::fromUtf8("plainTextEdit"));
plainTextEdit->setGeometry(QRect(10, 130, 481, 331));
pushButton = new QPushButton(Dialog);
pushButton->setObjectName(QString::fromUtf8("pushButton"));
pushButton->setGeometry(QRect(400, 80, 71, 27));
label_3 = new QLabel(Dialog);
label_3->setObjectName(QString::fromUtf8("label_3"));
label_3->setGeometry(QRect(10, 110, 62, 17));
label_4 = new QLabel(Dialog);
label_4->setObjectName(QString::fromUtf8("label_4"));
label_4->setGeometry(QRect(20, 80, 41, 17));
label_5 = new QLabel(Dialog);
label_5->setObjectName(QString::fromUtf8("label_5"));
label_5->setGeometry(QRect(140, 80, 41, 17));
lineEdit2 = new QLineEdit(Dialog);
lineEdit2->setObjectName(QString::fromUtf8("lineEdit2"));
lineEdit2->setGeometry(QRect(190, 80, 61, 27));
label_6 = new QLabel(Dialog);
label_6->setObjectName(QString::fromUtf8("label_6"));
label_6->setGeometry(QRect(270, 80, 41, 17));
lineEdit3 = new QLineEdit(Dialog);
lineEdit3->setObjectName(QString::fromUtf8("lineEdit3"));
lineEdit3->setGeometry(QRect(320, 80, 61, 27));
pushButton_2 = new QPushButton(Dialog);
pushButton_2->setObjectName(QString::fromUtf8("pushButton_2"));
pushButton_2->setGeometry(QRect(190, 470, 93, 27));
retranslateUi(Dialog);
QMetaObject::connectSlotsByName(Dialog);
} // setupUi
void retranslateUi(QDialog *Dialog)
{
Dialog->setWindowTitle(QApplication::translate("Dialog", "Dialog", 0, QApplication::UnicodeUTF8));
label->setText(QApplication::translate("Dialog", "\346\230\276\347\244\272\347\252\227\345\217\243", 0, QApplication::UnicodeUTF8));
label_2->setText(QApplication::translate("Dialog", "\350\257\267\350\276\223\345\205\245\344\270\211\344\270\252\350\277\2
展开阅读全文