操作系统实验二 Allocation & Reclaim

实验二  Allocation & Reclaim

实验《Allocation & Reclaim》

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


一、实验目的

帮助了解在不同的存储管理方式下,应怎样实现主存空间的分配和回收。

二、实验内容

主存储器空间的分配和回收

在可变分区管理方式下,采用最先适应算法实现主存空间的分配和回收。

三、实验方法

1、内存分配:当单块空闲内存足以为为即将加入就绪队列的进程分配空间时,设置最 先适应算法,最优适应算法、最差适应算法来进行内存分配;当单块内存不足以为进程 分配内存而空闲内存总和大于进程所需内存时利用紧缩算法;当进程所需内存大于空闲 内存总和时,将该进程加入后备队列队尾,然后对接下来的进程进行判断。

2、内存回收:进程完成后,回收主存,并与相邻空闲分区合并。

四、实验步骤

概要设计

1、数据结构及符号说明

(1)、对于未分分区表中的记录用结构体来表示

typedef struct Partition{

//起始地址

int addressMemory;

//地址长度

int size;

//分区状态

QString state;

QString PID=" ";

}Partition;

 (2)、用一个QList的对象来存储记录,表示未分分区表

 (3)、用“未分”来表示空闲分区,用“已分”来表示被进程所占用的分区,用“固定分配来表示被“操作系统所占用的分区”

2、对pcb的内容进行扩充并对数据库进行修改

3、绘制仪表盘来表示内存所占情况百分比

4、绘制未分分区表的UI界面

5、实现内存分配的三种算法以及紧缩算法

6、实现内存回收以及相邻空闲分区的合并

详细设计

1、pcb中加入requiredMemory,memoryAddress两项内容。

typedef struct PCB{

QString PID;

//进程名

int time;

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

QString state;

//状态

int priority;

//优先级

struct PCB *next;

//PCB指针

int requiredMemory=-1;

int memoryAddress=-1;

}PCB,*QueuePtr;

2、封装一个passrate来表示仪表盘,在主函数中创建一个仪表盘对象对内存所占百分比进行显示。

passrate=new Passrate(this);

passrate->setGeometry(925,400,200,200);

passrate->updateValue(20,getRange());

passrate->show();

3、UI界面显示上用每一行来表示一个分区,分别用三种颜色来代表“已分”,“未分”,“固定分配”三种状态,用一个固定值乘以该分区的大小来设置该单元行的高度,这样能够使效果看起来更加直观,设置一个下拉框来选择相应分配算法。

ui->memoryTableView->verticalHeader()->resizeSection(i,(list[i]->size)*12);

4、当单块空闲内存足以为为即将加入就绪队列的进程分配空间时,设置最 先适应算法,最优适应算法、最差适应算法来进行内存分配;当单块内存不足以为进程 分配内存而空闲内存总和大于进程所需内存时利用紧缩算法;当进程所需内存大于空闲 内存总和时,将该进程加入后备队列队尾,然后对接下来的进程进行判断。

5、进程完成后,回收主存,如果该分区的相邻分区为空闲分区,则将其进行合并。

五、实验代码

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();

}

2、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

3、passrate.h

#ifndef PASSRATE_H

#define PASSRATE_H

#include <QWidget>

#include <QtGlobal>

#include <QPainter>

#include <QPaintEvent>

#include <QPen>

#include<cmath>

#include<QLabel>

namespace Ui {

class Passrate;

}

class Passrate : public QWidget

{

    Q_OBJECT

public:

    explicit Passrate(QWidget *parent = 0);

    ~Passrate();

    void paintEvent(QPaintEvent *event);//重绘事件

    void updateValue(float value,float range);//更新展示的值,触发事件重绘

    void drawLines(QPainter *painter);//绘制最外围的线

    void drawBGE(QPainter *painter);//绘制中间最外层背景

    void drawTextE(QPainter *painter);//绘制中心文字背景

    void drawText(QPainter *painter);//绘制中心文字

    void drawCircleOut(QPainter *painter);

    void drawPointer(QPainter *painter);//绘制指针

    int getValue() const;

private:

    Ui::Passrate *ui;

    int lineCount;  //总的最外层线的条数

    int value;      //值

    int textSize;   //文本大小

    int bgERadius;  //背景直径

    int radius0;

    int radius1; //最外圈的刻度线对应直径

    int radius2; //短线内圈刻度线对应直径

    int radius3; //长线内圈刻度线对应直径

    int textOutRadius; //文本背景外层直径

    int textInnRadius; //文本背景内存直径

    float  range;

};

#endif // PASSRATE_H

4、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>

#include<passrate.h>

class NewPcb;

//定义结构体

typedef struct PCB{

QString PID;

//进程名

int time;

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

QString state;

//状态

int priority;

//优先级

struct PCB *next;

//PCB指针

int requiredMemory=-1;

int memoryAddress=-1;

}PCB,*QueuePtr;

typedef struct Partition{

//起始地址

int addressMemory;

//地址长度

int size;

//分区状态

QString state;

QString PID=" ";

}Partition;

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_putupPushButton_clicked();

    void on_nextPushButton_clicked();

    void on_releasePutupPushButton_clicked();

    void setValue();

    void on_overPushButton_clicked();

    void on_clearPushButton_clicked();

