I. Demand analysis

1. Tasks and objectives of programming

Through this experiment, we can deepen the understanding of process deadlocks, and further master the allocation of process resources, deadlock detection and security sequence generation method.

2. Input form and input value range

Number of processes n, type of resources m, resource allocation of each process at time T0 (input can be run, can also be set in the program)

3. The form of output

If a secure process sequence is displayed, a message is displayed indicating that the process sequence is secure.

4. The functions that the program can achieve

The program simulates the working process of the banker algorithm to prevent process deadlocks. Suppose the system has n processes P1… ,Pn, there are m types of allocated resources R1… Rm, at time T0, the j resources allocated by process Pi are Allocationij, and it also needs J resources. Currently, there are Workj resources remaining in the system. Now the banker algorithm is used to allocate process resources to prevent deadlock.

5, test data, including correct input and output results and contains error input and output results

Correct use cases

The input

Enter the maximum allowed quantity of resource 1 of process 1 Max[1] : 7 Enter the maximum allowed quantity of resource 2 of process 1 Max[2] : 5 Enter the maximum allowed quantity of resource 3 of process 1 Max[3] : 3 Input the allocated amount of resource 1 for process 1 [1] : 0 Input the allocated amount of resource 2 for process 1 [2] : 1 Input the allocated amount of resource 3 for process 1 [3] : 0 Input the maximum allowed quantity of resource 1 in process 2 Max[1] : 3 Input the maximum allowed quantity of resource 2 in process 2 Max[2] : 2 Input the maximum allowed quantity of resource 3 in process 2 Max[3] : 2 Input the allocated quantity of resource 1 in process 2 [1] : 2 Input the allocated quantity of resource 2 in process 2. Allocation[2] : 0 Input the allocated quantity of resource 3 in process 2. Allocation[3] : 0 Input the maximum allowed quantity of resource 1 in process 3. Max[1] : 9 Input the maximum allowed quantity of resource 2 in process 3. 0 Input the maximum amount of resource 3 in process 3 Max[3] : 2 Input the allocated amount of resource 1 in process 3 [1] : 3 Input the allocated amount of resource 2 in process 3 [2] : 0 Input the allocated amount of resource 3 in process 3. Allocation[3] : 2 Input the maximum allowed amount of resource 1 in process 4. Max[1] : 2 Input the maximum allowed amount of resource 2 in process 4. 2 Please input the allocated quantity of resource 1 of process 4 to be allocated [1] : 2 Please input the allocated quantity of resource 2 of process 4 to be allocated [2] : 1 Please input the allocated quantity of resource 3 of process 4 to be allocated [3] : 1 Input the maximum allowed quantity of resource 1 of process 5 Max[1] : 4 Input the maximum allowed quantity of resource 2 of process 5 Max[2] : 3 Input the maximum allowed quantity of resource 3 of process 5 Max[3] : 3 Input the allocated quantity of resource 1 of process 5 [1] : 0 Input the allocated amount of resource 2 for process 5 Allocation[2] : 0 Input the allocated amount of resource 3 for process 5 Allocation[3] : 2 Input the available amount of resource 1:3 Input the available amount of resource 2:3 Input the available amount of resource 3:2Copy the code

The output

SafeOrder: Process 2 Process 4 Process 5 Process 1 Process 3 The remaining resources are as follows: Resource 1 Remaining quantity: 3 Resource 2 Remaining quantity: 3 Resource 3 Remaining quantity: 2 Check whether there are new requests. If yes, enter the process id. If no, enter 0. 2 Enter resource 1 required by process 2. 1 Enter resource 2 required by process 2. 0 Enter resource 3 required by process 2. 2 Remaining quantity of resource 2:3 Remaining quantity of resource 3:0Copy the code

Wrong use case (negative input affects correct results)

The input

N: 1 Type of resource M: 3 Maximum allowed quantity of resource 1 of process 1 Max[1] : 1 Maximum allowed quantity of resource 2 of process 1 Max[2] : 1 Maximum allowed quantity of resource 3 of process 1 Max[3] : 1 please enter the process of resource Allocation number of allocated 1 [1] : 1 please enter the number of allocated resources process 1 2 Allocation [2] : 1-1 please enter process of the number of allocated resources 3 Allocation [3] : 1, please input the number of available resources available 1: 2 Enter the number of available resources 2:2 Enter the number of available resources 3:2Copy the code

