操作系统实验一《CPU Scheduling》

实验《CPU Scheduling》

实验学时: 4    实验地点: 二综203 实验日期: 2022年10月28日           

一、实验目的

多道系统中,当就绪进程数大于处理机数时,须按照某种策略决定哪些进程优先占用处理机。本实验模拟实现处理机调度,加深了解处理机调度的工作过程。

二、实验内容

选择一个调度算法,实现处理机调度。

1、设计一个按优先权调度算法实现处理机调度的程序;

2、设计按时间片轮转实现处理机调度的程序。

三、实验方法

本实验具体功能由Qt实现,并完成相关图形化界面设计,并在调度过程中加入动画,可以比较直观的看到cpu调度过程。

四、实验过程

1、概要设计

(1)、在实验中始终可以查看各个进程的状态。

(2)、如果内存中进程数少于规定道数,可自动从后备队列通过作业调度选择一作业 进入。

(3)、cpu调度可以实现抢占式优先级调度和时间片轮转两种形式。

(4)、进程调度过程可以使用自动进行和手动一步一步演示两种方式。

(5)、被挂起进程入挂起队列,设置解挂功能用于将指定挂起进程解挂并入就绪队列。

(6)、可动态增加进程。

(7)、可清空后备队列。

(8)、在就绪队列进程进入cpu执行时增加动效。

2、详细设计

(1)、建立数据库,以及表示就绪队列、后备队列、挂起队列、终止队列的数据表。

//指定数据库驱动名,增加数据库实例

     QSqlDatabase db=QSqlDatabase::addDatabase("QSQLITE");

     //设置数据库用户名

     db.setDatabaseName("user.db");

     if(!db.open())

     {

         qDebug()<<"连接失败,失败原因:"<<db.lastError().text();

     }

     else

     {

         qDebug()<<"连接成功";

     }

     //创建一个存储后备队列的表

     QString cmd="create table if not exists waiting( Pid  verchar(64) ,time int ,priority int, state verchar(64) )";

if(query.exec(cmd))

     {

          qDebug()<<"waitingTable exce successful";

     }

//创建一个存储就绪队列的表

     QString cmd="create table if not exists ready( Pid  verchar(64) ,time int ,priority int, state verchar(64) )";

if(query.exec(cmd))

     {

          qDebug()<<"readyTable exce successful";

     }

//创建一个存储挂起队列的表

     QString cmd="create table if not exists putup( Pid  verchar(64) ,time int ,priority int, state verchar(64) )";

if(query.exec(cmd))

     {

          qDebug()<<"putupTable exce successful";

     }

//创建一个存储终止队列的表

     QString cmd="create table if not exists finish( Pid  verchar(64) ,time int ,priority int, state verchar(64) )";

if(query.exec(cmd))

     {

          qDebug()<<"finishTable exce successful";

     }

(2)、在UI界面当中用四个QTableView控件分别表示后备队列、就绪队列、挂起队 列、终止队列。

(3)、当进入界面时,数据库中后备队列数据表中的数据会显示在ui界面中表示后备 队列的QTableview的控件当中。

(4)、高级调度采用先到先服务的调度算法,摄制道数为5,当就绪队列中的进程数 少于道数且后备队列进程数不为0时,后备队列里的进程会进入就绪队列。

//设置道数为5,即就绪队列中最多储存5个数据

#define N 5

void Widget:: InsertIntoReadyqueue()

{

     while((readyQueue.size<N)&&(waitingQueue.size!=0))

        {

          PCB *p=new PCB();

          p->PID=waitingQueue.front->next->PID;

          p->priority=waitingQueue.front->next->priority;

          p->state=waitingQueue.front->next->state;

          p->time=waitingQueue.front->next->time;

          QString pid=p->PID;

          int time=p->time;

          int priority=p->priority;

          EnQueue(readyQueue,p->PID,p->time,p->priority,"ready");

          DeQueue(waitingQueue);

          EnRecord(model2,pid,time,priority,"ready");

          DeRecord(model);

        }

}

(5)、在UI中增加一个表示调度方式的QComboBox的复选框控件,可以选择优先 级调度、时间片轮转两种cpu调度方式,可以通过改变复选框的内容来实现中途 两种调度方式的自由转换。

(6)、在UI中增加一个表示高级调度是自动进行还是手动进行的QComboBox的复 选框控件,当选择自动进行的时候每两秒会执行一次调度过程,中途可以由手动 切换为手动,也可以由自动切换为手动。

void Widget::setValue()

{

     if(ui->autoComboBox->currentText()=="自动调度")

     {

         time->start(2000);

     }

     if(ui->autoComboBox->currentText()=="手动调度")

     {

        time->stop();

    }

}    

