Document Sample
Assignment Powered By Docstoc
					Assignment 2
Memory Manager Simulator:
One of the jobs of a real operating system is to manage memory. The component of the operating
system that is responsible for this task is called the memory manager.
In this assignment, we shall simulate the work of a memory manager. Consequently, Our
simulated operating system will only contain those elements relevant for memory management.

Our memory hierarchy is composed of two levels (only): A fast and small memory which
represents the main memory of the computer, i.e., RAM, and a slow larger memory (backing
store) that represents the disk. Both main memory (MM) and disk memory are divided into pages
of fixed byte size.

The simulator will handle the memory pages of several processes. Each process reads and writes
information from memory using virtual addresses. The memory manager does the conversion
(using the MMU) of logical addresses to physical addresses. In addition, the memory manager
ensures that the requested physical page is located in memory (otherwise the memory manager
loads this page from the disk) and hands the requesting process the memory data it requested.

Each process has its own virtual address space. The memory manager is responsible for
managing all the pages of all processes, and handling all their requests.

In this assignment, we will implement several page replacement algorithms, and compare their

General Description:
In this section we provide an overview of the components included in the simulator being built.
The components are as follows.

   1. Main Memory (MM) – simulates a small and fast memory. The MM is partitioned into
      two parts.; a user part and a kernel part. In the user part of the MM we store the pages
      related with processes. In the kernel part of the MM we store pages needed by different
      components of the virtual operating system for the managing of memory. Each part is of
      a fixed size and is composed of a collection of pages.

2. Disk – simulates a slow larger memory device (like a hard disk). The disk is partitioned
   into two parts – user and kernel. Each part keeps pages which were paged out (for lack of
   space in the MM). Namely, the user part keeps paged out pages of the MM user part,
   while the kernel section keeps paged out pages of the MM kernel part. Each part is of a
   fixed size and is composed of a collection of pages. In the Disk we keep all the pages of
   processes (both kernel and user) in order. I.e., all user and kernel pages of a specific
   process are kept in sequence, details will follow. However, for a subset of these pages
   copies are kept in the MM.

3. Page Replacement Manager (PRM) – each time a requested (user or kernel) page is not in
   MM, the PRM is asked to relocate pages so that the requested page will be in MM, and
   ready for use. The PRM finds a free page slot of the appropriate type (kernel/user) in the
   repository of the MM (if such a free slot exists) and loads the requested page from the
   Disk to the repository of the MM. If no such free page slot exists, the PRM picks a page,
   and pages it out to the Disk. Then, the PRM loads the requested page from the Disk to the
   now free slot in the MM. Different paging algorithms will be used for different parts
   (kernel/user) of the MM.

4. Memory Management Unit (MMU) – is responsible for converting a process logical
   address to its physical address in the MM (if it is indeed there). If the page is not in the
   MM, the MMU generates a page fault. The MMU uses kernel pages to hold its page
   table. We shall use Two-Level Paging in our simulator. The MMU always keeps the outer
   table (in which every entry points to a second-level page) in its internal memory. The
   second-level pages are kept in either the MM or the Disk (in the kernel part). Since the
   entire page table (both outer table and second-level pages) is unique for each process,
   whenever a context switch is performed, the outer-table needs to be swapped out. The
   outer-table of the new process is to be loaded into the MMU's internal memory. Each
   page the MMU uses contains many page-entries. For instance, a typical entry may
   contain the 2nd page of the current process that is kept in MM, and its page number there
   is 1345. Another entry may contain the information that the 16th page of this process is
   not in MM (therefore on the Disk). The MMU has an internal memory capable of holding
   exactly one page.

5. Memory Manager (Manager) – this is the main driver. It receives requests from processes
   to read/write to/from memory (the processes give it virtual addresses). It uses the MMU
   to find the right page in MM and performs the requested action (read/write). Note that it
   is possible that the second-level page will not be in MM and will have to be loaded. Also,
   the actual user page (the one requested) may not be in MM, and will have to be loaded. In
   both cases a page fault will be returned from the MMU, and the Manager will have to ask
   the PRM to bring that page into memory. Then the Manager will use the MMU again
   (now, the same page fault can not occur). The Manager continues to do so until it
   succeeds in completing its operation.

6. User Interface (UI) – a simple interactive 'shell' to test your program. The user can create
   processes, switch between existing processes, read / write from/to a memory address (by

       giving a virtual address), print statistics (like the hit ratio), print "debugging" information
       (such as which pages are in MM right now).

                     The Components Of The Simulator
         Disk                                                      MM
          User                       kernel                        User          kernel




                                    User-Interface (UI)

                                 The User (a real human)

