操作系統實驗——動態分區分配方式的模擬


慕課指路:操作系統原理
超有意思一定要動手敲下試試的動態分區分配方式【滑稽】
代碼思路來源學校的慕課給出的代碼,自己敲了一遍進行了億點點改動
不過核心思路沒變,異常處理什么的沒有

一、實驗目的

了解動態分區分配方式中使用的數據結構和分配算法,並進一步加深對動態分區存儲管理方式及其實現過程的理解。

二、實驗要求

(1) 用C語言實現采用首次適應算法的動態分區分配過程alloc()和回收過程free()。空閑分區通過空閑分區鏈來管理;在進行內存分配時,系統優先使用空閑區低端的空間。
(2) 假設初始狀態下,可用的內存空間為640KB,並有下列的請求序列:

  • 作業1申請130KB

  • 作業2釋放60KB

  • 作業3申請100KB

  • 作業2釋放60KB

  • 作業4申請200KB

  • 作業3釋放100KB

  • 作業1釋放130KB

  • 作業5申請140KB

  • 作業6申請60KB

  • 作業7申請50KB

  • 作業6釋放60KB。

請采用首次適應算法進行內存塊的分配和回收,要求每次分配和回收后顯示出空閑內存分區鏈的情況。

三、實驗內容

1、數據結構

定義請求序列結構體,num代表作業號,state代表該作業申請還是釋放空間,len代表該做也申請或釋放空間的大小。

//定義請求序列結構體
struct Allocquery {
    int num;
    char state;  //a表示申請(apply),f表示釋放(free)
    int len;    //長度
    Allocquery(int n = 0, char s = 'f', int l = 0):num(n), state(s), len(l){}
} alocq[MaxNum];  

定義內存分配隊列結構體,flag為0時表示該內存塊空閑,為其他數值則表示相應作業。如為1則表示存儲的是作業1。firstadd表示該內存塊的首地址,len表示該內存塊的大小。

//定義內存分配隊列
struct Freequery {
    int flag;   //0表示空閑,其他數值表示相應作業
    int firstadd;   //起始地址
    int len;        //占有長度
    Freequery(int f = 0, int fi = 0, int l = 0) : flag(f), firstadd(fi), len(l) {}
} freeq[MaxNum];

2、初始化

從文件中讀取,in.txt內容為題意要求的作業請求隊列,1 a 130表示作業1申請130KB的空間

1 a 130

2 f 60

3 a 100

2 f 60

4 a 200

3 f 100

1 f 130

5 a 140

6 a 60

7 a 50

6 f 60

定義常量

const string InputFileName = "in.txt";
const string OutputFileName = "out.txt";
const int MaxNum = 11;

首先初始化作業請求序列,利用c++文件流,初始化每個作業請求。

//初始化作業請求序列
void initAlocq() {
    ifstream infp(InputFileName, ios::in);
    int index = 0;
    while(!infp.eof() && index < MaxNum) {
        int num;
        stringstream ss;
        infp >> alocq[index].num >> alocq[index].state >> alocq[index].len;
        ++index;
    }
    infp.close();
}

然后初始化內存空間,注意Freequery的構造函數中默認參數中len一開始都為0,也就是說len為0則這個內存塊不存在,可以作為循環結束的依據,所以一開始將freeq[0]的長度置為整個內存空間的長度。

void initFreeq() {
    freeq[0].flag = 0, freeq[0].firstadd = 0, freeq[0].len = 640;
}

3、主程序

對每次作業請求執行操作,並顯示執行結果在文件out.txt中。其中Freetotal表示內存空余塊的數量,一開始當然為1,first_alg為首次適應算法,參數為請求塊、當前空塊個數、內存分配隊列 。

void Run() {
    ofstream outfp(OutputFileName, ios::out);
    int Freetotal = 1;
    //對每次作業請求執行操作,顯示執行結果
    for(int i = 0; i < MaxNum; ++i ) {
        first_alg(alocq[i], Freetotal, freeq);
        outfp << "序列" << i+1 <<  ":作業" << alocq[i].num;
        if(alocq[i].state == 'a') outfp << "申請" << alocq[i].len << "K\n";
        else outfp << "釋放" << alocq[i].len << "K\n";
        outfp << "Now total free blocks:" << Freetotal << endl;
        outfp << "IDNum\taddress\t\tlength"<< endl;
        for(int j = 0 ; freeq[j].len != 0; ++j) {
            outfp << " " << freeq[j].flag << "\t\t "
                << freeq[j].firstadd << "\t\t "
                << freeq[j].len << endl;
        }
        outfp << "--------------------------------------------------\n" << endl;

    }
    outfp.close();
}
int main() {
    initAlocq();
    initFreeq();
    Run();
    return 0;
}

首次適應算法,參數為請求塊、當前空塊個數、內存分配隊列

函數聲明:

void first_alg(Allocquery nowaloc, int &ptotal, Freequery *pfreeq);