//每隔设定时间执行一次下一步操作

     connect(time,SIGNAL(timeout()),this,SLOT(on_nextPushButton_cl icked()));

     //当自动手动选择复选框内容改变的时候,改变自动手动方式

     connect(ui->autoComboBox,SIGNAL(currentTextChanged(QString)), this,SLOT(setValue()));

(7)、在UI中增加一个表示挂起和解挂的按钮,可以将就绪队列中选定的进程挂起到挂起队列,也可以将挂起队列的进程解挂到就绪队列当中。

(8)、在UI中增加一个表示添加进程的按钮,点击后进入添加进程的子界面,添加 时会对根据该添加的进程PID在数据库中挂起队列、后备队列、就绪队列的数据 表中,以及当前运行的进程中查找,如果该进程名已存在,会跳出提示框请求重 新添加

(9)、在UI中增加一个表示清空后备队列的按钮,点击后将会清空后备队列和表示

数据库中表示后备队列的数据表。

(10)、 在就绪队列下面设置一个按钮来记录该队列排序后的队首元素,将按钮设置 为不可见,当需要就绪队列进cpu时可以让该按钮变为可见,并设置动画效果使其 飞入cpu执行区。

//设置动画效果

void Widget::beginAnimation()

{

     p->raise();

     p->setVisible(true);

     animation->setPropertyName("geometry");

     animation->setDuration(1000);

     animation->setStartValue(QRect(470,330,300,50));

     animation->setEndValue(QRect(470,555,300,50));

     animation->start();

}

3、界面效果

五、实验代码

1、main.cpp主程序

#include "widget.h"

#include <QApplication>

#include <QDebug>

#include<QSqlError>

#include<QSqlQuery>

#include<QSqlQueryModel>

#include<QSqlTableModel>

int main(int argc, char *argv[])

{

    QApplication a(argc, argv);

    /**数据库部分

     *

    **/

    //指定数据库驱动名,增加数据库实例

    QSqlDatabase db=QSqlDatabase::addDatabase("QSQLITE");

    //设置数据库用户名

    db.setDatabaseName("user.db");

    if(!db.open())

    {

        qDebug()<<"连接失败,失败原因:"<<db.lastError().text();

    }

    else

    {

        qDebug()<<"连接成功";

    }

    //创建一个存储后备队列的表

    QString cmd="create table if not exists waiting( Pid verchar(64) ,time int ,priority int, state verchar(64) )";

    QSqlQuery query;

    if(query.exec(cmd))

    {

        qDebug()<<"waitingTable exce successful";

    }

  //创建一个存储ready队列的表

    cmd="create table if not exists ready( Pid verchar(64) ,time int ,priority int, state verchar(64) )";

    if(query.exec(cmd))

    {

        qDebug()<< "readyTable exce successful";

    }

    //创建一个存储完成队列的表

    cmd="create table if not exists finish( Pid verchar(64) ,time int ,priority int, state verchar(64) )";

    if(query.exec(cmd))

    {

        qDebug()<<"finishTable exce successful";

    }

    //创建一个挂起队列的表

    cmd="create table if not exists putup( Pid verchar(64) ,time int ,priority int, state verchar(64) )";

    if(query.exec(cmd))

    {

        qDebug()<<"putupTable exce successful";

    }    

    Widget  w;

    w.show();

    return a.exec();

}

  1. widget.h

//该文件表示主界面

#ifndef WIDGET_H

#define WIDGET_H

#include <QtSql/QSqlDatabase>

#include <QWidget>

#include <NewPcb.h>

#include<ui_Newpcb.h>

#include<QPaintEvent>

#include<QSqlTableModel>

#include<QStandardItemModel>

#include<QPropertyAnimation>

class NewPcb;

//定义结构体

typedef struct PCB{

QString PID;

//进程名

int time;

//要求运行时间,单位时间

QString state;

//状态

int priority;

//优先级

struct PCB *next;

//PCB指针

}PCB,*QueuePtr;

typedef struct {

  QueuePtr front;

  QueuePtr rear;

  int size;

}linkQueue;

namespace Ui {

class Widget;

}

class Widget : public QWidget

{

    Q_OBJECT

public:

    explicit Widget(QWidget *parent = 0);

    ~Widget();

private slots:

    void on_addPushButton_clicked();

    void on_beginPushButton_clicked();

    void on_putupPushButton_clicked();

    void on_nextPushButton_clicked();

    

    void on_pushButton_2_clicked();

    void on_releasePutupPushButton_clicked();

    void on_BeginPushButton_clicked();

    void setValue();

    void on_overPushButton_clicked();

    void on_clearPushButton_clicked();

private:

    Ui::Widget *ui;

    NewPcb *newPcb;

    PCB *running;

    QPushButton *p;

    QPropertyAnimation *animation;

    QSqlTableModel *model;//后备队列可视化模型

