Experiment 3 virtual storage management (C + + implementation of OPT, FIFO, LRU, LFU and NUR algorithm)

Posted by Sgarissta on Sun, 12 Dec 2021 02:07:31 +0100

Experiment 3 virtual storage management

Experimental properties

  • Design

Recommended class hours

  • 4 class hours

Experimental purpose

One of the main functions of storage management is to allocate space reasonably. Request paging storage management is a common virtual storage management technology.

The purpose of this experiment is to simulate the design of page replacement algorithm in request paging storage management, understand the characteristics of virtual storage technology, and master the page replacement method of request paging storage management.

Experimental content

(1) An instruction sequence is generated by random numbers, with a total of 320 instructions. The address of the instruction is generated according to the following principles:

  1. 50% of the instructions are executed sequentially;

  2. 25% of the instructions are evenly distributed in the front address part;

  3. 25% of the instructions are evenly distributed in the back address part.

The specific implementation methods are:

  1. stay [ 0 , 319 ] [0, 319] A starting point is randomly selected between the instruction addresses of [0319] m m m​;
  2. Execute one instruction in sequence, that is, the execution address is m + 1 m+1 Instruction of m+1 +;
  3. Before address [ 0 , m + 1 ] [0, m+1] Randomly select an instruction from [0,m+1] and execute it. The address of the instruction is m ′ m' m′​​;
  4. Execute an instruction in sequence at the address m ′ + 1 m'+1 m′+1​​​;
  5. Post address [ m ′ + 2 , 319 ] [m'+2, 319] Randomly select an instruction in [m '+ 2319] and execute it;
  6. Repeat the above steps until executed 320 320 320 instructions.

(2) Transform an instruction sequence into a page address stream

Setting: 1 ️⃣ The page size is 1K; two ️⃣ The user memory capacity is 4 pages to 32 pages; three ️⃣ User virtual memory capacity is 32K;

In user virtual memory, press each K K K. storage 10 10 10 instructions arrange virtual memory addresses, i.e 320 320 The storage mode of 320 instructions in virtual memory is as follows: 0 0 Article 0 ~ article 9 9 Directive 9 is the second 0 0 0} page (the corresponding virtual memory address is [ 0 , 9 ] [0, 9] [0,9]);

The instructions from Article 10 to Article 19 are page 1 (the corresponding virtual memory address is [ 10 , 19 ] [10, 19] [10,19]);

...

The first 310 310 Article 310 ~ article 319 319 Directive 319 is article 31 31 Page 31 (the corresponding virtual memory address is [ 310 , 319 ] [310, 319] [310,319]);

In the above way, user instructions can be composed 32 32 Page 32.

(3) Calculate and output the hit rate of the following algorithms under different memory capacity.

  1. Optimal permutation algorithm ( O P T ) (OPT) (OPT);

  2. First in first out algorithm ( F I F O ) (FIFO) (FIFO);

  3. Least recently used algorithm ( L R U ) (LRU) (LRU);

  4. Least access page algorithm ( L F U ) (LFU) (LFU)​;

  5. Algorithms are not often used recently ( N U R ) (NUR) (NUR)​.

life in rate = 1 − ( page noodles lose effect second number ) / ( page land site flow long degree ) Hit rate = 1 - (page failure times) / (page address stream length) Hit rate = 1 − (page failure times) / (page address stream length)

In this experiment, the length of the page address stream is 320, and the number of page failures is the number of times that the page corresponding to the instruction is not in memory each time the corresponding instruction is accessed.

Random number generation method: functions provided by the system can be used r a n d ( ) rand() rand() to initialize and generate random numbers respectively. For example: s r a n d ( ) srand() srand(); statement is a random number that can be initialized:

  • a [ 0 ] = 10 ∗ r a n d ( ) / 32767 ∗ 319 + 1 a[0]=10*rand()/32767*319+1 a[0]=10∗rand()/32767∗319+1​;

  • a [ 1 ] = 10 ∗ r a n d ( ) / 32767 ∗ a [ 0 ] a[1] = 10*rand()/32767*a[0] a[1]=10∗rand()/32767∗a[0]​;​​

Statements can be used to generate a [ 0 ] a[0] a[0] and a [ 1 ] a[1] Random number in a[1].

Experimental requirements

1) Carefully program before getting on the machine;

2) Independent debugging program when on the machine;

3) Submit the experimental report, including paper and electronic parts. See the test report template for the requirements of the test report.

Code display

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <deque>
using namespace std;

// Global variable definition
const int Page_address_stream = 320;
const int Virtual_page = 32;
vector<int> virtual_page_list(Page_address_stream);