private:

    Ui::Widget *ui;

    NewPcb *newPcb;

    PCB *running;

    QPushButton *p;

    //内存占用扇形

    Passrate* passrate;

    QPropertyAnimation *animation;

    QStandardItemModel* partitionModel;

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

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

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

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

    QTimer *time;

    void paintEvent(QPaintEvent*);

    void beginAnimation();

    void InsertIntoReadyqueue();

    void InsertIntoRunning();

    //对队列进行操作

    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,int requiredMemory,int memoryAddress );

    void DeRecord(QSqlTableModel *model);

    void reRecord(QSqlTableModel *model,int frontAddress,int backAddress);

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

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

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

    bool InitQueue(linkQueue &Q);

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

    bool DeQueue(linkQueue &Q);

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

    void sortReadyQueue();

    bool SeQueue(linkQueue &Q,QString pid);

    bool reQueueByAddress(linkQueue &Q,int frontAddress,int backAddress);

//    bool SortQueue(linkQueue &Q);

    //判断是否就绪队列中所有的进程是否都不能调入内存

    bool isAllCanEntry();

    //用数组刷新QTableview

    void refreshTable(QList<Partition*>list,QStandardItemModel* model);

    //求出未分分区表中单块最大内存大小

    int getMaxOfSingleSize(QList<Partition*>list);

    //求和未分分区表中所有内存内存

    int getSumOfAllSize(QList<Partition*>list);

    //获取对应所占内存

    int getSumOfAllBusySize();

    //获取对应角度

    int getRange();

    //三种分配算法

    int getIndexOfFirstFit(int size);

    int getIndexOfBestFit(int size);

    int getIndexOfWorstFit(int size);

    void printPartition();

};

#endif // WIDGET_H

5、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;

}

  1. passrate.cpp

#include "passrate.h"

#include "ui_passrate.h"

#include<QLabel>

Passrate::Passrate(QWidget *parent) :

    QWidget(parent),

    ui(new Ui::Passrate)

{

    //初始化一些基本数据

    ui->setupUi(this);

    //对应100条刻度线

    lineCount = 100;

    value = 100;

    bgERadius = 30;

    textSize = 16;

    radius0=  80;

    radius1 = 70;

    radius2 = 60;

    radius3 = 50;

    bgERadius = 45;

    textOutRadius = 30;

    textInnRadius = 20;

    //初始化指针转动角度

    range=0;

}

Passrate::~Passrate()

{

    delete ui;

}

void Passrate::paintEvent(QPaintEvent *event){//界面绘制事件

    int width = this->width();

    int height = this->height();

    int side = qMin(width, height);

    QPainter painter(this);

    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);//设置渲染,启动反锯齿

    painter.translate(width / 2, height / 2);//平移坐标系到窗口正中央

    painter.scale(side / 200.0, side / 200.0);//绘制的图片对窗口进行自适应

    drawCircleOut(&painter);

    drawBGE(&painter); //画背景圆

    drawTextE(&painter);//画文字所在圆弧

    drawText(&painter);//画文字

    drawLines(&painter);//画最外部的线

    drawPointer(&painter);//绘制指针

}

void Passrate::updateValue(float value,float range){//提供给外部的方法,用于更新value

    this->value = value;

    this->range = range;

    update();//每次更新value后,都重绘界面

}

//在这里对外侧100条线进行设置

void Passrate::drawLines(QPainter* painter){

    painter->save();

    QPen pen;

    pen.setColor(QColor("#A2E2B4"));

    pen.setWidth(2);

    painter->setPen(pen);

    float range = 270.0/lineCount; //自定义所有的线加起来占270度,100条线

    painter->rotate(135);//旋转135度,开始画线,总共画270度。

    //在这里设置短刻度线

    QLine line1(QPoint(radius2,0),QPoint(radius1,0));//按照坐标从radius1到radius2

    QLine line2(QPoint(radius3,0),QPoint(radius1,0));//按照坐标从radius1到radius3

    for(int i = 0;i<=lineCount;i++){

        QPen pen;

        pen.setWidth(2);

        if(i>20&&i<=value){

        pen.setColor(QColor("#98ACD9"));

        painter->setPen(pen);

        }

        if(i>90&&i<=value){

            pen.setColor(QColor("#6ED8E1"));

            painter->setPen(pen);

        }

        if(i>value){//把应该不显示的部分变成灰色(按照中间的百分比数)

            pen.setColor(QColor("#D7D7D7"));

            painter->setPen(pen);

        }

        if(i==0||i==10||i==20||i==30||i==40||i==50||i==60||i==70||i==80||i==90||i==100)

        painter->drawLine(line2);

        else

        painter->drawLine(line1);

        painter->rotate(range);

    }

    painter->restore();

}

void Passrate::drawBGE(QPainter* painter){

    painter->save();

    painter->setPen(Qt::NoPen);

    painter->setBrush(QColor("#EAEAEA"));

    QRect rect(-bgERadius,-bgERadius,bgERadius*2,bgERadius*2);

    painter->drawEllipse(rect);//画出背景圆(灰色)

    painter->restore();

}

