c從文件讀取數據,實現銀行家算法

銀行家算法

針對多類資源分配的情況,最著名的而是銀行家算法,銀行家算法的設計思想是:當用戶申請一組資源時,系統必須做出判斷;如果把這些資源分出去,系統是否還處於安全狀態。若是,就可以分出這些資源;否則,該申請暫不予滿足。
實現銀行家算法要有若干數據結構,用來表示資源分配系統的狀態。

  • 其中,n表示系統中進程的數目。M表示資源分類數。

  • Avaliable是一個長度爲m的向量,表示每一類資源可用的數量。Avaliable[j]=k,表示rj類資源可用的數量是k

  • Max是一個n*m矩陣,表示每個進程對資源的最大需求。Max[i,j]=k,表示進程pi至多課申請k個rj類資源單位

  • Allocation是一個n*m的矩陣,表示當前分給每個進程的資源數目,Allocation[i,j]=k,表示進程pi當前分到k個rj類資源

  • Need是一個n*m矩陣,他表示每個進程還缺少多少資源。Need[i,j]=k,表示進程pj尚需k個rj類資源才能完成其任務。顯然,Need[i,j]=Max[i,j]-Allocation[i,j]

  • Request 是一個n*m矩陣,i表示進程pi申請向量,Request[i][j]=k表示進程pi需要申請k個rj類資源

從文件讀取數據銀行家算法的驗證數據文件data格式說明

驗證數據:建立在程序目錄下建立data文件,文件內容是:
5 3
10 5 7
0 0 1 0 7 5 3
1 2 0 0 3 2 2
2 3 0 2 9 0 2
3 2 1 1 2 2 2
4 0 0 2 4 3 3

1 1 0 2
4 3 3 0
0 0 2 0
第一行:5個進程,3種資源。
第二行:每種資源系統擁有的最大數量。
3-7行:第一列是進程號(按順序排),2-4列是Request(資源請求)向量,5-7列是Max(最大資源需求量)向量。
8-10行:第一列是進程號,2-4列是Request(資源請求)向量。

運行程序,通過命令行參數指定文件,如: ./banker ./data運行。

代碼

/**
 * lzy
 */
#include <stdio.h>
#include <unistd.h>

#define maxNum 100
#define maxLineNum 100
// 定義一個文件指針全局變量
FILE *fpl;
// 定義一個儲存文件一行的數組
char line[maxLineNum];
//定義一個數組用來儲存提取的字符
int lineData[maxLineNum];
// 定義一個數組來保存進程名,如processBox[1] = 2表示下標爲1時,對應的進程名爲2
int processBox[maxNum];
// 安全性算法需要用到的Work,Finish數組
int Work[maxNum];
int Finish[maxNum];
// 定義進程數目,定義資源分類數
int n, m;
int Resource[maxNum] = {0};
int Available[maxNum] = {0};
int Max[100][maxNum] = {0};
int Allocation[maxNum][maxNum] = {0};
int Need[maxNum][maxNum] = {0};
int Request[maxNum][maxNum] = {0};
char firstLetter;

/**
 * 讀取line一行的數據到數組lineData中
 * @param num 提取個數
 */
void updateLineData(int num) {
    firstLetter = line[0];

    int nape;
    int cursor = 0;
    for (int i = 0; i < num; ++i) {
        nape = 0;
        while ((int) line[cursor] != 32 && (int) line[cursor] != 0 && (int) line[cursor] != 10) {
            nape = nape * 10 + (int) line[cursor] - 48;
            ++cursor;
        }

        ++cursor;
        lineData[i] = nape;
    }
}

/**
 * 初始化數據函數,
 * @param src ,目標文件目錄
 */
void lzyInitData(char *src) {
    // 1.初始化文件指針
    fpl = fopen(src, "r");
    if (fpl == NULL) {
        printf("lzy:文件讀取失敗,沒有這個文件");
        _exit(-1);
    }

    // 2.讀取文件,初始化各種全局變量
    // 2.1初始化n、m
    fgets(line, maxLineNum, fpl);
    updateLineData(2);
    n = lineData[0];
    m = lineData[1];



    // 2.2初始化Resource
    fgets(line, maxLineNum, fpl);
    updateLineData(m);
    for (int i = 0; i < m; ++i) {
        Resource[i] = lineData[i];
    }


    // 2.3初始化Allocation和Max,還有processBox
    for (int j = 0; j < n; ++j) {
        fgets(line, maxLineNum, fpl);
        updateLineData(1 + 2 * m);
        processBox[j] = lineData[0];
        for (int i = 0; i < m; ++i) {
            Allocation[lineData[0]][i] = lineData[i + 1];
            Max[lineData[0]][i] = lineData[i + m + 1];
        }
    }

    // 2.4初始化Available
    for (int i = 0; i < m; ++i) {
        int noAvailableNum = 0;
        for (int k = 0; k < n; ++k) {
            noAvailableNum += Allocation[processBox[k]][i];
        }
        Available[i] = Resource[i] - noAvailableNum;
    }


    // 2.4初始化Need
    for (int k = 0; k < maxNum; ++k) {
        for (int i = 0; i < maxNum; ++i) {
            Need[k][i] = Max[k][i] - Allocation[k][i];
        }
    }

    // 2.5初始化Request
    fgets(line, maxLineNum, fpl);
    updateLineData(1 + m);

    if (firstLetter == '\n') {
        fgets(line, maxLineNum, fpl);
        updateLineData(1 + m);
    }

    while (1) {
        for (int i = 0; i < m; ++i) {
            Request[lineData[0]][i] = lineData[i + 1];
        }
        if (!fgets(line, maxLineNum, fpl)) {
            break;
        }
        updateLineData(1 + m);
    }

    // 3.關閉文件流
    fclose(fpl);
}

/**
 * 檢測Request[process][i] 是否都小於Need[process][i],i=1,2,...,n
 * @param process
 * @return 結果 0:false 1:true
 */
int checkNeed(int process) {
    for (int i = 0; i < m; ++i) {
        if (Request[process][i] > Need[process][i]) return 0;
    }

    return 1;
}

/**
 * 檢查Request i 和 Available的大小
 * @param process
 * @return
 */
int checkAvailable(int process) {
    for (int i = 0; i < m; ++i) {
        if (Request[process][i] > Available[i]) return 0;
    }

    return 1;
}

/**
 * Available - Request[process][i]
 * @param process
 */
void availableSubRequestI(int process) {
    for (int i = 0; i < m; ++i) {
        Available[i] -= Request[process][i];
    }
}

/**
 * Available = Available + Request[process][i]
 * @param process
 */
void availableAddRequestI(int process) {
    for (int i = 0; i < m; ++i) {
        Available[i] += Request[process][i];
    }
}

/**
 * Allocation[process] =  Allocation[process] + Request[process
 * @param process
 */
void allocationAddRequest(int process) {
    for (int i = 0; i < m; ++i) {
        Allocation[process][i] += Request[process][i];
    }
}

/**
 * Allocation[process] =  Allocation[process] - Request[process
 * @param process
 */
void allocationSubRequest(int process) {
    for (int i = 0; i < m; ++i) {
        Allocation[process][i] -= Request[process][i];
    }
}

/**
 * Need[process] =  Need[process] - Request[process]
 * @param process
 */
void needSubRequest(int process) {
    for (int i = 0; i < m; ++i) {
        Need[process][i] -= Request[process][i];
    }
}


/**
 * Need[process] =  Need[process] + Request[process]
 * @param process
 */
void needAddRequest(int process) {
    for (int i = 0; i < m; ++i) {
        Need[process][i] += Request[process][i];
    }
}

/**
 * Work := Available
 */
void appendAvailableToWork() {
    for (int i = 0; i < m; ++i) {
        Work[i] = Available[i];
    }
}

/**
 * 重新初始化Finish
 */
void resetFinish() {
    for (int i = 0; i < maxNum; ++i) {
        Finish[i] = 0;
    }
}