Data Structures:
In this section we detail the data structure that are to be defined and used in the simulation.
One may assume that sufficient 'internal' memory is provided for maintaining these data
structures, i.e., one does not have to store it in either MM or Disk. The data structures are as
1. ProcessControlBlock (PCB) – The following record is kept for each process. The PCB
    contains information regarding a specific process. Namely,
         a. Process id (pid).
         b. Start and end indices to the Disk user part, i.e., the location of the user pages of the
             related process are stored.
         c. Start and end indices to the Disk kernel part, i.e., the location of the page table
             (second layer pages) of the related process is stored.
         d. Virtual time.
         e. The location of the outer-table associated with the process in the outer-table array.

2. Outer-Table Array - An array of pages used to hold the outer table (first layer pages) of all
   processes. A copy of the outer table of each process is kept in this array. This array simulates
   a fixed size area of RAM dedicated by the operating system for holding all the outer-tables.
3. MM-Disk-User-Map - a data structure which maps each user page in the MM to its user page
   address in the Disk or marks that it is an unused page.
4. MM-Disk-Kernel-Map – a data structure which maps each kernel page in the MM to its
   kernel page address in the Disk or marks it as unused page.
   The implementation of this mapping function is up to you. You can correlate between each
   page in MM and its Disk address, or you can keep some pointer to the PCB and offset (and
   then the Disk address can be calculated by the start index from the PCB + offset). These data
   structures are there just for you to know what each page in MM contains. You may
   implement them any way you wish. For example, saving the explicit disk page number, or
   saving pid and offset.
5. For each page in MM (kernel and user), a dirty bit is kept. Whenever the content of that page
   in changed, that bit must be set (flagged true). Whenever a page is loaded to MM or saved to
   Disk, this bit must be cleared (flagged false). Also there is a dirty bit for the page the MMU
   holds (the first-layer page).
6. For each page in MM (kernel and user), a reference bit is kept. Whenever a page is accessed
   (read or write), that bit must be set (flagged true). Whenever a page is loaded to MM, this bit
   must be cleared (flagged false). The replacement algorithm may read / change these bits.
7. For each page in MM (kernel and user), a reference virtual time (integer) is kept. Whenever a
   page is loaded, this field must be updated according to the process's current virtual time. The
   page replacement algorithm will use / change this field.

Description of an Entry in the Page Table:
Each entry contains only an address (index) in MM. Each entry should be exactly 4 bytes in size.
This means that if you are given that PageSize is 40 bytes then it should hold exactly 10 entries.
You may assume that a page size is a power of two. (4, 8, 16, 32…).

Detailed Description of Each Component:
   1. Main Memory (MM) –
      divided to user and kernel parts. We simulate the MM by two arrays of pages (one for
      each part). Each page is an array of PageSize bytes. The NumOfUserPagesInMM and
      NumOfKernelPagesInMM, from the config file, determine the size of each array.

   2. Disk – Much like the MM, we use two arrays, NumOfKernelPagesInDisk and
      NumOfUserPagesInDisk determines the length of each array. Every element in an array
      (a page) is of PageSize bytes.
      The Disk Structure:
      For each process we keep in the kernel part all its second-layer pages one after the other.
      In the user part we keep all its user pages also in sequence.

                                                    The Disk

     Pid=8       Pid = 12 Pid = 4                                   Pid = 8           Pid = 12

     lvl   lvl   lvl   Lv    lvl   lvl   ..   ..   ..   …   …   1     2   3   4   1   2   3      4   …
      2     2     2     l2    2     2

                       Kernel part                                    user part

             In this example we have each page capable of holding two entries. So
             second layer contains 2 pages. And each process has 4 user pages.