void Passrate::drawTextE(QPainter* painter){

    painter->save();

    painter->setPen(Qt::NoPen);

    painter->setBrush(QColor("#6FD6FF"));//画出中间的蓝色圆环

    QPainterPath path;

    QRect rectOut(-textOutRadius,-textOutRadius,textOutRadius*2,textOutRadius*2);

    path.arcTo(rectOut,0,360);//画出圆环外围

    QPainterPath subPath;

    QRect rectInn(-textInnRadius,-textInnRadius,textInnRadius*2,textInnRadius*2);

    subPath.addEllipse(rectInn);//内芯

    //做出里面的圆环

    path -= subPath;

    painter->drawPath(path);

    QPainterPath path1;

    painter->setBrush(QColor("#98ACD9"));

    QRect rectOut1(-10,-10,20,20);

    path1.arcTo(rectOut1,0,360);//画出圆环外围

    painter->drawPath(path1);

    painter->restore();

}

void Passrate::drawText(QPainter* painter){

    painter->save();

    painter->setPen(QColor("#000000"));

    QRect rectInn(-20,40,40,40);

    QFont font = painter->font();

    font.setPixelSize(textSize);//设置字体大小

    font.setFamily("Microsoft YaHei");

    painter->setFont(font);

    painter->drawText(rectInn,Qt::AlignCenter,QString::number(value)+"%");

    painter->restore();

}

void Passrate::drawCircleOut(QPainter *painter)

{

    painter->save();

    painter->setPen(Qt::NoPen);

    painter->setBrush(QColor("#98ACD9"));//画出中间的蓝色圆环

    QPainterPath path1;

    QRect rectOut1(-radius0,-radius0,radius0*2,radius0*2);

    path1.arcTo(rectOut1,-45,270);//画出仪表盘圆环外围

    QPainterPath path2;

    QRect rectOut2(-radius1,-radius1,radius1*2,radius1*2);

    path2.arcTo(rectOut2,-45,270);//画出仪表盘圆环内围

    QPainterPath path3;

    path3=path1-path2;

    painter->drawPath(path3);

    painter->restore();

}

//绘制仪表盘指针

void Passrate::drawPointer(QPainter *painter)

{

    painter->save();

    painter->setPen(Qt::NoPen);

    painter->setBrush(QColor("#98ACD9"));

    //先设置一个多边形

    QPolygon poly;

    poly.setPoints(3,-5,0,5,0,0,radius2);

    painter->rotate(range);

    painter->drawConvexPolygon(poly);

}

int Passrate::getValue() const

{

    return value;

}

  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>

#include"dashboard.h"

#include"passrate.h"

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

#define N 5

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

#define TIMESLICE 2

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

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

#define PRIORITYCHANGE 1

#define NOTSELECTED "#6ED8E1";

#define SELECTED "#98ACD9";

//进程状态枚举

enum STATE

{ WAITING,

    READY,

    RUNNING,

    BLOCK,

    FINISH

};

//初始化三个队列

linkQueue readyQueue;

linkQueue waitingQueue;

linkQueue putupQueue;

linkQueue finishQueue;

QList<Partition*>partitionQueue;

Widget::Widget(QWidget *parent) :

    QWidget(parent),

    ui(new Ui::Widget)

{

    //创建三种颜色对应的标志

    QLabel *lablep1=new QLabel(this);

    lablep1->setText("OS操作系统");

    lablep1->setGeometry(1480,640,90,18);

    QLabel *lablep2=new QLabel(this);

    lablep2->setText("未分分区");

    lablep2->setGeometry(1480,670,90,15);

    QLabel *lablep3=new QLabel(this);

    lablep3->setText("已分分区");

    lablep3->setGeometry(1480,700,90,15);

    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);

    //初始化未分分区表

    ui->memoryTableView->verticalHeader()->setMinimumSectionSize(12);

    partitionModel=new QStandardItemModel(1,4,this);

    partitionModel->setHeaderData(0, Qt::Horizontal, "PID");

    partitionModel->setHeaderData(1, Qt::Horizontal, "起址");

    partitionModel->setHeaderData(2, Qt::Horizontal, "长度");

    partitionModel->setHeaderData(3, Qt::Horizontal, "状态");

    ui->memoryTableView->setModel(partitionModel);

    ui->memoryTableView->setColumnWidth(0,85);

    ui->memoryTableView->setColumnWidth(1,85);

    ui->memoryTableView->setColumnWidth(2,85);

    ui->memoryTableView->setColumnWidth(3,85);

    Partition *partition=new Partition;

    partition->addressMemory=0;

    partition->size=20;

    partition->state="固定分配";

    partition->PID="OS操作系统";

    partitionQueue.append(partition);

    Partition *partition1=new Partition;

    partition1->addressMemory=20;

    partition1->size=80;

    partition1->state="未分";

    partitionQueue.append(partition1);

    refreshTable(partitionQueue,partitionModel);

    //创建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);

    //初始化内存占用情况

    passrate=new Passrate(this);

    passrate->setGeometry(925,400,200,200);

    passrate->updateValue(20,getRange());

    passrate->show();

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

    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();

        int requiredMemory=newPcb->ui->requiredMemoryLineEdit->text().toInt();

        if(requiredMemory>80)

        {

            QMessageBox::warning(this,"警告","该所需内存过大,请重新输入","OK");

        }

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

        {

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

        }

        else {

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

            EnRecord(model,pid,time,priority,"waiting",requiredMemory,-1);

            //对后备队列进行修改

            EnQueue(waitingQueue,pid,time,priority,"waiting",requiredMemory,-1);

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

            InsertIntoReadyqueue();

        }

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

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

        newPcb->ui->requiredMemoryLineEdit->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)