The output

SafeOrder: The remaining resources of process 1 are as follows: Resource 1 Remaining quantity: 2 Resource 2 Remaining quantity: 2 Resource 3 Remaining quantity: 2 Check whether there are new requests. If yes, enter the process id. If no, enter 0. 1 Enter the quantity of resource 1 required by process 1. 2 Enter the quantity of resource 2 required by process 1. 2 Enter the quantity of resource 3 required by process 1Copy the code

Second, outline design

Definition of abstract data types

int n;// Number of processes n
int m;// Resource type m
int Available[MaxNumber];// The number of available resources
int Request[MaxNumber];// Number of resources requested by the process
int SafeOrder[MaxNumber];// Security process sequence

// Define the data structure of the process
typedef struct {
    int Max[MaxNumber];
    int Allocation[MaxNumber];
    int Need[MaxNumber];
    bool Finished;// Complete state
} Progress;
Copy the code

2. The flow of the main program

int main(a) {
    BankerAlgorithm bankerAlgorithm{};
    bankerAlgorithm.Input();
    bankerAlgorithm.Order(bankerAlgorithm.progress, bankerAlgorithm.Available);

    return 0;
}
Copy the code

3. Hierarchical (call) relationship between each program module

int main(a) {
    BankerAlgorithm bankerAlgorithm{};
    bankerAlgorithm.Input();
    bankerAlgorithm.Order(bankerAlgorithm.progress, bankerAlgorithm.Available);

    return 0;
}