首先判斷是申請空間還是釋放空間,若為申請空間,遍歷所有內存塊。當且僅當該內存塊pfreeq[i]沒有被分配,且大小大於等於申請的空間量,將該塊分配給該作業,並將空塊合並,詳細的合並方法在注釋里都有體現。若為釋放空間,那就找到待釋放的塊將其釋放,並將釋放后空閑區合並。

//首次適應算法
//參數為請求塊、當前空塊個數、內存具體使用情況
void first_alg(Allocquery nowaloc, int &ptotal, Freequery *pfreeq){
    Freequery temp;
    Freequery temp_f1, temp_f2;
    if(nowaloc.state == 'a') {
        //申請空間
        for(int i = 0; i < MaxNum; ++i) {
            //該內存塊空閑 且空間足以分給該作業
            if(pfreeq[i].flag == 0 && pfreeq[i].len >= nowaloc.len) {
                temp.flag = pfreeq[i].flag;
                temp.firstadd = pfreeq[i].firstadd+nowaloc.len; //首地址下移
                temp.len = pfreeq[i].len-nowaloc.len;           //剩余空間長度
                //找到的空塊長度正好等於請求塊,則立刻分配
                pfreeq[i].flag = nowaloc.num;
                pfreeq[i].len = nowaloc.len;
                if(pfreeq[i+1].len == 0) {
                    //找到的空塊正好是全部剩余空間
                    pfreeq[i+1] = temp;
                } else if (pfreeq[i+1].firstadd != temp.firstadd){
                    //前后被占用,空塊在中間,且長度大於請求塊
                    temp_f1 = temp;
                    temp_f2 = pfreeq[i+1];
                    int j;
                    for(j = i+1; pfreeq[j].len != 0; ++j) {
                        pfreeq[j] = temp_f1;
                        temp_f1 = temp_f2;
                        temp_f2 = pfreeq[j+1];
                    }
                    pfreeq[j] = temp_f1;
                }
                break;
            }
        } 
    } else {
        //釋放空間
        for(int i = 0; i < MaxNum; ++i) {
            if(pfreeq[i].flag == nowaloc.num) {
                //找到待回收的塊
                if(i > 0 && pfreeq[i-1].flag == 0 && pfreeq[i+1].flag == 0) {
                    //前后都為空塊,且回收塊的首地址不是0
                    pfreeq[i-1].len = pfreeq[i-1].len + nowaloc.len + pfreeq[i+1].len;
                    for(int j = i; pfreeq[j].len != 0; ++j) {
                            //三塊合並后隊列變化
                        pfreeq[j] = pfreeq[j+2];
                    }
                } else if(i > 0 && pfreeq[i-1].flag == 0) {
                        //前為空塊,后不為空塊,且不是首塊
                        pfreeq[i-1].len = pfreeq[i-1].len + nowaloc.len;
                        for(int j = i; pfreeq[j].len != 0; ++j) {
                            //兩塊合並后隊列變化
                            pfreeq[j] = pfreeq[j+1];
                        }
                } else if(pfreeq[i+1].flag == 0) {
                    //后為空塊
                    pfreeq[i].flag = 0;
                    pfreeq[i].len = nowaloc.len + pfreeq[i+1].len;
                    for(int j = i+1; pfreeq[j].len != 0; ++j) {
                        pfreeq[j] = pfreeq[j+1];
                    }
                } else {
                    //前后都不空
                    pfreeq[i].flag = 0;
                }
            }
        }
    }
    int fnum = 0;   //統計空閑塊
    for(int i = 0; pfreeq[i].len != 0; ++i) 
        if(pfreeq[i].flag == 0) ++fnum;
    ptotal = fnum;
}

四、實驗結果

在這里插入圖片描述

五、完整代碼

#include <iostream>
#include <string>![在這里插入圖片描述](https://img-blog.csdnimg.cn/20210603201251414.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ1ODkwNTMz,size_16,color_FFFFFF,t_70)

#include <sstream>
#include <fstream>
using namespace std;
const string InputFileName = "in.txt";
const string OutputFileName = "out.txt";
const int MaxNum = 11;
//定義請求序列結構體
struct Allocquery {
    int num;
    char state;  //a表示申請(apply),f表示釋放(free)
    int len;    //長度
    Allocquery(int n = 0, char s = 'f', int l = 0):num(n), state(s), len(l){}
} alocq[MaxNum];  
//定義內存分配隊列
struct Freequery {
    int flag;   //0表示空閑,其他數值表示相應作業
    int firstadd;   //起始地址
    int len;        //占有長度
    Freequery(int f = 0, int fi = 0, int l = 0) : flag(f), firstadd(fi), len(l) {}
} freeq[MaxNum];

//首次適應算法
//參數為請求塊、當前空塊個數、內存分配隊列
void first_alg(Allocquery nowaloc, int &ptotal, Freequery *pfreeq);