{

//    //设置主界面背景

//    QPainter painter1(this);

//    QPixmap  pix;

//    pix.load(":/a.jpg");

//    painter1.drawPixmap(0,0,this->width(),this->height(),pix);

//    //绘制样式

//    QStyleOption opt;

//    opt.initFrom(this);

//    QPainter p(this);

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

//    //设置边角样式

//    QBitmap bmp(this->size());

//    bmp.fill();

//    QPainter painter2(&bmp);

//    painter2.setPen(Qt::NoPen);

//    painter2.setBrush(Qt::black);

//    painter2.setRenderHint(QPainter::Antialiasing);

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

//    setMask(bmp);

    QPainter paint(this);

    //操作系统对应颜色圆

    paint.setPen(QPen(QColor("#A2E2B4"),Qt::SolidLine));

    paint.setBrush(QBrush(QColor("#A2E2B4")));

    paint.drawEllipse(1450,640,15,15);

    //未分分区对应颜色圆

    paint.setPen(QPen(QColor("#6ED8E1"),Qt::SolidLine));

    paint.setBrush(QBrush(QColor("#6ED8E1")));

    paint.drawEllipse(1450,670,15,15);

    //已分分区对应颜色圆

    paint.setPen(QPen(QColor("#98ACD9"),Qt::SolidLine));

    paint.setBrush(QBrush(QColor("#98ACD9")));

    paint.drawEllipse(1450,700,15,15);

}

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, "当前状态");

    model->setHeaderData(4, Qt::Horizontal, "所需内存");

    model->setHeaderData(5, Qt::Horizontal, "起始地址");

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

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

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

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

    ui->waintingQueueView->setColumnWidth(4, 85);

    ui->waintingQueueView->setColumnWidth(5, 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(),query.value(4).toInt(),query.value(5).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, "当前状态");

    model2->setHeaderData(4, Qt::Horizontal, "所需内存");

    model2->setHeaderData(5, Qt::Horizontal, "起始地址");

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

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

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

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

    ui->readyQueueView->setColumnWidth(4, 80);

    ui->readyQueueView->setColumnWidth(5, 80);

    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, "当前状态");

    model->setHeaderData(4, Qt::Horizontal, "所需内存");

    model->setHeaderData(5, Qt::Horizontal, "起始地址");

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

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

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

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

    ui->putupQueueView->setColumnWidth(4, 80);

    ui->putupQueueView->setColumnWidth(5, 80);

    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, "当前状态");

    model->setHeaderData(4, Qt::Horizontal, "所需内存");

    model->setHeaderData(5, Qt::Horizontal, "起始地址");

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

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

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

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

    ui->finishQueueView->setColumnWidth(4, 90);

    ui->finishQueueView->setColumnWidth(5, 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,int requiredMemory,int memoryAddress)

{

    QueuePtr p =new PCB;

    if(!p)

    {

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

        return false;

    }

    p->PID=pid;

    p->time=time;//正确

    p->priority=priority;//错误

    p->state=state;

    p->requiredMemory=requiredMemory;

    p->memoryAddress=memoryAddress;

    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,int requiredMemory,int memoryAddress)

{

    if(Q.size==0)

     {

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

        return true;

    }

    else{

        QueuePtr p =new PCB;

        if(!p)

        {

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

            return false;

        }

        p->PID=pid;

        p->time=time;

        p->priority=priority;

        p->state=state;

        p->requiredMemory=requiredMemory;

        p->memoryAddress=memoryAddress;

        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;

}

bool Widget::reQueueByAddress(linkQueue &Q,int frontAddress,int backAddress)

{

    PCB *p=new PCB;

    p=Q.front->next;

    while (p!=NULL) {

       if(p->memoryAddress==frontAddress)

          {

            p->memoryAddress=backAddress;

            return true;

       }

       p=p->next;

    }

    return false;

}

/**

 *对图表进行改变

 */

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

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

    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);

    record.setValue(4,requiredMemory);

    record.setValue(5,memoryAddress);

    model->insertRecord(row,record);

}

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

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

        record.setValue(0,pid);

        record.setValue(1,time);

        record.setValue(2,priority);

        record.setValue(3,state);

        record.setValue(4,requiredMemory);

        record.setValue(5,memoryAddress);

        model->insertRecord(0,record);

}

void Widget::DeRecord(QSqlTableModel *model){

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

      {

         model->removeRow(0);

         model->select();

      }

}

void Widget::reRecord(QSqlTableModel *model,int frontAddress,int backAddress)

{

    for(int i=0;i<model->rowCount();i++)

    {

        if(model->record(i).value(5)==frontAddress)

        {

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

            record.setValue(5,backAddress);

            model->removeRow(i);

            model->select();

            model->insertRecord(i,record);

        }

    }

}

/**

  *一些按钮的槽函数

  *

  *

**/

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

void Widget::on_putupPushButton_clicked()