    QSqlTableModel *model2;//ready队列可视化模型

    QSqlTableModel *model3;//挂起队列可视化模型

    QSqlTableModel *model4;//完成队列可视化模型

    QTimer *time;

    void beginAnimation();

    void paintEvent(QPaintEvent *p1);

    void InsertIntoReadyqueue();

    void InsertIntoRunning();

    //对队列进行操作

    bool SeQueue(linkQueue &Q,QString pid);

    void initWaitingQueue(QSqlTableModel* model);

    void initReadyQueue(QSqlTableModel* model1,QSqlTableModel* model2);

    void initPutupQueue(QSqlTableModel* model);

    void initFinishQueue(QSqlTableModel*model);

    //对tableview同时也是对数据库进行处理

    void EnRecord(QSqlTableModel *model,QString pid,int time,int priority,QString state );

    void DeRecord(QSqlTableModel *model);

    void EnRecordFront(QSqlTableModel *model, QString pid, int time, int priority, QString state);

//    void priorityScheduling();//优先级调度算法

    //关于队列的基本操作,分别为初始化队列,增加节点,删除节点

    bool InitQueue(linkQueue &Q);

    bool EnQueue(linkQueue &Q,QString pid,int time,int priority,QString state);

    bool DeQueue(linkQueue &Q);

    bool EnQueueFront(linkQueue &Q,QString pid,int time,int priority,QString state);

    void sortReadyQueue();

//    bool SortQueue(linkQueue &Q);

};

#endif // WIDGET_H

  1. newPcb.h

//该文件表示新加进程界面

#ifndef NEWPCB_H

#define NEWPCB_H

#include <QWidget>

#include <widget.h>

#include<QPaintEvent>

class Widget;

namespace Ui {

class NewPcb;

}

class NewPcb : public QWidget

{

    Q_OBJECT

public:

    explicit NewPcb(QWidget *parent = 0);

    ~NewPcb();

    void setWidget(Widget *widget);

    Widget *widget;

    Ui::NewPcb *ui;

private slots:

    void on_okPushButton_clicked();

    void on_returnPushButton_clicked();

private:

    void paintEvent(QPaintEvent *p1);

};

#endif // NEWPCB_H

  1. widget.cpp

//该文件表示主界面界面

#include "widget.h"

#include "ui_widget.h"

#include<QDebug>

#include<QSqlError>

#include<QSqlQuery>

#include<QSqlQueryModel>

#include<QSqlTableModel>

#include<QStyleOption>

#include<QPainter>

#include<QBitmap>

#include<QSqlRecord>

#include<QStandardItemModel>

#include<QTimer>

#include<QMessageBox>

//设置道数为5,即就绪队列中最多储存5个数据

#define N 5

//规定点击一次下一次后时间片减少多少

#define TIMESLICE 2

//规定点击一次下一次后优先级减少多少

//priority越大,优先级越高,越先执行

#define PRIORITYCHANGE 1

//进程状态枚举

enum STATE

{ WAITING,

    READY,

    RUNNING,

    BLOCK,

    FINISH

};

//初始化三个队列

linkQueue readyQueue;

linkQueue waitingQueue;

linkQueue putupQueue;

linkQueue finishQueue;

Widget::Widget(QWidget *parent) :

    QWidget(parent),

    ui(new Ui::Widget)