3. Page Replacement Manager (PRM) –
   The PRM is responsible for loading pages from the Disk to the MM. It has two methods
   in the form of:
   loadUserPage(int processID, int pageNum);
   loadKernelPage(int processID, int pageNum);
   The RPM uses the appropriate PCB to find out which page on the Disk should be loaded,
   selects where to load it to, if the selected location already houses a page then that page
   must be paged-out, and then copies the page from the Disk to the selected location in
   Selecting the location is as follows:
   If there is an unused page (empty) it is selected.
   Else, one is picked based on the algorithm specified in the config file under
   AlgorithmForUser or AlgorithmForKernel (depending if we are paging out a kernel or
   user page).
   Paging-out a page p includes:
   Case 1: p is a user page:
   The second layer page that holds the entry pointing to it must be updated. This includes
   checking if this second layer page is in MM (using the MM-Disk map), and if so,
   updating that page in MM. If it is not in MM, a kernel page fault occurs and that page
   must be loaded from Disk to MM and then updated (meaning calling the loadKernelPage
   Case 2: p is a kernel page:
   Case 2.1: p is a level-two page:

   The first layer page (outer-table) must be updated. If the first layer page is currently in
   the MMU, then it is updated there. If it is not in the MMU, it is updated directly in the
   outer-table array.
   Case 2.2: p is a level-one page:
   This cannot happen since the level-one pages are not kept in MM.
   In All Cases:
   If the dirty bit of p is on, then p must be written to the Disk. If the dirty bit of p is off,
   then no point of writing p to the Disk since his copy on the Disk is already up-to-date.
   Another point to note is that paging out a user page that his kernel page is not in the MM
   you will be required to reload the kernel page just for this update. This generates another
   page fault.

4. Memory Management Unit (MMU) – is responsible for converting a process's logical
   address to its physical address in MM.
   It has a method that receives a virtual address, and returns the page number in MM which
   contains this user page. To find out this answer, it uses its current outer-table (first layer)
   to find out where is the second layer page that holds the answer. It is possible this second
   layer page will not be in MM, in that case the MMU returns that a kernel page fault has
   occurred and specifies which page it needs. The Manager will receive this information
   and arrange (with the help of the PRM) for that page to be loaded into MM. Then the
   MMU will be asked again (and this time it will find the second layer page in MM), then it
   will look in the MM, find the address of the requested user page in MM and return it.
   However it is possible that the requested user page is not in MM, in which case a page
   fault occurs, and again the Manager will receive it and arrange for that page to be loaded
   up, and the MMU will be asked again. Basically whenever a page fault occurs in the
   MMU, the MMU reports it to the Manager and does nothing more. The Manager will
   arrange for the page needed to be loaded up to MM and send a new request to the MMU.
   Also, if you need to update the outer-table of a process not currently running, you can go
   update it directly in the outer-table array.

                                                                   Main Memory
                                                     Kernel part             User part
                                                   1st page                               1st
                                              1       120                                page

                   MMU                        2       1345
                                              ..        ..
            indx   addr                       16        -                                page
            1       13
                                               16th page                                 user
            2        -                                                                   256th
                                             250      1243
            ..      ..                                                                   page
                                             251        -
           16       24                                                                   user
                                              ..        ..
                                             256      1065                               page

                                              11th page
                                             160        -                                 2nd
                                             161      345
                                              ..       ..
                                             166        -

5. Memory Manager (Manager) –
   Is the main driver. It receives from the UI requests like:
        a. read(int vAddr int amount) – sends the vAddr to the MMU, invokes the PRM
           whenever page faults occur, calls the MMU again until the MMU returns its
           answer. Then it goes to the MM at the location provided by the MMU, returns the
           specified bytes inside that page. It is possible the read will extend to several
           pages, so after reaching the end of the page, need to get the next page address
           from the MMU again, and continue reading there…
        b. write(int vAddr, char[] c) - writes the given chars to MM. gets the MM page
           number from the MMU (again page faults can occur and PRM must be called),
           goes to that page, writes (at the right offset) the given bytes (don’t forget to raises
           the dirty flag of that page). It is possible the write will extend to several pages, so
           after reaching the end of the page, need to get the next page address from the
           MMU again, and continue writing there…
        c. int createProcess() – finds space big enough on the Disk to hold the process user
           pages and kernel pages (by just looking at the PCBs and knowing the number of
           pages the Disk can hold such free space can be located), updates all data
           structures according (adds a new PCB, updates the maps, outer-table array),
           allocates a unique process id (PID) for the newly created process and returns it. If
           there is not enough Disk space for creating a new process, -1 is returned.

       d. deleteProcess(int id) – The data structures are updated (PCB deleted, maps
          updated, outer-table array), note that there is no need to actually change the
          content of the Disk pages or the MM pages, The MM pages will just be marked
          empty and contain 'trash' and the same goes for the Disk pages.
       e. contextSwitch(int id) – performs a context switch. Meaning we load the outer-
          table (first-layer) of the given process' id to the MMU, after we saved (if dirty) the
          current outer-table (which is in the MMU) to the outer-table array.
       f. Other functions – feel free to add them as needed.

6. User Interface (UI) –
   a simple interactive 'shell' to test your program. Prints the prompt ">" to stdout and waits
   for commands. The meaning of the $ symbol will be explained later. Notice the
   commands are case-sensitive (meaning createProcess is a valid command and
   createprocess is not). possible commands are:
       a. createProcess
          creates a new process and prints out the new process ID (or description of error if
          something like "insufficient space" occurred).
       b. delProcess id
          deletes the process with the given id. Prints "ok" (or description of error if
          something like "no such process id" occurred).
       c. switchTo id
          performs a context switch to run the process with that id. Prints "ok" (or
          description of error like "no such process id.").
       d. write vAddr1 s
          writes the string s starting from location vAddr1. Prints "ok" (or description of
          error if it occurred). $
       e. read vAddr amount
          reads and prints amount bytes from vAddr. Print each byte as a char. (or
          description of error if it occurred). $
       f. loopRead vAddr off amount
          reads and prints the chars found at vAddr, vAddr+off, vAddr+2*off, …,
          vAddr+(amount-1)*off. Assume these memory addresses are within the bounds of
          the virtual memory (not below 0 or too big). Assume amount > 0. $
       g. loopWrite vAddr c off amount
          writes the char c to the following virtual addresses: vAddr, vAddr+off,
          vAddr+2*off, …, vAddr+(amount-1)*off. Assume these memory addresses are
          within the bounds of the virtual memory (not below 0 or too big). Assume amount
          > 0. $
       h. userHitRate
          prints the total hit ratio (a real number between 0 and 1) for user pages only.
          (Reminder – this is equal to "how many times user pages were already in MM,
          divided by the number of times we referred to user pages").
       i. kernelHitRate
          prints the total hit ratio so far for kernel pages only.
       j. hitRate
          prints the total hit ratio so far for both kernel and user pages.

           k. printUserMM
              displays what pages are in the user part of the MM. For each page in MM (in
              order) display "(pid,pageNum)". For empty pages (un-used) print "(empty)".
           l. printKernelMM
              same as printUserMM but for kernel pages. For empty pages display "(empty)",
              for second-layer pages display "(pid, pageNum)", where page num 5 (for
              example) means that this is the 5th second layer page of the current process.
           m. printMMUTable
              prints the outer-table (currently in the MMU), entry by entry. For each entry that
              points to a second-layer page in MM display "(entry_index, MMAddr)", for each
              entry that points to a second-layer page that is not in MM, display "(entry_index, -
           n. exit
              Terminate the simulator run.

The Configuration File:
Has the following format:

PageSize = [integer]
NumOfKernelPagesInMM = [integer]
NumOfUserPagesInMM = [integer]
NumOfKernelPagesInDisk = [integer]
NumOfUserPagesInDisk = [integer]
AlgorithmForUser = [WSClock/FIFO]
AlgorithmForKernel = [WSClock/FIFO]
WSClockDelta = [integer]

       You may assume the given file will have this exact format. Integers are of course positive
only. Notice the fine details, such that there is exactly one space between field name and the '='
char, and also one space between the '=' char and the value.

The Replacement Algorithms:
You are required to implement both WSClock and FIFO. Notice different parts (kernel / user)
have independent replacement algorithms.
FIFO – Implement it by using some queue. Elements added at one end and removed from the
other end. Whenever a page is loaded into MM you move that page frame number to the end of
the queue. Whenever you need to page out some page – the page frame at the head of the queue
is selected. You may assume to have enough 'internal memory' for this queue, so you don’t need
to save it in the MM or the Disk.
WSClock – Is a global algorithm which chooses which page should be paged out by using: the
'virtual time' of each process, the reference bit of each page, the 'reference virtual time' of each
page, and single pointer (the "clock hand"). The data structures described before contain this
information. You learned in class how this algorithm works. Remember to update all data

structures accordingly when a page is loaded to MM from the Disk.
The virtual time of a process is advanced by one, for each UI command it performs that contains
the symbol '$' in its description.
Let p be the page currently pointed by the "clock hand", its reference virtual time be rp, p
belongs to process pid, and pid's virtual time is t. we define currentDelta to be (t – rp). The
variable WSClockDelta is defined in the config file.
     Case 1: p's reference bit is set (1):
        it is not paged out, instead its reference bit is cleared, its virtual time is updated to t, and
        the "clock hand" advances to point to the next page.
     Case 2: p's reference bit is cleared (0) and currentDelta <= WSClockDelta :
        the "clock hand" advances to point to the next page.
     Case 3: p's reference bit is cleared (0) and currentDelta > WSClockDelta :
        the "clock hand" advances to point to the next page, p is selected to be paged out.
     Case 4: There exists no page p such that case 3 is true for him, meaning the clock hand
        has finished a full circle on all pages in a single iteration, then the page with biggest
        currentDelta is selected to be paged out.

Running your program:
Is done by typing:
> sim <config_filename>

Submitting Requirements & Technical Information:
    1. Programming language to be used is C++.
    2. Submit a single zip file called (where the ID is your and your partner's ID).
       This zip file should contain only source code (cpp and h files) as well as your makefile.
    3. Unzipping your program and running 'make' should compile your code and create the
       executable 'sim'.
    4. Your program will be tested on local Linux machines as installed in lab 34/302. Make
       sure the code and makefile you submit run flawlessly on these machines before
    5. Submit your zip file using the submission system.
    6. Questions should be sent to
    7. This assignment is worth 10% of your final course grade.
    8. Due date – as published in the course website.

Q & A:
In this last section we include some Q&A from previous years. We hope that this section will
clear up anything we missed

Q: When creating a new process how many first layer, second layer and user pages should be
allocated for that process?
A: One first layer page in the outer-table array.
As many second layer pages as can be pointed to from the outer table (Calculated using the
pageSize and entrySize) in the kernel part of the Disk.
As many user pages as all the second layer pages (together) can point to in the user part of the

Q: In real OS a process must ask for memory space (for example call malloc). How do the
processes receive memory in our simulator?
A: In order to simplify matters, the processes start with all possible memory already allocated to
them. A process can write to its virtual address 1023 for example immediately after being
created, it does not need to ask our operating system for this memory.

Q: Suppose we have kernel size 1, and we need to reload the
kernel page after that. Does that constitute a kernel-miss?
A: You may assume that the number of blocks in each part of MM is at least 4.

Q: May we assume that PIDs of processes start from 0 and not from 1?
A: Yes.

Q: What is exactly the hitRate?
A: hitRate is the number of times a desired page was found to be in MM divided by the
number of times you wanted to access a page. There are several ways to count this, for
example, do you count hits/miss on kernel pages when you want to update them after
making room for loading a new page. Pick a reasonable counting method, and describe to
the grader what you picked.

Q: Suppose we delete a process that has pages in the MM.
After the process dies, are these pages in the MM defined
empty or non empty(but holding garbage)?
A: They are empty. You can choose to manually go and put some value (like 0) there, but it is
really not necessary and is just not efficient. Leave the data as it is, junk, and when some page
will be loaded there it will overwrite that junk.

Q: Is there a limit on the maximum number of chars
in a string? and what is the length
of strings we have to take care of ?
A: Assume the strings contain at most 100 bytes.

Q: When performing a context switch, are we clearing the Main
memory from all pages of previous process?
(otherwise - when we store a page of a previous process,
how can we reach its kernel page so we can mark that the
page is no longer in the Main memory?)
A: You are not clearing it. The data structures you keep suffice to know all the information you
need. It is not a super-simple operation, but it's not too hard either.

Q: May we assume, that when we write an address in a page,
the whole address is written into one page? Or may it be
that half of an address is stored in one page and
the other part is in another page (for example : when page
size 2 bytes)?
A: Assume pageSize > 3. You can't write 'half an address' in one page and the other 'half' in

Q: May we assume that size of enrty in outer table is 4 byte?
A: Yes

Q: Can we hold on disk pointers to disk pages?
A: You cannot have MM just point to disk pages, they are two different things.
Image you change something in memory (and raise the dirty bit), that change did not yet happen
on the disk

Q: How do we interface with the MainMemory from the MMU
and the MemoryManager ? Do we add a function to the MM
that returns one byte ? one page ? the same goes for writing...
If the latter is correct, where do we store the page we read
from MM ?
A: The MM is just a collection of pages.
The MMU can just access it directly, so just go to the data there and read/write it there.

Q: You wrote in the assignment description that the MMU has
exactly one page of internal memory. Does this the page hold the current outer table? or is this
page used for something else ?
A: This is the page that holds the current outer table.

Q: About the outer table array:
Does it have a fixed size?
if it does: what is this size ?
is there a maximum number of processes ?
if there is: what do we do if there are too many
processes and there's not enough space on the disk ?
A: The disk space limits the amount of processes. The outer table array should be large enough
to contain the outer tables of all processes, so that is its max size.

Q: When we create a process, and then context switch to it,
is it all its pages are only on the disk? Meaning each request at
first will be "miss"?
A: When you create a process, none of his pages are in MM, so yeah the
first request will produce a 'miss'

Q: If we create a process, how do we know where to put it on the disk?
Because some processes may have been deleted, and leave "spaces" in the
kernel and user part of the disk, so adding the sizes of each process space
won't do.
A: Use the PCBs.
For example, if the PCBs say disk pages 0-9 and 20-29 are used, then it is because the process
using 10-19 was probably deleted...

Q: How do we know how much user Pages a process have at creation?
Does it have fixed length?
A: Yes it is fixed since the first layer page is of fixed size and each second layer page is of fixed
size. Therefore there are a fixed number of entries in the entire page table. Therefore there is a
fixed amount of user pages per process.

Q: Does the MMU contain the outer table array?
else where should be the Outer table array?
A: The outer table array is kept as 'internal memory'. You can keep it in the MMU if you want.
The point is you don't need to manage it's page-in/page-out to/from

Q: Each process needs pageSize/4 kernel and (pageSize/4)^2 user pages.
so can i assume NumOfKernelPagesInDisk % (pageSize/4) = 0 and
NumOfUserPagesInDisk % (pageSize/4)^2 = 0
A: No

Q: Does the first-layer table of a process should be a page, and consist of
PageSize/4 entries? (in the Q&A in the ass description it says: "One first
Layer page in the outer table array").
A: The first-layer page (also known as the outer table) has the same size as any other page and
contains as many entries as space allows.

Q: Could you explain more about the format of the vAddrs given by the
user when he wants to write or read?
A: I'll explain by example. Lets assume pageSize = 30 and the user asked to write some char to
vAddress 362. Therefore that byte should be written to the second byte in the 12th user page of
this process (because 362 / 30 = 12 and 362 % 30 = 2). The answer may be a bit different
depending on how you count, from 0 or from 1.
The user of course does not know where this is written, he is not even aware there are pages or
what size they are. If a process has say 100 user pages, each of size 30 bytes, then the vAddress
run from 0 to 2999 and he thinks this memory is continuous.

Q: May we assume that read/write commands do not request an amount that
exists the process boundaries?
A: You may assume that read/write will not refer to addresses
outside the process virtual address space.

Q: in the "printUserMM", do we need to print the logical pageNum,
or the physical num?
if it is the logical num: how can we know all of the user pages num
that is now in the MM, some kernel pages that points at them can
be only in the disk (and not in the MM).
A: The logical. You have MM-Disk-User-Map to help you.

1.Can we add absent bit to page table entry , or we need to reset
somehow address in MM when page is swaped out ?

2. In 'create' command do we switch active process to be created one?

3. In 'delete' command . If we delete 'active' process ,
which process is active after deletion ?

4. Quote: From description of create command
.. updates all data structures according
 (adds a new PCB, updates the maps, outer-table array)...
What updates we need to do in maps?
1. Since each entry needs to be 4 bytes, it will be easier not to add an absent bit and just write
something like -1 as the address in MM.
2. No. just create, don’t switch.
3. No process will be active, just like there is no active processes when you start up the
simulator. The user will have to switch to whatever process he wants to run next.
4. The comment in the brackets "(add new PCB..)" is just an example of what updates you might
perform. It is possible you don’t need to touch the maps. The point is - remember to update
whatever data structures need updating. It is possible you will to update other structures as well,
exactly what is up to you.

Q: can you please explain what is the MMU's page table and how
it different from the MMU's outer table that mentioned in
the assignment description.
"The MMU uses kernel pages to hold its 'page table'. "
"The MMU always keeps the 'outer table' (in which every
entry points to a second-level page) in its internal memory."
A: Imagine a simple computer that has a very small virtual address and so one layer paging is
used. There is only one table that holds all the information. This table is the page table. Once we
extend this idea to two-layer paging, the page table is the collection of all data in all the second
layer pages (even though it is split up). It is a logical name.
The outer table is the first layer-page in the two-layer approach. It is the table that points to all
the second layer-pages, which actually contain the data of the page table.
Slide 32, titled two-level page-table scheme, in the Memory ppt file (under lectures) visually
explains this.

Q: I didn't fully understand how I should implement a Page in the system.
It should be just chars of some size or a struct?
Please explain more about the page.
A: You may implement it as you wish. It's just a collection of PageSize bytes, so an array is one
(simple) option. Since a char in C++ is 1 byte, it can be easier (for some) to think of it as a char