{

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

    //获取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",list[4].data().toInt(),-1);

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

    //删去该进程的内存

    int m;

    //如果回收区前后都没有相邻的空闲区域则flag不变,此时只需要对该回收区进行修改

    int flag=0;

    //查找该块分区所对应的下标

    for(int i=0;i<partitionQueue.size();i++)

    {

        if(partitionQueue[i]->addressMemory==list[5].data().toInt())

        {

            m=i;

            break;

        }

    }

    //如果回收区的后面有一个相邻的空闲分区

    if(partitionQueue.size()>=m+2&&partitionQueue[m+1]->state=="未分")

    {

        partitionQueue[m]->size+=partitionQueue[m+1]->size;

        partitionQueue[m]->state="未分";

        partitionQueue[m]->PID=" ";

        partitionQueue.removeOne(partitionQueue[m+1]);

        flag=1;

        refreshTable(partitionQueue,partitionModel);

        ui->showLabel->setText("内存单元合并!");

    }

    //如果回收区的前面有一个相邻的空闲分区

    if(m>0&&partitionQueue[m-1]->state=="未分")

    {

        partitionQueue[m-1]->size+=partitionQueue[m]->size;

        partitionQueue.removeOne(partitionQueue[m]);

        flag=1;

        refreshTable(partitionQueue,partitionModel);

        ui->showLabel->setText("内存单元合并!");

    }

    //如果该回收区前后都没有相邻空闲分区,则无需合并

    if(flag==0)

    {

        partitionQueue[m]->state="未分";

        partitionQueue[m]->PID=" ";

        refreshTable(partitionQueue,partitionModel);

    }

    //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()) {

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

    }

    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",list[4].data().toInt(),list[5].data().toInt());

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

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

    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()<<" ";

    //初始化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",query.value(4).toInt(),query.value(5).toInt());

    }

}