//初始化作業請求序列
void initAlocq() {
    ifstream infp(InputFileName, ios::in);
    int index = 0;
    while(!infp.eof() && index < MaxNum) {
        int num;
        stringstream ss;
        infp >> alocq[index].num >> alocq[index].state >> alocq[index].len;
        //cout << alocq[index].num << ' ' << alocq[index].state << ' ' << alocq[index].len << endl;
        ++index;
    }
    infp.close();
}
//初始化內存空間
void initFreeq() {
    freeq[0].flag = 0, freeq[0].firstadd = 0, freeq[0].len = 640;
}
void Run() {
    ofstream outfp(OutputFileName, ios::out);
    int Freetotal = 1;
    //對每次作業請求執行操作,顯示執行結果
    for(int i = 0; i < MaxNum; ++i ) {
        first_alg(alocq[i], Freetotal, freeq);
        outfp << "序列" << i+1 <<  ":作業" << alocq[i].num;
        if(alocq[i].state == 'a') outfp << "申請" << alocq[i].len << "K\n";
        else outfp << "釋放" << alocq[i].len << "K\n";
        outfp << "Now total free blocks:" << Freetotal << endl;
        outfp << "IDNum\taddress\t\tlength"<< endl;
        for(int j = 0 ; freeq[j].len != 0; ++j) {
            outfp << " " << freeq[j].flag << "\t\t "
                << freeq[j].firstadd << "\t\t "
                << freeq[j].len << endl;
        }
        outfp << "--------------------------------------------------\n" << endl;

    }
    outfp.close();
}
int main() {
    initAlocq();
    initFreeq();
    Run();
    return 0;
}
//首次適應算法
//參數為請求塊、當前空塊個數、內存具體使用情況
void first_alg(Allocquery nowaloc, int &ptotal, Freequery *pfreeq){
    Freequery temp;
    Freequery temp_f1, temp_f2;
    if(nowaloc.state == 'a') {
        //申請空間
        for(int i = 0; i < MaxNum; ++i) {
            //該內存塊空閑 且空間足以分給該作業
            if(pfreeq[i].flag == 0 && pfreeq[i].len >= nowaloc.len) {
                temp.flag = pfreeq[i].flag;
                temp.firstadd = pfreeq[i].firstadd+nowaloc.len; //首地址下移
                temp.len = pfreeq[i].len-nowaloc.len;           //剩余空間長度
                //找到的空塊長度正好等於請求塊,則立刻分配
                pfreeq[i].flag = nowaloc.num;
                pfreeq[i].len = nowaloc.len;
                if(pfreeq[i+1].len == 0) {
                    //找到的空塊正好是全部剩余空間
                    pfreeq[i+1] = temp;
                } else if (pfreeq[i+1].firstadd != temp.firstadd){
                    //前后被占用,空塊在中間,且長度大於請求塊
                    temp_f1 = temp;
                    temp_f2 = pfreeq[i+1];
                    int j;
                    for(j = i+1; pfreeq[j].len != 0; ++j) {
                        pfreeq[j] = temp_f1;
                        temp_f1 = temp_f2;
                        temp_f2 = pfreeq[j+1];
                    }
                    pfreeq[j] = temp_f1;
                }
                break;
            }
        } 
    } else {
        //釋放空間
        for(int i = 0; i < MaxNum; ++i) {
            if(pfreeq[i].flag == nowaloc.num) {
                //找到待回收的塊
                if(i > 0 && pfreeq[i-1].flag == 0 && pfreeq[i+1].flag == 0) {
                    //前后都為空塊,且回收塊的首地址不是0
                    pfreeq[i-1].len = pfreeq[i-1].len + nowaloc.len + pfreeq[i+1].len;
                    for(int j = i; pfreeq[j].len != 0; ++j) {
                            //三塊合並后隊列變化
                        pfreeq[j] = pfreeq[j+2];
                    }
                } else if(i > 0 && pfreeq[i-1].flag == 0) {
                        //前為空塊,后不為空塊,且不是首塊
                        pfreeq[i-1].len = pfreeq[i-1].len + nowaloc.len;
                        for(int j = i; pfreeq[j].len != 0; ++j) {
                            //兩塊合並后隊列變化
                            pfreeq[j] = pfreeq[j+1];
                        }
                } else if(pfreeq[i+1].flag == 0) {
                    //后為空塊
                    pfreeq[i].flag = 0;
                    pfreeq[i].len = nowaloc.len + pfreeq[i+1].len;
                    for(int j = i+1; pfreeq[j].len != 0; ++j) {
                        pfreeq[j] = pfreeq[j+1];
                    }
                } else {
                    //前后都不空
                    pfreeq[i].flag = 0;
                }
            }
        }
    }
    int fnum = 0;   //統計空閑塊
    for(int i = 0; pfreeq[i].len != 0; ++i) 
        if(pfreeq[i].flag == 0) ++fnum;
    ptotal = fnum;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM