···3737 # Make space in physical memory depending on the order.
3838 def make_space(s):
3939 def rec(page_table: dict[int, Bits], order: list[int], page: int) -> tuple[int, list[int]]:
4040- print("-" * 80)
4141- print("\ttable:", page_table)
4242- print("\torder:", order)
4343- print("\tpage:", page)
4444- print("-" * 80)
4540 # if the page table says that the page's R bit was set:
4641 if page_table[page].read == True:
4742 # rotate the queue: s_.order[1:] + [page]
···4944 # the next page to check for is: s_.order[0]
5045 return rec(page_table | {page: Bits(False, False)}, order[1:] + [order[0]], order[0])
5146 else:
5252- print("=" * 80)
5353- print("final page:", page)
5454- print("=" * 80)
5547 return page, order
5656- # Finally, return the new state, without that page.
5748 last_page, new_order = rec(s.page_table, s.order[1:] + [s.order[0]], s.order[0])
4949+ # Finally, return the new state, without that page.
5850 return State(s.faults, s.hits, new_order[:-1], {k: v for k, v in s.page_table.items() if k != last_page}, s.physical_capacity)
59515252+ # This function simply inserts a page into the page table.
6053 def insert(s, page: int):
6154 return State(s.faults, s.hits, s.order + [page], s.page_table | {page: Bits(False, False)}, s.physical_capacity)
62555656+# This is the algorithm for second chance page replacement.
6357def second(state: State, access: tuple[str,int]) -> State:
6458 page = access[1]
6565- print("-" * 80)
6666- print("table:", state.page_table)
6767- print("order:", state.order)
6868- print("page:", page)
6969- print("-" * 80)
5959+ # If the page is in the page table, that is a page hit.
7060 if page in state.page_table:
6161+ # Also, the page's R bit must be set to 1.
7162 return state.modify(page, True).hit()
7263 else:
6464+ # If there isn't any space in the page table, call make_space()
7365 if len(state.page_table) == state.physical_capacity:
7466 return state.make_space().insert(page).fault()
7567 else:
6868+ # If there is space in the page table, we can simply insert the page.
7669 return state.insert(page).fault()
77707871def main():
7272+ # The user must provide the physical capacity and the file path to the
7373+ # access sequence.
7974 if len(sys.argv) != 3:
8075 print("USAGE:", sys.argv[0], "number_of_pages", "file_path")
8176 print("\twhere:\n\t\tnumber_of_pages : int\n\t\tfile_path : string")
82777878+ # The second argument is the file path.
8379 file_path = sys.argv[2]
84808181+ # This simply parses the access sequence file.
8582 accesses = []
8683 with open(file_path) as f:
8784 for pair in f.read().split():
8885 mode, page = pair.split(":")
8986 accesses.append((mode, int(page)))
90878888+ # The physical capacity is the first argument.
9189 limit = int(sys.argv[1])
9090+ # The result is simply the evaluation of the second algorithm on the access
9191+ # sequence.
9292 res = fold(second, State(0, 0, [], dict(), limit), accesses)
93939494+ # Print the result.
9495 print("Faults:", res.faults, "\nHits:", res.hits)
95969697main()