{

    time=new QTimer(this);

    //初始化动画

    p=new QPushButton(this);

    p->setGeometry(480,330,300,50);

    p->setVisible(false);

    const QString style={"QPushButton{color: #2f3640;background-color: #f5f6fa;border-radius: 15px;border-color: #2f3640;border-style: solid;border-width: 2px; padding: 5px;front:楷体    ;font-weight:bold ;}"};

    p->setStyleSheet(style);

    p->raise();

    animation=new QPropertyAnimation();

    animation->setTargetObject(p);

    animation->setEasingCurve(QEasingCurve::Linear);//设置动画效果

    //初始化当前运行进程指针

    running=new PCB();

    ui->setupUi(this);

    newPcb=new NewPcb();

    this->newPcb->setWidget(this);

    //创建后备队列对应的模型

    model=new QSqlTableModel(this);

    model->setTable("waiting");

    model->select();

    ui->waintingQueueView->setModel(model);

    initWaitingQueue(model);

    //创建ready队列对应的模型

    model2=new QSqlTableModel(this);

    model2->setTable("ready");

    model2->select();

    ui->readyQueueView->setModel(model2);

    initReadyQueue(model,model2);

    //创建挂起队列对应的模型

    model3=new QSqlTableModel(this);

    model3->setTable("putup");

    model3->select();

    ui->putupQueueView->setModel(model3);

    initPutupQueue(model3);

    

    //创建完成队列对应的模型

    model4=new QSqlTableModel(this);

    model4->setTable("finish");

    model4->select();

    ui->finishQueueView->setModel(model4);

    initFinishQueue(model4);

    ui->pidPushButton->setVisible(false);

    ui->timePushButton->setVisible(false);

    ui->priorityPushButton->setVisible(false);

    //往后备队列添加进程的时候同时判断几个队列是否含有该进程名,如果有返回给出警告

    connect(newPcb->ui->okPushButton,&QPushButton::clicked,[=](){

        QString pid=newPcb->ui->pidLineEdit->text();

        int priority=newPcb->ui->priorityComboBox->currentText().toInt();

        int time=newPcb->ui->timeLineEdit->text().toInt();

        if(SeQueue(waitingQueue,pid)||SeQueue(readyQueue,pid)||SeQueue(putupQueue,pid)||(running->PID==pid))

        {

            QMessageBox::warning(this,"警告","该进程名已存在,请重新输入","OK");

        }

        else {

            //添加数据库记录并同时对数据库进行修改

            EnRecord(model,pid,time,priority,"waiting");

            //对后备队列进行修改

            EnQueue(waitingQueue,pid,time,priority,"waiting");

            //如果就绪队列有位置,进入就绪队列

            InsertIntoReadyqueue();

        }

        newPcb->ui->pidLineEdit->clear();

        newPcb->ui->timeLineEdit->clear();

    });

    //每隔设定时间执行一次下一步操作

    connect(time,SIGNAL(timeout()),this,SLOT(on_nextPushButton_clicked()));

    //当自动手动选择复选框内容改变的时候,改变自动手动方式

    connect(ui->autoComboBox,SIGNAL(currentTextChanged(QString)),this,SLOT(setValue()));

}

Widget::~Widget()

{

    delete ui;

}

//该界面样式

void Widget::paintEvent(QPaintEvent *p1)

{

    //绘制样式

    QStyleOption opt;

    opt.initFrom(this);

    QPainter p(this);

    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);//绘制样式

    QBitmap bmp(this->size());

    bmp.fill();

    QPainter painter(&bmp);

    painter.setPen(Qt::NoPen);

    painter.setBrush(Qt::black);

    painter.setRenderHint(QPainter::Antialiasing);

    //painter.drawRoundedRect(bmp.rect(), 12, 12);

    setMask(bmp);

}

void Widget::on_addPushButton_clicked()

{

    this->newPcb->show();

    this->hide();

}

//初始化后备队列

void Widget:: initWaitingQueue(QSqlTableModel* model)

{

//  query.exec(QString("insert into cpuSchedule values('%1','%2','%3','%4')").arg("p5").arg(54).arg(32).arg("wainting"));

    //显示设置

    model->setHeaderData(0, Qt::Horizontal, "进程名称");

    model->setHeaderData(1, Qt::Horizontal, "所需时间");

    model->setHeaderData(2, Qt::Horizontal, "优先级");

    model->setHeaderData(3, Qt::Horizontal, "当前状态");

    ui->waintingQueueView->setColumnWidth(0, 124);

    ui->waintingQueueView->setColumnWidth(1, 124);

    ui->waintingQueueView->setColumnWidth(2, 124);

    ui->waintingQueueView->setColumnWidth(3, 0);

    QSqlQuery query("user.db");

    query.exec("select *from waiting");

    //创建空队列

    InitQueue(waitingQueue);

    //用数据库中的信息初始化tableview控件信息,初始化后备队列

    while(query.next()) {

        EnQueue(waitingQueue,query.value(0).toString(),query.value(1).toInt(),query.value(2).toInt(),query.value(3).toString());

        qDebug()<<query.value(0).toString()<<query.value(1).toInt();

    }

}

//初始化就绪队列

void Widget:: initReadyQueue(QSqlTableModel* model1,QSqlTableModel* model2)

{

    //显示设置

    model2->setHeaderData(0, Qt::Horizontal, "进程名称");

    model2->setHeaderData(1, Qt::Horizontal, "所需时间");

    model2->setHeaderData(2, Qt::Horizontal, "优先级");

    model2->setHeaderData(3, Qt::Horizontal, "当前状态");

    ui->readyQueueView->setColumnWidth(0, 124);

    ui->readyQueueView->setColumnWidth(1, 124);

    ui->readyQueueView->setColumnWidth(2, 124);

    ui->readyQueueView->setColumnWidth(3, 0);

    QSqlQuery query("user.db");

    query.exec("select *from ready");    

    //创建新队列

    InitQueue(readyQueue);

    InsertIntoReadyqueue();

}

//初始化挂起队列