// Page table structure
struct PageTable
{
    int pageNum;
    // The status bit P indicates whether the page has been called into memory
    int P;
    // How long will the records in OPT be accessed
    // The LFU records the number of accesses in a period of time
    // Record in NUR whether it has been accessed recently
    int A;
};
vector<PageTable> PageTableList(Virtual_page);

// Function declaration
void OPT(int user_memory_capacity);
void FIFO(int user_memory_capacity);
void LRU(int user_memory_capacity);
void LFU(int user_memory_capacity);
void NUR(int user_memory_capacity);
void refresh();

// Main function
int main()
{
    refresh();
    // Random seed
    srand((unsigned int)time(NULL));
    vector<int> lst;
    // Randomly generated instruction sequence
    for (int i = 0; i < Page_address_stream; i += 4)
    {
        // Random starting point m
        int m = rand() % (Page_address_stream);
        // Sequential execution: Address (m+1)
        lst.push_back(m + 1);
        // Select the execution with address m2 from the previous address
        int m2 = rand() % (m + 2);
        lst.push_back(m2);
        // Sequential execution: Address (m2+1)
        lst.push_back(m2 + 1);
        // Select instruction execution from the back address
        lst.push_back(rand() % (Page_address_stream - (m2 + 2)) + (m2 + 2));
    }
    // Print instruction sequence
    // for (int i = 0; i < Page_address_stream; i++)
    // {
    //     printf("%d\t", lst[i]);
    //     if ((i + 1) % 4 == 0)
    //     {
    //         cout << endl;
    //     }
    // }

    // Transform an instruction sequence into a page address stream
    // Each instruction corresponds to a page and a page offset
    for (int i = 0; i < Page_address_stream; i++)
    {
        virtual_page_list[i] = lst[i] / 10;
    }
    // Algorithm test
    printf("Page Frames\tOPT\t\tFIFO\t\tLRU\t\tLFU\t\tNUR\n");
    for (int i = 4; i <= Virtual_page; i++)
    {
        printf("%d\t\t", i);
        OPT(i);
        FIFO(i);
        LRU(i);
        LFU(i);
        NUR(i);
        cout << endl;
    }
    system("pause");
    return 0;
}

void refresh()
{
    // Page table array assignment
    for (int i = 0; i < Virtual_page; i++)
    {
        PageTableList[i].pageNum = i;
        PageTableList[i].P = 0;
        PageTableList[i].A = 0;
    }
}

void OPT(int user_memory_capacity)
{
    refresh();
    deque<int> q;
    int missing_page = 0;
    for (int i = 0; i < Page_address_stream; i++)
    {
        int cur_page = virtual_page_list[i];
        // If the current page is not in memory
        if (PageTableList[cur_page].P == 0)
        {
            missing_page++;
            // If the memory is not full
            if (q.size() < user_memory_capacity)
            {
                PageTableList[cur_page].P = 1;
                q.push_back(cur_page);
            }
            // The memory is full. The element will not be accessed for the longest time
            else
            {
                int del_page;
                for (int j = i + 1; j < Page_address_stream; j++)
                {
                    int far_page = virtual_page_list[j];
                    if (PageTableList[far_page].P == 1 && PageTableList[far_page].A == 0)
                    {
                        PageTableList[far_page].A = j - i;
                        del_page = far_page;
                    }
                }
                // Check to see if there are pages in memory that can no longer be used in the future
                // In this case, the A of the page table should be infinite, but we should delete it
                for (int idx = 0; idx < q.size(); idx++)
                {
                    if (PageTableList[q[idx]].P == 1 && PageTableList[q[idx]].A == 0)
                    {
                        PageTableList[q[idx]].A = 1e5;
                        del_page = q[idx];
                        break;
                    }
                }
                // Page table A reset
                for (int i = 0; i < Virtual_page; i++)
                {
                    PageTableList[i].A = 0;
                }
                PageTableList[del_page].P = 0;
                int local = 0;
                for (; local < q.size(); local++)
                {
                    if (q[local] == del_page)
                    {
                        break;
                    }
                }
                q.erase(q.begin() + local);
                PageTableList[cur_page].P = 1;
                q.push_back(cur_page);
            }
        }
    }
    printf("%.4f\t\t", 1 - ((double)missing_page / Page_address_stream));
}

void FIFO(int user_memory_capacity)
{
    refresh();
    // Simulate queue with deque
    deque<int> q;
    int missing_page = 0;
    for (int i = 0; i < Page_address_stream; i++)
    {
        int cur_page = virtual_page_list[i];
        // If the current page is not in memory
        if (PageTableList[cur_page].P == 0)
        {
            missing_page++;
            // If the memory is not full
            if (q.size() < user_memory_capacity)
            {
                PageTableList[cur_page].P = 1;
                q.push_back(cur_page);
            }
            // The memory is full, pop up the team leader
            else
            {
                PageTableList[q.front()].P = 0;
                q.pop_front();
                PageTableList[cur_page].P = 1;
                q.push_back(cur_page);
            }
        }
    }
    printf("%.4f\t\t", 1 - ((double)missing_page / Page_address_stream));
}