//从就绪队列中选取队首元素进入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;

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

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

    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)&&isAllCanEntry())

    {refreshTable(partitionQueue,partitionModel);

          //获取waiting队列队首元素refreshTable(partitionQueue,partitionModel);

          PCB *p=new PCB();refreshTable(partitionQueue,partitionModel);refreshTable(partitionQueue,partitionModel);refreshTable(partitionQueue,partitionModel);

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

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

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

          p->memoryAddress=waitingQueue.front->next->memoryAddress;//为空

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

          if(p->requiredMemory>getSumOfAllSize(partitionQueue))

          {

              ui->showLabel->setText("内存不足");

              qDebug()<<"目前后备队列队首元素的进程大小大于该内存剩余大小";

              //将队首元素移到队尾

              DeQueue(waitingQueue);

              DeRecord(model);

              EnQueue(waitingQueue,p->PID,p->time,p->priority,p->state,p->requiredMemory,p->memoryAddress);

              EnRecord(model,p->PID,p->time,p->priority,p->state,p->requiredMemory,p->memoryAddress);

              //终止该次循环

              continue;

          }

          //判断单个分区是否可以容纳该进程

          if(p->requiredMemory<=getMaxOfSingleSize(partitionQueue))

          {

              qDebug()<<"执行一次"<<p->requiredMemory<<getMaxOfSingleSize(partitionQueue);

              Partition*partition=new Partition;

              if(ui->allocationComboBox->currentText()=="最先适应分配")

              {

                int index=getIndexOfFirstFit(p->requiredMemory);

                if(p->requiredMemory==partitionQueue[index]->size)

                {

                    qDebug()<<"刚好相等";

                    partitionQueue[index]->state="已分";

                    partitionQueue[index]->PID=p->PID;

                    refreshTable(partitionQueue,partitionModel);

                    p->memoryAddress=partitionQueue[index]->addressMemory;

                }

                else

                {

                    partition->addressMemory=partitionQueue[index]->addressMemory;

                    partition->size=p->requiredMemory;

                    partition->PID=p->PID;

                    partition->state="已分";

                    p->memoryAddress=partitionQueue[index]->addressMemory;

                    partitionQueue[index]->addressMemory=partitionQueue[index]->addressMemory+p->requiredMemory;

                    partitionQueue[index]->size=partitionQueue[index]->size-p->requiredMemory;

                    partitionQueue.insert(index,partition);

                    refreshTable(partitionQueue,partitionModel);

                }

              }

              if(ui->allocationComboBox->currentText()=="最优适应分配")

              {

                    int index=getIndexOfBestFit(p->requiredMemory);

                    if(p->requiredMemory==partitionQueue[index]->size)

                    {

                        partitionQueue[index]->state="已分";

                        partitionQueue[index]->PID=p->PID;

                        refreshTable(partitionQueue,partitionModel);

                        p->memoryAddress=partitionQueue[index]->addressMemory;

                    }

                    else

                    {

                        partition->addressMemory=partitionQueue[index]->addressMemory;

                        partition->size=p->requiredMemory;

                        partition->PID=p->PID;

                        partition->state="已分";

                        p->memoryAddress=partitionQueue[index]->addressMemory;

                        partitionQueue[index]->addressMemory=partitionQueue[index]->addressMemory+p->requiredMemory;

                        partitionQueue[index]->size=partitionQueue[index]->size-p->requiredMemory;

                        partitionQueue.insert(index,partition);

                        refreshTable(partitionQueue,partitionModel);

                    }

              }

              if(ui->allocationComboBox->currentText()=="最差适应分配")

              {

                  int index=getIndexOfWorstFit(p->requiredMemory);

                  if(p->requiredMemory==partitionQueue[index]->size)

                  {

                      partitionQueue[index]->state="已分";

                      partitionQueue[index]->PID=p->PID;

                      refreshTable(partitionQueue,partitionModel);

                      p->memoryAddress=partitionQueue[index]->addressMemory;

                  }

                  else

                  {

                      partition->addressMemory=partitionQueue[index]->addressMemory;

                      partition->size=p->requiredMemory;

                      partition->PID=p->PID;

                      partition->state="已分";

                      p->memoryAddress=partitionQueue[index]->addressMemory;

                      partitionQueue[index]->addressMemory=partitionQueue[index]->addressMemory+p->requiredMemory;

                      partitionQueue[index]->size=partitionQueue[index]->size-p->requiredMemory;

                      partitionQueue.insert(index,partition);

                      refreshTable(partitionQueue,partitionModel);

                  }

              }

          }

          //若单个分区不可以容纳该进程而空闲分区总和足够容纳该进程,采用紧缩技术

          if(p->requiredMemory>getMaxOfSingleSize(partitionQueue)&&p->requiredMemory<=getSumOfAllSize(partitionQueue))

          {

              ui->showLabel->setText("发生紧缩!");

              QList<Partition*> tempQueue;

              tempQueue.append(partitionQueue[0]);

              int addressBegin=20;

              for(int i=1;i<partitionQueue.size();i++)

              {

                  if(partitionQueue[i]->state=="已分")

                  {

                      //对ready队列或者running队列中的pcb信息进行修改

                      if(running->memoryAddress==partitionQueue[i]->addressMemory)

                      {

                          running->memoryAddress=addressBegin;

                          qDebug()<<"当前running队列为"<<running->PID<<running->memoryAddress<<running->requiredMemory;

                      }

                      else {

                         reQueueByAddress(readyQueue,partitionQueue[i]->addressMemory,addressBegin);

                         reRecord(model2,partitionQueue[i]->addressMemory,addressBegin);

                      }

                      partitionQueue[i]->addressMemory=addressBegin;

                      addressBegin+=partitionQueue[i]->size;

                      tempQueue.append(partitionQueue[i]);

                  }

              }

              //在末尾加上一个合并后的空闲分区;

              Partition *partition=new Partition;

              partition->addressMemory=addressBegin;

              partition->size=100-addressBegin;

              partition->state="未分";

              partition->PID=" ";

              if(p->requiredMemory==partition->size)

              {

                  //对相应的PCB进行修改

                  p->memoryAddress=addressBegin;

                  qDebug()<<"合并内存正好够";

                  //对未分分区表进行修改

                  partition->state="已分";

                  partition->PID=p->PID;

                  tempQueue.append(partition);

              }

              else {

                  //对相应的PCB进行修改

                  p->memoryAddress=addressBegin;

                  qDebug()<<"p->requiredMemory"<<p->requiredMemory<<"partition->size"<<partition->size;

                  qDebug()<<"合并内存不够";

                  //对未分分区表进行修改

                  Partition *partition1=new Partition;

                  partition1->size=p->requiredMemory;

                  partition1->PID=p->PID;

                  partition1->state="已分";

                  partition1->addressMemory=addressBegin;

                  tempQueue.append(partition1);

                  partition->addressMemory+=p->requiredMemory;

                  partition->size=100-partition->addressMemory;

                  partition->PID=" ";

                  partition->state="未分";

                  tempQueue.append(partition);

              }

              partitionQueue=tempQueue;

              printPartition();

              refreshTable(partitionQueue,partitionModel);

          }

          passrate->updateValue(getSumOfAllBusySize(),getRange());

          //waiting队列减少元素,ready队列增加元素

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

          DeQueue(waitingQueue);

          //做了修改

          EnRecord(model2,p->PID,p->time,p->priority,"ready",p->requiredMemory,p->memoryAddress);

          DeRecord(model);

          refreshTable(partitionQueue,partitionModel);

    }

}

void Widget::on_nextPushButton_clicked()