void Widget:: initPutupQueue(QSqlTableModel* model){

    //显示设置

    model->setHeaderData(0, Qt::Horizontal, "进程名称");

    model->setHeaderData(1, Qt::Horizontal, "所需时间");

    model->setHeaderData(2, Qt::Horizontal, "优先级");

    model->setHeaderData(3, Qt::Horizontal, "当前状态");

    ui->putupQueueView->setColumnWidth(0, 124);

    ui->putupQueueView->setColumnWidth(1, 124);

    ui->putupQueueView->setColumnWidth(2, 124);

    ui->putupQueueView->setColumnWidth(3, 0);

    InitQueue(putupQueue);

}

//初始化终止队列

void Widget:: initFinishQueue(QSqlTableModel* model){

    //显示设置

    model->setHeaderData(0, Qt::Horizontal, "进程名称");

    model->setHeaderData(1, Qt::Horizontal, "所需时间");

    model->setHeaderData(2, Qt::Horizontal, "优先级");

    model->setHeaderData(3, Qt::Horizontal, "当前状态");

    ui->finishQueueView->setColumnWidth(0, 124);

    ui->finishQueueView->setColumnWidth(1, 124);

    ui->finishQueueView->setColumnWidth(2, 124);

    ui->finishQueueView->setColumnWidth(3, 0);

    InitQueue(finishQueue);

}

/**

 * 对队列数据结构进行操作

 *

 * */

bool Widget:: InitQueue(linkQueue &Q)

//构建一个空队列

{   Q.front=(QueuePtr) malloc((sizeof(PCB)));

    Q.rear=Q.front;

    //头指针和尾指针均指向头节点

    if(!Q.front)

    {

        qDebug()<<"分配空间出现错误";

        return false;

    }

    Q.size=0;

    Q.front->next=NULL;

    return true;

}

//从队列尾部添加元素

bool Widget:: EnQueue(linkQueue &Q,QString pid,int time,int priority,QString state)

{

    QueuePtr p =new PCB;

    if(!p)

    {

        qDebug()<<"分配空间出现错误";

        return false;

    }

    p->PID=pid;

    p->time=time;//正确

    p->priority=priority;//错误

    p->state=state;

    qDebug()<<"添加链表元素"<<p->PID<<p->time<<p->priority<<p->state;

    p->next=NULL;

    Q.rear->next=p;

    Q.rear=p;

    Q.size++;

    return 0;

}

//从队列头部添加元素

bool Widget::EnQueueFront(linkQueue &Q,QString pid,int time,int priority,QString state)

{

    if(Q.size==0)

     {

        EnQueue(Q,pid,time,priority,state);

        return true;

    }

    else{

        QueuePtr p =new PCB;

        if(!p)

        {

            qDebug()<<"分配空间出现错误";

            return false;

        }

        p->PID=pid;

        p->time=time;

        p->priority=priority;

        p->state=state;

        qDebug()<<"向链表头部添加元素"<<p->PID<<p->time<<p->priority<<p->state;

        p->next=Q.front->next;

        Q.front->next=p;

        Q.size++;

        return true;

    }

}

bool Widget::DeQueue(linkQueue &Q)

{

    //若队列不空,则删除队头元素,返回true;否则返回false

    if(Q.size==0)

    {

        QMessageBox::information(this,tr("注意"),tr("该队列为空"));

        return false;

    }

    PCB *p=Q.front->next;

    Q.front->next=p->next;

    if(Q.rear==p)

    //即如果同时指向头节点

    Q.rear=Q.front;

    Q.size--;

    free(p);

    return true;

}

bool Widget::SeQueue(linkQueue &Q,QString pid)

{

    PCB *p=new PCB;

    p=Q.front->next;

    while (p!=NULL) {

       if(p->PID==pid)

           return true;

       p=p->next;

    }

    return false;

}

/**

 *对图表进行改变

 */

void Widget::EnRecord(QSqlTableModel *model,QString pid,int time,int priority,QString state ){

    //添加数据库记录并同时对数据库进行修改

    QSqlRecord record = model->record() ; //获取空记录

    int row = model->rowCount() ; //获取行数,该数字便是需要插入的行,因为行数不从0开始,而插入的行又得从0开始

    record.setValue(0,pid);

    record.setValue(1,time);

    record.setValue(2,priority);

    record.setValue(3,state);

    model->insertRecord(row,record);

}

void Widget::EnRecordFront(QSqlTableModel *model,QString pid,int time,int priority,QString state ){

        QSqlRecord record = model->record() ; //获取空记录

        record.setValue(0,pid);

        record.setValue(1,time);

        record.setValue(2,priority);

        record.setValue(3,state);

        model->insertRecord(0,record);

}

void Widget::DeRecord(QSqlTableModel *model){

   if((model->rowCount())>=1)

      {

         model->removeRow(0);

         model->select();

      }

}

/**

  *一些按钮的槽函数

  *

  *

**/