// The InputAlgorithm function is called to select the input function
void Input(a) {...}// Perform security process detection and output security sequence
void Order(Progress pg[MaxNumber], int a[MaxNumber]) {
    // Define the subscript
    int orderNum = 0;

    // Copy process operations
    Progress progressCopy[MaxNumber];
    for (int i = 1; i <= n; i++) {
        progressCopy[i] = pg[i];
    }

    // Copy the number of available requirements
    int available[MaxNumber];
    for (int i = 1; i <= m; i++) {
        available[i] = a[i];
    }

    // Call NewFinish to determine whether all processes are complete
    while(! NewFinish(progressCopy)) {// call the IsSafe function to determine if it IsSafe now
        if (IsSafe(progressCopy, available)) {
            for (int i = 1; i <= n; i++) {
                if(! progressCopy[i].Finished &&// Call the IsExecutable function to determine whether the process can satisfy the allotable resources
                    IsExecutable(progressCopy[i], available)) {
                    // Allocate only if both incomplete and assignable requirements of the process are satisfied...}}}else {
            cout << "Unsafe" << endl;
            exit(0); }}/ / output SafeOrder... NewRequest (pg, a); }// Determine whether there is a new request, if there is no exit, if there is a request to enter the number of resources
void NewRequest(Progress pg[MaxNumber], int a[MaxNumber]) {...// Output the number of remaining resources...// Determine the new request, if there are new requests available, call the Order function to re-perform the banker algorithm security calculation
    cout << endl << "Is there a new request? If yes, enter the process number. If no, enter 0:";
    cin >> newRequest;
    if(newRequest ! =0) {
        for (int i = 1; i <= m; i++) {
			// If the allocatable resource is insufficient or exceeds the requirement, the NewRequest function is called again
            NewRequest(pg, a);
        }
    	···
        Order(pg, a);
    } else {
        return; }}// Determine whether all processes are complete
bool NewFinish(Progress pg[MaxNumber]) {...}// Determine if allocatable resources can satisfy the process
bool IsExecutable(Progress pg, const int a[MaxNumber]) {...}// Determine if it is safe now
bool IsSafe(Progress pg[MaxNumber], int a[MaxNumber]) {...}Copy the code

Third, detailed design

Implement the specific algorithm of the program module

1, Order banker algorithm sort

// Perform security process detection and output security sequence
void Order(Progress pg[MaxNumber], int a[MaxNumber]) {
    // Define the subscript
    int orderNum = 0;

    // Copy process operations...// Copy the number of available requirements...// Call NewFinish to determine whether all processes are complete
    while(! NewFinish(progressCopy)) {// call the IsSafe function to determine if it IsSafe now
        if (IsSafe(progressCopy, available)) {
            for (int i = 1; i <= n; i++) {
                if(! progressCopy[i].Finished &&// Call the IsExecutable function to determine whether the process can satisfy the allotable resources
                    IsExecutable(progressCopy[i], available)) {
                    // Allocate only if both incomplete and assignable requirements of the process are satisfied...}}}else {
            cout << "Unsafe" << endl;
            exit(0); }}/ / output SafeOrder...// If the state is secure, call NewRequest again to request the next requirement input
    NewRequest(pg, a);
}
Copy the code

2. NewRequest initiates a NewRequest

// Determine whether there is a new request, if there is no exit, if there is a request to enter the number of resources
void NewRequest(Progress pg[MaxNumber], int a[MaxNumber]) {...// Output the number of remaining resources...// Determine the new request, if there are new requests available, call the Order function to re-perform the banker algorithm security calculation
    cout << endl << "Is there a new request? If yes, enter the process number. If no, enter 0:";
    cin >> newRequest;
    if(newRequest ! =0) {
        for (int i = 1; i <= m; i++) {
			// If the allocatable resource is insufficient or exceeds the requirement, the NewRequest function is called again
            NewRequest(pg, a);
        }
    	···
        Order(pg, a);
    } else {
        return; }}Copy the code

3. The NewFinish function determines that the process is complete

// Determine whether all processes are complete
bool NewFinish(Progress pg[MaxNumber]) {
    bool finished = true;
    for (int i = 1; i <= n; i++) {
        finished *= pg[i].Finished;
    }
    return finished;
}
Copy the code

The IsExecutable function determines whether resources are sufficient or not

// Determine if allocatable resources can satisfy the process
bool IsExecutable(Progress pg, const int a[MaxNumber]) {
    bool isExecutable = true;
    for (int i = 1; i <= m; i++) {
        isExecutable *= (pg.Need[i] <= a[i]);
    }
    return isExecutable;
}
Copy the code

5. The IsSafe function checks whether the current process IsSafe

// Determine if it is safe now
bool IsSafe(Progress pg[MaxNumber], int a[MaxNumber]) {
    bool isExecutable = false;
    for (int i = 1; i <= n; i++) {
        if (IsExecutable(pg[i], a)) {
            isExecutable = true;
            returnisExecutable; }}return isExecutable;
}
Copy the code

Four, debugging analysis

Problems encountered in the debugging process and solutions, design and implementation review and analysis

The performance analysis of the algorithm (including the time complexity and space complexity analysis of basic operations and other algorithms) and its improvement idea

Performance analysis

algorithm Time complexity Spatial complexity
Order algorithm security process detection T(n) = O(n2) S(n) = O(n)
The NewRequest algorithm requests resources T(n) = O(n2) S(n) = O(n2)
The NewFinish algorithm determines whether all processes are complete T(n) = O(n) S(n) = O(n)
The IsExecutable algorithm determines whether the process can be satisfied with the allocated resources T(n) = O(n) S(n) = O(n)
The IsSafe algorithm checks whether a process is in the secure state T(n) = O(n) S(n) = O(n)

Improve vision

The output is more complicated, more inconvenient to test, can be read file input instead

5. User instructions

Directions for use

  • The console will prompt the user to enter, as prompted to enter the content
  • Do not enter negative values, which will affect the correct results
  • When the selection algorithm input is complete, the secure process sequence is output
  • You can choose whether to use additional resource requests or exit as required

6. Test results

Test results, both input and output

D:\Documents\MyCourse\OperatingSystem\cmake-build-debug\chapter03.exe Please enter the number of processes n: 5 Please enter the type of resource M: 3 Please enter the maximum allowed number of resource 1 of process 1 Max[1] : 7 Input the maximum amount of resource 2 for process 1 Max[2] : 5 Input the maximum amount of resource 3 for process 1 Max[3] : 3 Input the allocated amount of resource 1 for process 1 Allocation[1] : 0 Input the allocated amount of resource 2 for process 1 Allocation[2] : 1 Set the maximum amount of resource 1 in process 2. Max[1] : 3 Set the maximum amount of resource 2 in process 2. Max[2] : 2 Set the maximum amount of resource 3 in process 2. 2 Please input the allocated quantity of resource 1 of process 2 as Allocation[1] : 2 Please input the allocated quantity of resource 2 of process 2 as Allocation[2] : 0 Please input the allocated quantity of resource 3 of process 2 as Allocation[3] : 0 Input the maximum allowed quantity of resource 1 in process 3 Max[1] : 9 Input the maximum allowed quantity of resource 2 in process 3 Max[2] : 0 Input the maximum allowed quantity of resource 3 in process 3 Max[3] : 2 Input the allocated quantity of resource 1 in process 3 [1] : 3 Input the allocated quantity of resource 2 in process 3. Allocation[2] : 0 Input the allocated quantity of resource 3 in process 3. Allocation[3] : 2 Input the maximum allowed quantity of resource 1 in process 4. 2 Input the maximum allowed quantity of resource 3 for process 4 Max[3] : 2 Input the allocated quantity of resource 1 for process 4 [1] : 2 Input the allocated quantity of resource 2 for process 4 [2] : 1 Set the maximum allowed quantity of resource 1 for process 5. Max[1] : 4 Set the maximum allowed quantity of resource 2 for process 5. Max[2] : 3 Set the maximum allowed quantity of resource 3 for process 5. 3 Input the allocated quantity of resource 1 for process 5. [1] : 0 Input the allocated quantity of resource 2 for process 5. [2] : 0 Input the allocated quantity of resource 3 for process 5. [3] : 2 Input the available quantity of resource 1. 3 Enter the available quantity of resource 2:3 Enter the available quantity of resource 3:2 SafeOrder: Process 2 Process 4 Process 5 Process 1 Process 3 Remaining quantity of resource 1:3 Remaining quantity of resource 2:3 Remaining quantity of resource 3: If no, enter 0:2 Number of resource 1 required by process 2 :1 Number of resource 2 required by process 2 :0 Number of resource 3 required by process 2 :2 SafeOrder: Process 2 Process 4 Process 5 Process 1 Process 3 The remaining resources are as follows: Resource 1 Remaining quantity: 2 Resource 2 Remaining quantity: 3 Resource 3 Remaining quantity: 0 Check whether new requests exist. If yes, enter the process id. If no, enter 0. If the number of resources required by process 4 exceeds the number of resources required by process 4, re-enter the number of resources available. If the number of resources required by process 4 exceeds the number of resources required by process 4, re-enter the number of resources available. If the number of resources required by process 4 exceeds the number of resources required by process 4, re-enter the number of resources available. 5 Enter resource 1 required by Process 5 :1 Resource 2 required by Process 5 :3 Resource 3 required by Process 5 :0 Unsafe Process finished with exit code 0Copy the code

Seven, the appendix

Annotated source programs

#include <iostream>
#include <iomanip>

using namespace std;
#define MaxNumber 100

class BankerAlgorithm {
public:

    int n;// Number of processes n
    int m;// Resource type m
    int Available[MaxNumber];// The number of available resources
    int Request[MaxNumber];// Number of resources requested by the process
    int SafeOrder[MaxNumber];// Security process sequence

    // Define the data structure of the process
    typedef struct {
        int Max[MaxNumber];
        int Allocation[MaxNumber];
        int Need[MaxNumber];
        bool Finished;// Complete state
    } Progress;

    Progress progress[MaxNumber];

    // Enter the number of processes, type of resources, and the number of Max, Allocation, and needs of resources related to each process
    void Input(a) {
        cout << "Please enter the number of processes n:";
        cin >> n;
        cout << "Please enter resource type m:";
        cin >> m;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                cout << "Please enter the process" << i << "Resources" << j << "Maximum allowable quantity Max[" << j << "]:";
                cin >> progress[i].Max[j];
            }
            for (int j = 1; j <= m; j++) {
                cout << "Please enter the process" << i << "Resources" << j << "Allocation of allocated quantity [" << j << "]:";
                cin >> progress[i].Allocation[j];
            }
            for (int j = 1; j <= m; j++) { progress[i].Need[j] = progress[i].Max[j] - progress[i].Allocation[j]; }}for (int i = 1; i <= m; i++) {
            cout << "Please enter available resources" << i << "Available quantity:";
            cin >> Available[i];
        }

        cout << endl;
    }

    // Determine whether there is a new request, if there is no exit, if there is a request to enter the number of resources
    void NewRequest(Progress pg[MaxNumber], int a[MaxNumber]) {
        int newRequest;

        // The number of remaining resources is referenced
        cout << endl << endl << "The remaining resources are as follows:" << endl;
        for (int i = 1; i <= m; i++) {
            cout << setw(6) < <"Resources" << setw(2) << i << setw(6) < <"Remaining quantity:" << setw(2) << a[i] << endl;
        }

        // Determine the new request
        cout << endl << "Is there a new request? If yes, enter the process number. If no, enter 0:";
        cin >> newRequest;
        if(newRequest ! =0) {
            for (int i = 1; i <= m; i++) {
                cout << "Please enter the process" << newRequest << "Required resources" << i << "Quantity :";
                cin >> Request[i];
                if (Request[i] > a[i]) {
                    cout << "Insufficient allocatable resources, please re-enter" << endl;
                    NewRequest(pg, a);
                }
                if (Request[i] > pg[newRequest].Need[i]) {
                    cout << "Out of demand, please re-enter" << endl; NewRequest(pg, a); }}for (int i = 1; i <= m; i++) {
                a[i] -= Request[i];
                pg[newRequest].Allocation[i] += Request[i];
                pg[newRequest].Need[i] -= Request[i];
            }
            Order(pg, a);
        } else {
            return; }}void Order(Progress pg[MaxNumber], int a[MaxNumber]) {
        // Define the subscript
        int orderNum = 0;

        // Copy process operations
        Progress progressCopy[MaxNumber];
        for (int i = 1; i <= n; i++) {
            progressCopy[i] = pg[i];
        }

        // Copy the number of available requirements
        int available[MaxNumber];
        for (int i = 1; i <= m; i++) {
            available[i] = a[i];
        }

        while(! NewFinish(progressCopy)) {/ / if any
            if (IsSafe(progressCopy, available)) {
                for (int i = 1; i <= n; i++) {
                    if(! progressCopy[i].Finished && IsExecutable(progressCopy[i], available)) {// Allocate only if both incomplete and assignable requirements of the process are satisfied
                        progressCopy[i].Finished = true;
                        for (int j = 1; j <= m; j++) { available[j] += progressCopy[i].Allocation[j]; } SafeOrder[++orderNum] = i; }}}else {
                cout << "Unsafe" << endl;
                exit(0); }}/ / output SafeOrder
        cout << "SafeOrder for.";
        for (int i = 1; i <= n; i++) {
            cout << setw(12) < <"Process" << setw(4) << SafeOrder[i];
        }

        NewRequest(pg, a);
    }

    // Determine whether all processes are complete
    bool NewFinish(Progress pg[MaxNumber]) {
        bool finished = true;
        for (int i = 1; i <= n; i++) {
            finished *= pg[i].Finished;
        }
        return finished;
    }

    // Determine if allocatable resources can satisfy the process
    bool IsExecutable(Progress pg, const int a[MaxNumber]) {
        bool isExecutable = true;
        for (int i = 1; i <= m; i++) {
            isExecutable *= (pg.Need[i] <= a[i]);
        }
        return isExecutable;
    }

    // Determine if it is safe now
    bool IsSafe(Progress pg[MaxNumber], int a[MaxNumber]) {
        bool isExecutable = false;
        for (int i = 1; i <= n; i++) {
            if (IsExecutable(pg[i], a)) {
                isExecutable = true;
                returnisExecutable; }}returnisExecutable; }};int main(a) {
    BankerAlgorithm bankerAlgorithm{};
    bankerAlgorithm.Input();
    bankerAlgorithm.Order(bankerAlgorithm.progress, bankerAlgorithm.Available);

    return 0;
}
Copy the code