void LRU(int user_memory_capacity)
{
    refresh();
    // Using deque to simulate stack
    deque<int> q;
    int missing_page = 0;
    for (int i = 0; i < Page_address_stream; i++)
    {
        int cur_page = virtual_page_list[i];
        // If the current page is not in memory
        if (PageTableList[cur_page].P == 0)
        {
            missing_page++;
            // If the memory is not full
            if (q.size() < user_memory_capacity)
            {
                PageTableList[cur_page].P = 1;
                q.push_back(cur_page);
            }
            // The memory is full, pop up the team leader
            else
            {
                // Pop up the element at the bottom of the stack (not accessed for the longest time)
                PageTableList[q.front()].P = 0;
                q.pop_front();
                PageTableList[cur_page].P = 1;
                q.push_back(cur_page);
            }
        }
        // If the current page is in memory, take the page out of the stack and put it at the top of the stack
        else
        {
            // Find the page subscript
            int idx = 0;
            for (; idx < q.size(); idx++)
            {
                if (q[idx] == cur_page)
                {
                    break;
                }
            }
            // The page pops up
            q.erase(q.begin() + idx);
            // Put it on the top of the stack
            q.push_back(cur_page);
        }
    }
    printf("%.4f\t\t", 1 - ((double)missing_page / Page_address_stream));
}

void LFU(int user_memory_capacity)
{
    refresh();
    deque<int> q;
    int missing_page = 0;
    for (int i = 0; i < Page_address_stream; i++)
    {
        int cur_page = virtual_page_list[i];
        // If the current page is not in memory
        if (PageTableList[cur_page].P == 0)
        {
            missing_page++;
            // If the memory is not full
            if (q.size() < user_memory_capacity)
            {
                PageTableList[cur_page].P = 1;
                PageTableList[cur_page].A++;
                q.push_back(cur_page);
            }
            // The memory is full, and the one with the least frequent access is ejected
            else
            {
                int minimum_frequency = PageTableList[q[0]].A;
                int min_idx = 0;
                for (int j = 1; j < q.size(); j++)
                {
                    // It can't be equal to, because if the frequency is the same, the one who stays in memory longer must be kicked out
                    if (minimum_frequency > PageTableList[q[j]].A)
                    {
                        minimum_frequency = PageTableList[q[j]].A;
                        min_idx = j;
                    }
                }
                PageTableList[q[min_idx]].P = 0;
                PageTableList[q[min_idx]].A = 0;
                q.erase(q.begin() + min_idx);
                PageTableList[cur_page].P = 1;
                PageTableList[cur_page].A++;
                q.push_back(cur_page);
            }
        }
        // The current page is in memory. The number of accesses to the page is increased by one
        else
        {
            PageTableList[cur_page].A++;
        }
    }
    printf("%.4f\t\t", 1 - ((double)missing_page / Page_address_stream));
}

void NUR(int user_memory_capacity)
{
    refresh();
    deque<int> q;
    int missing_page = 0;
    // Pointer p in circular array
    int p = 0;
    for (int i = 0; i < Page_address_stream; i++)
    {
        int cur_page = virtual_page_list[i];
        // If the current page is not in memory
        if (PageTableList[cur_page].P == 0)
        {
            missing_page++;
            // If the memory is not full
            if (q.size() < user_memory_capacity)
            {
                PageTableList[cur_page].P = 1;
                PageTableList[cur_page].A = 1;
                q.push_back(cur_page);
            }
            // The memory is full
            else
            {
                while (1)
                {
                    if (PageTableList[q[p]].A == 0)
                    {
                        PageTableList[q[p]].P = 0;
                        q[p] = cur_page;
                        PageTableList[cur_page].P = 1;
                        PageTableList[cur_page].A = 1;
                        p++;
                        if (p == user_memory_capacity)
                        {
                            p = 0;
                        }
                        break;
                    }
                    else
                    {
                        PageTableList[q[p]].A = 0;
                        p++;
                        if (p == user_memory_capacity)
                        {
                            p = 0;
                        }
                    }
                }
            }
        }
        // The current page is in memory, access location 1
        else
        {
            PageTableList[cur_page].A = 1;
        }
    }
    printf("%.4f\t\t", 1 - ((double)missing_page / Page_address_stream));
}

Topics: C++ Algorithm Operating System