//当点击挂起按钮的时候

void Widget::on_putupPushButton_clicked()

{

    qDebug()<<"在此处挂起";

    //获取ready表格选中的行

    int cursor=ui->readyQueueView->currentIndex().row();

    //获取选中该行信息

    QModelIndexList list=ui->readyQueueView->selectionModel()->selectedIndexes();

    //在挂起图表中增加一行,同时在挂起队列添加一个节点

    EnRecord(model3,list[0].data().toString(),list[1].data().toInt(),list[2].data().toInt(),"putup");

    EnQueue (putupQueue,list[0].data().toString(),list[1].data().toInt(),list[2].data().toInt(),"putup");

    //ready队列当中删除该行

    model2->removeRow(cursor);

    model2->select();

    //对下面的数据进行排序

    QSqlQuery query;

    if(query.exec("select *from ready order by PID DESC "))

    //初始化ready队列

    qDebug()<<"在此处初始化队列";

    InitQueue(readyQueue);

    while(query.next()) {

        qDebug()<<query.value(0).toString()<<query.value(1).toInt();

        EnQueue (readyQueue,query.value(0).toString(),query.value(1).toInt(),query.value(2).toInt(),"putup");

    }

    qDebug()<<readyQueue.size<<waitingQueue.size;

    InsertIntoReadyqueue();

}

//解除挂起的时候

void Widget::on_releasePutupPushButton_clicked()

{

    qDebug()<<"执行开始挂起";

    //获取选中的行

    int cursor=ui->putupQueueView->currentIndex().row();

    //获取选中内容

    QModelIndexList list=ui->putupQueueView->selectionModel()->selectedIndexes();

    //在waiting图表头部增加一条记录

    EnRecordFront(model,list[0].data().toString(),list[1].data().toInt(),list[2].data().toInt(),"waiting");

    EnQueueFront(waitingQueue,list[0].data().toString(),list[1].data().toInt(),list[2].data().toInt(),"waiting");

    //从挂起队列当中删除该条记录

    model3->removeRow(cursor);

    model3->select();

    InsertIntoReadyqueue();

}

void Widget::on_overPushButton_clicked()

{

    this->close();

}

//清空后备队列

void Widget::on_clearPushButton_clicked()

{

    //将后备队列的数据库清空

    QString cmd="delete from waiting";

    //执行sql语句

    QSqlQuery query;

    if(query.exec(cmd))

    {

        qDebug()<<"waiting数据库清空 清空 successful";

    }

    initWaitingQueue(model);

    model->select();

}

/**

  *

  *

  **/

//将ready队列和模型按照优先级进行排序

void Widget::sortReadyQueue()

{

    //按照优先级队列进行排序

    model2->setSort(2, Qt::DescendingOrder);

    model2->select();

    QSqlQuery query;

    if(query.exec("select *from ready order by priority DESC "))

        qDebug()<<"laaaaa";

    //初始化ready队列

    InitQueue(readyQueue);

    while(query.next()) {

        qDebug()<<query.value(0).toString()<<query.value(1).toInt();

        EnQueue(readyQueue,query.value(0).toString(),query.value(1).toInt(),query.value(2).toInt(),"ready");

    }

}

//从就绪队列中选取队首元素进入cpu执行,就绪队列减少一条数据

void Widget::InsertIntoRunning()

{

    PCB *p1=new PCB;

    p1->PID=readyQueue.front->next->PID;

    p1->time=readyQueue.front->next->time;

    p1->priority=readyQueue.front->next->priority;

    p1->state=readyQueue.front->next->state;

    running=p1;

    QString pid2=running->PID;

    int time2=running->time;

    int priority2=running->priority;

    QString time2_0=tr("%1").arg(time2);

    QString priority2_0=tr("%1").arg(priority2);

    ui->pidPushButton->setText(pid2);

    ui->timePushButton->setText(time2_0);

    ui->priorityPushButton->setText(priority2_0);

    p->setText(pid2+"           "+time2_0+"           "+priority2_0);

    beginAnimation();

    DeQueue(readyQueue);

    DeRecord(model2);

}

void Widget:: InsertIntoReadyqueue()

{

    while((readyQueue.size<N)&&(waitingQueue.size!=0))

    {

          PCB *p=new PCB();

//          p=waitingQueue.front->next;//获取waiting队列队首元素

          p->PID=waitingQueue.front->next->PID;

          p->priority=waitingQueue.front->next->priority;

          p->state=waitingQueue.front->next->state;

          p->time=waitingQueue.front->next->time;

          QString pid=p->PID;

          int time=p->time;

          int priority=p->priority;

          EnQueue(readyQueue,p->PID,p->time,p->priority,"ready");

          DeQueue(waitingQueue);

          EnRecord(model2,pid,time,priority,"ready");

          DeRecord(model);

    }

}