{   ui->showLabel->setText(" ");

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

    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",p->requiredMemory,p->memoryAddress);

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

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

            }

            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",p->requiredMemory,p->memoryAddress);

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

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

                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",running->requiredMemory,-1);

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

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

             int m;

             //如果回收区前后都没有相邻的空闲区域则flag不变,此时只需要对该回收区进行修改

             int flag=0;

             //查找该块分区所对应的下标

             for(int i=0;i<partitionQueue.size();i++)

             {

                 if(partitionQueue[i]->addressMemory==running->memoryAddress)

                 {

                     m=i;

                     break;

                 }

             }

             //如果回收区的后面有一个相邻的空闲分区

             if(partitionQueue.size()>=m+2&&partitionQueue[m+1]->state=="未分")

             {

                 partitionQueue[m]->size+=partitionQueue[m+1]->size;

                 partitionQueue[m]->state="未分";

                 partitionQueue[m]->PID=" ";

                 partitionQueue.removeOne(partitionQueue[m+1]);

                 flag=1;

                 refreshTable(partitionQueue,partitionModel);

                 passrate->updateValue(getSumOfAllBusySize(),getRange());

                 ui->showLabel->setText("内存单元合并!");

             }

             //如果回收区的前面有一个相邻的空闲分区

             if(m>0&&partitionQueue[m-1]->state=="未分")

             {

                 partitionQueue[m-1]->size+=partitionQueue[m]->size;

                 partitionQueue.removeOne(partitionQueue[m]);

                 flag=1;

                 refreshTable(partitionQueue,partitionModel);

                  passrate->updateValue(getSumOfAllBusySize(),getRange());

                  ui->showLabel->setText("内存单元合并!");

             }

             //如果该回收区前后都没有相邻空闲分区,则无需合并

             if(flag==0)

             {

                 partitionQueue[m]->state="未分";

                 partitionQueue[m]->PID=" ";

                 refreshTable(partitionQueue,partitionModel);

                 passrate->updateValue(getSumOfAllBusySize(),getRange());

             }

             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",p->requiredMemory,p->memoryAddress);

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

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

                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;

            int requiredMemory1=running->requiredMemory;

            int memoryAddress1=running->memoryAddress;

            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",running->requiredMemory,-1);

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

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

                int m;

                //如果回收区前后都没有相邻的空闲区域则flag不变,此时只需要对该回收区进行修改

                int flag=0;

                //查找该块分区所对应的下标

                for(int i=0;i<partitionQueue.size();i++)

                {

                    if(partitionQueue[i]->addressMemory==running->memoryAddress)

                    {

                        m=i;

                        break;

                    }

                }

                //如果回收区的后面有一个相邻的空闲分区

                if(partitionQueue.size()>=m+2&&partitionQueue[m+1]->state=="未分")

                {

                    partitionQueue[m]->size+=partitionQueue[m+1]->size;

                    partitionQueue[m]->state="未分";

                    partitionQueue[m]->PID=" ";

                    partitionQueue.removeOne(partitionQueue[m+1]);

                    flag=1;

                    refreshTable(partitionQueue,partitionModel);

                    qDebug()<<"总内存为              "<<getSumOfAllBusySize();

                    passrate->updateValue(getSumOfAllBusySize(),getRange());

                    ui->showLabel->setText("内存单元合并!");

                }

                //如果回收区的前面有一个相邻的空闲分区

                if(m>0&&partitionQueue[m-1]->state=="未分")

                {

                    partitionQueue[m-1]->size+=partitionQueue[m]->size;

                    partitionQueue.removeOne(partitionQueue[m]);

                    flag=1;

                    refreshTable(partitionQueue,partitionModel);

                   qDebug()<<"总内存为              "<<getSumOfAllBusySize();

                    passrate->updateValue(getSumOfAllBusySize(),getRange());

                    ui->showLabel->setText("内存单元合并!");

                }

                //如果该回收区前后都没有相邻空闲分区,则无需合并

                if(flag==0)

                {

                    partitionQueue[m]->state="未分";

                    partitionQueue[m]->PID=" ";

                    refreshTable(partitionQueue,partitionModel);

                    qDebug()<<"总内存为              "<<getSumOfAllBusySize();

                    passrate->updateValue(getSumOfAllBusySize(),getRange());

                }

                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",requiredMemory1,memoryAddress1);

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

                return;

            }

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

            else {

                return;

            }

        }

    }

  refreshTable(partitionQueue,partitionModel);

}

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

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();

}

//用数组初始化QTableview

void Widget::refreshTable(QList<Partition*>list,QStandardItemModel* model)

{

    model->removeRows(0,model->rowCount());

    for(int i=0;i<list.size();i++)

    {

        model->setItem(i,0,new QStandardItem(list[i]->PID));

        model->setItem(i,1,new QStandardItem(tr("%1").arg(list[i]->addressMemory)));

        model->setItem(i,2,new QStandardItem(tr("%1").arg(list[i]->size)));

        model->setItem(i,3,new QStandardItem(list[i]->state));

        ui->memoryTableView->verticalHeader()->resizeSection(i,(list[i]->size)*12);

        if(list[i]->state=="未分")

        {

            for (int j = 0; j < 4;j ++) {

                model->item(i,j)->setBackground(QColor("#6ED8E1"));

            }

        }

        else if(list[i]->state=="已分")

        {

            for (int j = 0; j < 4;j ++) {

                model->item(i,j)->setBackground(QColor("#98ACD9"));

            }

        }

        else if(list[i]->state=="固定分配")

        {

            for (int j = 0; j < 4;j ++) {

                model->item(i,j)->setBackground(QColor("#A2E2B4"));

            }

        }

    }

}

int Widget::getMaxOfSingleSize(QList<Partition*>list)

{

    int m=0;

    for(int i=0;i<list.size();i++)

    {

        if(list[i]->size>m&&list[i]->state=="未分")

           m=list[i]->size;

    }

    return m;

}

int Widget::getSumOfAllSize(QList<Partition*>list)

{

    int m=0;

    for(int i=0;i<list.size();i++)

    {

        if(list[i]->state=="未分")

          m+=list[i]->size;

    }

    return m;

}

int Widget::getSumOfAllBusySize()

{

    int m=0;

    for(int i=0;i<partitionQueue.size();i++)

    {

        if(partitionQueue[i]->state=="已分")

          m+=partitionQueue[i]->size;

    }

    m=m+20;

    return m;

}

int Widget::getRange()

{

    float m=45+getSumOfAllBusySize()*2.7;

    return m;

}