/**
 * 判斷Need[process]中的每一項都小於等於Work[process]
 * @param process
 * @return
 */
int needSmallerOrEqualToWork(int process) {
    for (int i = 0; i < m; ++i) {
        if (Need[process][i] > Work[i]) {
            return 0;
        }
    }
    return 1;

}

/**
 * 搜尋滿足下列條件的i值:Finish[i]=false,且NeedI =< Work
 * @return 找不到,返回-1
 */
int searchIFinishEqualTo0AndNeedSmallerOrEqualToWork() {
    for (int i = 0; i < n; ++i) {
        if (Finish[processBox[i]] == 0 && needSmallerOrEqualToWork(processBox[i])) {
            return i;
        }
    }
    return -1;
}

/**
 * Work:=Work+Allocation
 * 回收資源
 * @param process
 */
void workAddAllocation(int process) {
    for (int i = 0; i < m; ++i) {
        Work[i] += Allocation[process][i];
    }
}

int FinishISAllTrue() {
    for (int i = 0; i < n; ++i) {
        if (!Finish[i]) {
            return 0;
        }
    }
    return 1;
}

int main(int argc, char *argv[]) {
    if (argc == 1) {
        printf("沒有輸入參數");
        _exit(0);
    }

    // 初始化數據
    lzyInitData(argv[1]);

    int isSafe = 0;
    for (int i = 0; i < n; ++i) {
        int isAllZero = 1;
        for (int j = 0; j < m; ++j) {
            if (Request[i][j] != 0) {
                isAllZero = 0;
                break;
            }
        }
        if (isAllZero) continue;

        // 一、若Request i > Need i表示出錯,因爲進程對資源的申請量大於它說明的最大值
        if (!checkNeed(processBox[i])) {
            printf("lzy:錯誤!因爲進程對資源的申請量大於它說明的最大值");
            _exit(-1);
        }

        // 二、若Request i > Available,則等待
        if (!checkAvailable(processBox[i])) {
            continue;
        }

        // 三、假設系統把申請的資源分給進程pi,則應對有關數據結構進行修改
        availableSubRequestI(processBox[i]);
        allocationAddRequest(processBox[i]);
        needSubRequest(processBox[i]);

        // 四、系統執行安全性算法,查看此時系統狀態是否安全,如果是安全的,就實際分配資源,
        //滿足進程p1的此次申請;否則,若新狀態是不安全的,則pi等待,對所申請資源暫不予分配,
        //並且把資源分配狀態恢復成三之前的情況
        // 四-1 令Work和Finish分別表示長度爲m,n的向量,最初,置Work := Available,
        // Finish[all]=false
        appendAvailableToWork();
        resetFinish();
        // 四-2 搜尋滿足下列條件的i值:Finish[i]=false,且NeedI =< Work。若沒有找到,則轉向4.
        int target = searchIFinishEqualTo0AndNeedSmallerOrEqualToWork();
        while (target != -1) {
            printf("進程%d的路徑可以爲:%d ->\n", processBox[i], processBox[target]);
            // 四-3 修改數據值:Work:=Work+Allocation(p1釋放所佔資源),Finish[i]=true
            workAddAllocation(processBox[target]);
            Finish[processBox[target]] = 1;
            target = searchIFinishEqualTo0AndNeedSmallerOrEqualToWork();
        }

        // 四-4 若Finish都爲true,則系統處於安全狀態,否則,系統處於不安全狀態,恢復三之前的情況
        availableAddRequestI(processBox[i]);
        allocationSubRequest(processBox[i]);
        needAddRequest(processBox[i]);

        if (!FinishISAllTrue()) {
            printf("lzy:進程%d處於不安全狀態!\n", processBox[i]);
            continue;
        } else {
            printf("lzy:處於安全狀態!");
            printf("進程%d處於安全狀態滿足申請!\n\n", processBox[i]);
            isSafe = 1;
        }
    }

    if (!isSafe) {
        printf("lzy:結果,無論怎麼樣,都處於不安全狀態!\n");
    }

    return 0;
}

運行結果(linux環境下)

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章