void Widget::on_nextPushButton_clicked()

{   //保证在空队列中增加元素时能够继续启动

    InsertIntoReadyqueue();

    if(ui->schedulingComboBox->currentText()=="优先级调度")

    {

        if(running->PID==""&&readyQueue.size>0)

        {

            sortReadyQueue();

            //就绪队列进cpu

            InsertIntoRunning();

            //后备队列进入就绪队列

            InsertIntoReadyqueue();

            //就绪队列进行排序

            sortReadyQueue();

            //进行抢占

            if(readyQueue.size>0&&running->priority<readyQueue.front->next->priority&&running!=NULL&&readyQueue.size>0)

            {

                 PCB*p=new PCB;

                 p=running;

                 //将就绪队列队首元素调进CPU执行

                 InsertIntoRunning();

                 //将原cPu执行元素调到就绪队列队首

                 EnQueueFront(readyQueue,p->PID,p->time,p->priority,"ready");

                 //在ready队列视图加入该元素

                 EnRecordFront(model2,p->PID,p->time,p->priority,"ready");

            }

            return;

        }

        if (running->PID!="") {

           sortReadyQueue();

           //进行抢占,运行期间在就绪队列中增加高优先级进程,应立即进入running队列

           if(running->PID!=""&&readyQueue.size>0&&running->priority<readyQueue.front->next->priority)

           {

                PCB*p=new PCB;

                p=running;

                //将就绪队列队首元素调进CPU执行

                InsertIntoRunning();

                //将原cPu执行元素调到就绪队列队首

                EnQueueFront(readyQueue,p->PID,p->time,p->priority,"ready");

                //在waiting队列视图加入该元素

                EnRecordFront(model2,p->PID,p->time,p->priority,"ready");

                sortReadyQueue();

           }

           //所需运行时间减少

           running->time= running->time-TIMESLICE;

           running->priority=running->priority-PRIORITYCHANGE;

           int time1=running->time;

           int priority1=running->priority;

           QString time1_0=tr("%1").arg(time1);

           QString priority1_0=tr("%1").arg(priority1);

           ui->priorityPushButton->setText(priority1_0);

           ui->timePushButton->setText(time1_0);

           p->setText(running->PID+"           "+time1_0+"           "+priority1_0);

           if(running->time<=0)

           {

             //在终止队列里添加元素

             EnQueue(finishQueue,running->PID,0,running->priority,"finish");

             //在终止队列视图中添加元素

             EnRecord(model4,running->PID,0,running->priority,"finish");

             running->PID="";

             ui->priorityPushButton->setText("");

             ui->timePushButton->setText("");

             ui->pidPushButton->setText("");

             p->setText("");

             if(readyQueue.size>0)

             {

                 sortReadyQueue();

                 //从就绪队列中选取第一条数据插入

                 InsertIntoRunning();

                 //从后备队列里选取一条数据插入就绪队列

                 InsertIntoReadyqueue();

                 //将就绪队列和就绪视图进行排序

                 sortReadyQueue();

             }

           }

           //进行抢占,如果运行完优先级低于就绪队列队首,将其置于后备队列

           if(running->PID!=""&&readyQueue.size>0&&running->priority<readyQueue.front->next->priority)

           {

                PCB*p=new PCB;

                p=running;

                //将就绪队列队首元素调进CPU执行

                InsertIntoRunning();

                //将原cPu执行元素调到就绪队列队首

                EnQueueFront(readyQueue,p->PID,p->time,p->priority,"ready");

                //在waiting队列视图加入该元素

                EnRecordFront(model2,p->PID,p->time,p->priority,"ready");

                sortReadyQueue();

           }

           return;

        }

        //即当后备队列和就绪队列均为空的时候

        if(running->PID==""&&readyQueue.size==0)

        {

            return;

        }

    }

    if(ui->schedulingComboBox->currentText()=="时间片调度")

    {

        if(running->PID==""&&readyQueue.size>0)

        {

            InsertIntoRunning();

            InsertIntoReadyqueue();

            return;

        }

        if(running->PID!="")

        {

            running->time=running->time-TIMESLICE;

            int time1=running->time;

            int priority1=running->priority;

            QString pid1=running->PID;

            QString time1_0=tr("%1").arg(time1);

            QString priority1_0=tr("%1").arg(priority1);

            ui->priorityPushButton->setText(priority1_0);

            ui->timePushButton->setText(time1_0);

            p->setText(running->PID+"           "+time1_0+"           "+priority1_0);

            if(running->time<=0)

            {

                //在终止队列里添加元素

                EnQueue(finishQueue,running->PID,0,running->priority,"finish");

                //在终止队列视图中添加元素

                EnRecord(model4,running->PID,0,running->priority,"finish");

                running->PID="";

                ui->priorityPushButton->setText("");

                ui->timePushButton->setText("");

                ui->pidPushButton->setText("");

                p->setText("");

                if(readyQueue.size>0)

                {

                    qDebug()<<"readyQueue.size"<<readyQueue.size;

                    //从就绪队列中选取第一条数据插入

                    InsertIntoRunning();

                    //从waiting队列里选取一条数据插入就绪队列

                    InsertIntoReadyqueue();

                }

                else{

                    return;

                }

                return;

            }

            else if(running->time>0&&readyQueue.size>0) {

                InsertIntoRunning();

                qDebug()<<"执行完InsertIntoRunning()";

                EnRecord(model2,pid1,time1,priority1,"ready");

                EnQueue(readyQueue,pid1,time1,priority1,"ready");

                return;

            }

            //即running.time>0而且就绪队列为空

            else {

                return;

            }

        }

    }

}