/**

 * @brief Widget::getIndexOfFirstFit

 * @return 最先适应分配算法

 */

int Widget::getIndexOfFirstFit(int size)

{

    //将未分区表按照地址由小到大排列

    for(int i=1;i<partitionQueue.size();i++)

    {

        if(partitionQueue[i-1]->addressMemory>partitionQueue[i]->addressMemory&&partitionQueue[i-1]->PID!="OS操作系统")

        {

            Partition *partition=new Partition;

            partition=partitionQueue[i-1];

            partitionQueue[i-1]=partitionQueue[i];

            partitionQueue[i]=partition;

        }

    }

    refreshTable(partitionQueue,partitionModel);

    printPartition();

    for(int i=0;i<partitionQueue.size();i++)

    {

        if(partitionQueue[i]->size>=size&&partitionQueue[i]->state=="未分")

        {

            return i;

        }

    }

}

/**

 * @brief Widget::getIndexOfFirstFit

 * @return 最优适应分配算法

 */

int Widget::getIndexOfBestFit(int size)

{

    int index=0;

    int m;

    //将未分区表按照内存大小由小到大排列

    for(int i=1;i<partitionQueue.size();i++)

    {

        if(partitionQueue[i]->state=="未分"&&partitionQueue[i]->size>=size)

        {

            index=i;

            m=partitionQueue[i]->size;

            break;

        }

    }

    for(int i=1;i<partitionQueue.size();i++)

    {

        if(partitionQueue[i]->size<m&&partitionQueue[i]->state=="未分"&&partitionQueue[i]->size>=size)

        {

            index=i;

            m=partitionQueue[i]->size;

        }

    }

    return index;

}

/**

 * @brief Widget::getIndexOfFirstFit

 * @return 最差适应分配算法

 */

int Widget::getIndexOfWorstFit(int size)

{

    int index=0;

    int m=0;

    //将未分区表按照内存大小由小到大排列

    for(int i=1;i<partitionQueue.size();i++)

    {

        if(partitionQueue[i]->size>m&&partitionQueue[i]->state=="未分")

        {

            index=i;

            m=partitionQueue[i]->size;

        }

    }

    return index;

}

void Widget::printPartition()

{

    qDebug()<<"打印开始";

    for(int i=0;i<partitionQueue.size();i++)

    {

        qDebug()<<partitionQueue[i]->PID<<partitionQueue[i]->addressMemory<<partitionQueue[i]->size<<partitionQueue[i]->state;

    }

    qDebug()<<"打印结束";

}

 bool Widget:: isAllCanEntry()

 {

     PCB *p=new PCB;

     p=waitingQueue.front->next;

     while (p!=NULL) {

        if(p->requiredMemory<=getSumOfAllSize(partitionQueue))

           {

             return true;

             }

        p=p->next;

     }

     return false;

 }

六、实验结论

1、最先适应算法

原本状态为

 

点击下一步的时候,p7运行完,与下方的单元格进行合并,下一个进程将会进入内存, 该进程需要2个内存单元根据最先适应算法,它会进入第一个大小为4的空闲分区。

运行结果如下:

显然符合预期

2、最优适应算法

初始状态

点击下一步时P12释放内存空间,产生一个大小为2的空闲分区,p13进入内存,根据最优适应算法,p13将会进入刚产生的空闲分区。

运行结果如下:

 显然符合要求

3、最差适应算法

初始值

点击下一步时,p7释放内存空间,与下面的内存单元进行合并产生一个大小为50的空闲分区,p10进行内存,根据最坏适应算法,将会选择这个大小为50的空闲分区。

实验结果

显然符合要求

4、紧缩算法

初始状态

点击下一步之后p15释放内存空间,与下面的空闲分区进行合并,产生一个大小为49的空闲分区,而p16所需要的内存大小为58,显然此时单个分区不足以容纳该进程而空闲分区之和大于所需分区大小,此时会将所有的空闲内存紧缩在一起

实验结果如下

显然符合要求

实验结论:

        首次适应算法从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给作业,这种方法的目的在于减少查找时间。

        最佳适应算法从全部空闲区中找出能满足作业要求的,且大小最小的空闲分区,这种方法能使碎片尽量小。

        最差适应算法从全部空闲区中找出能满足作业要求的、且大小最大的空闲分区,从而使链表中的节点大小趋于均匀。

        三种适应算法每个都有自己独特的优点,当然与此相应的也有缺点,应该酌情处理

        通过内存合并可以一定的减少外碎片。通过紧缩算法,也可以在相应的情况下对外

碎片进行处理

七、实验小结

1、通过这一次实验让我对内存的分配和回收有了更加清楚的认识,由于这个实验是在原来的基础上进行的,工作量不是很大,相对完成比较轻松

2、在这次实验当中,创新性的加入了仪表盘,并对Qtableview相应的行进行颜色和高度的处理,这样能够使内存占用情况的显示以及分区状态看起来更加直观。

3、在这次实验中实现了三种分配算法,并写了紧缩算法,并对进行所需内存大于空闲分区内存总和的情况进行了考虑和处理,较为全面。

4、不足之处在于代码没有较好的实现封装的思想,看起来较为冗余,在编程的过程中会由于大于产生堆栈越界的情况,在之后会不断的规范自己的代码习惯,提高自己的编程能力。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值