//在这里进行更换手动还是自动进行处理机调度

void Widget::setValue()

{

    if(ui->autoComboBox->currentText()=="自动调度")

    {

        time->start(2000);

    }

    if(ui->autoComboBox->currentText()=="手动调度")

    {

        time->stop();

    }

}

//设置动画效果

void Widget::beginAnimation()

{

    p->raise();

    p->setVisible(true);

    animation->setPropertyName("geometry");

    animation->setDuration(1000);

    animation->setStartValue(QRect(470,330,300,50));

    animation->setEndValue(QRect(470,555,300,50));

    animation->start();

}

  1. newPcb.cpp

//该文件表示新加进程界面

#include "newpcb.h"

#include "ui_newpcb.h"

#include<QStyleOption>

#include<QPainter>

#include<QBitmap>

NewPcb::NewPcb(QWidget *parent) :

    QWidget(parent),

    ui(new Ui::NewPcb)

{

    ui->setupUi(this);

//  widget=new Widget();这样有问题

    //隐藏标题栏

    setWindowFlags(Qt::FramelessWindowHint);//无边框 置顶

    //设置样式

    this->setStyleSheet("#Widget{background-color: rgba(255, 0, 0, 150);}");

}

void NewPcb::paintEvent(QPaintEvent *p1)

{

    //绘制样式

    QStyleOption opt;

    opt.initFrom(this);

    QPainter p(this);

    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);//绘制样式

    QBitmap bmp(this->size());

    bmp.fill();

    QPainter painter(&bmp);

    painter.setPen(Qt::NoPen);

    painter.setBrush(Qt::black);

    painter.setRenderHint(QPainter::Antialiasing);

    painter.drawRoundedRect(bmp.rect(), 12, 12);

    setMask(bmp);

}

NewPcb::~NewPcb()

{

    delete ui;

}

void NewPcb::on_okPushButton_clicked()

{

    this->widget->show();

    this->hide();

}

void NewPcb::on_returnPushButton_clicked()

{

    this->widget->show();

    this->hide();

}

void NewPcb::setWidget(Widget *widget)

{

    this->widget=widget;

}

六、实验结论

   在动态优先级调度算法当中可以让优先级高的首先得到执行,规定正在执行的进程,其优先权将随着执行时间的增加而逐渐降低,使其优先权可能不再是最高,从而暂停其执行,将处理器回收并分配给其他优先权更高的进程。这种方式能防止个别长期进程长期占用处理器的现象。但也会存在无穷等待的问题,可以用老化来解决。

在时间片轮转法,每次调度时把CPU分配给队首进程,让其执行一个时间片,当时间片用完,由计时器发出时钟中断,调度程序则暂停该进程的执行,使其退出处理器,并将它送到就绪队列的末尾,等待下一轮调度执行。然后,把CPU分配给就绪队列中新的队首进程,同时也让它执行一个时间片。这样就可以保证就绪队列中的所有进程,在一定的时间(可接受的等待时间)内,均能获得一个时间片的执行时间。但时间片的选择很重要

七、实验小结

  1. 该实验满足了实验要求中的所有内容,采用图形化界面,并加入了一些动画效果,使cpu调度过程看起来更加直观,引入数据库,可以保存上一次运行时未完成、挂起以及后备队列里的的进程,使其不会丢失,并且可以通过navicat对数据库进行可视化管理,方便使用。
  2. 通过这次试验,由于使用的是队列的数据结构,以前并不是很熟悉,通过这次的实验, 让我对队列的使用和指针的认识更加深刻;也让我对数据库的增删查改的使用更加熟 练,提高了我的编程能力
  3. 通过这次实验让我对处理机调度有了更加直观的认识,也让我意识到了优先级调度和时间片  轮转两种调度方式的各自优缺点,加深了解处理机调度的工作过程。
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值