This commit is contained in:
2025-04-29 22:22:54 +00:00
parent cfd1f759e0
commit a672211d32
4 changed files with 129 additions and 57 deletions
Binary file not shown.
+25
View File
@@ -0,0 +1,25 @@
COS331
HW4
Nicholas Pease
How To Compile
Compiling this program is done using gcc as follows
gcc hw4.c
How to Run
Run this program by executing the resulting binary
./a.out
Limitations of Program
If you want to mess with the page sizes and counts, you should be able to modify these three DEFINES in the homework file to achieve this, but this is untested
#define PAGE_SIZE 256
#define PHYSICAL_PAGE_COUNT 64
#define LOGICAL_PAGE_COUNT 256
Beyond this, there are no limitations of the program in regards to the assignment. Everything should function as directed.
Aspects of Program to Improve
I think I have already implemented this program to the best of my ability in C. I would love to take it to a object-oirented language like C++ instead, where I could extend the memory management further, but as it stands, this program is fairly modular, allowing easy exchange of the LRU and modification of pseudo-system resources. Perhaps an optimization to not create the bin file if it already exists would be advantageous.
Sources:
fseek (https://www.geeksforgeeks.org/fseek-in-c-with-example/)
+104 -57
View File
@@ -3,56 +3,69 @@
#include <stdio.h>
#include <stdlib.h>
//Globals
// Defines
#define PAGE_SIZE 256
#define PHYSICAL_PAGE_COUNT 64
#define LOGICAL_PAGE_COUNT 256
typedef enum { false, true } bool;
// Structs and Enums
typedef enum
{
false,
true
} bool;
int numPageFaults = 0;
struct MemoryAddress {
struct MemoryAddress
{
unsigned short int address;
unsigned int pageNumber;
unsigned int offset;
unsigned int runNumber; // Run Number
};
struct PageTableEntry {
struct PageTableEntry
{
int pageNumber; // Physical Page Number
bool valid; // Valid bit defaults to false (page not loaded)
bool valid; // Valid bit defaults to false (page not loaded)
};
struct PageTableEntry RAMTracker[PHYSICAL_PAGE_COUNT]; // Physical RAM Tracker
struct PageTableEntry LogicalRAMTracker[LOGICAL_PAGE_COUNT]; // Logical RAM Tracker
// Globals
int numPageFaults = 0;
struct PageTableEntry RAMTracker[PHYSICAL_PAGE_COUNT]; // Physical RAM Tracker
struct PageTableEntry LogicalRAMTracker[LOGICAL_PAGE_COUNT]; // Logical RAM Tracker
unsigned char RAM[PHYSICAL_PAGE_COUNT][PAGE_SIZE] = {[0 ... 63] = {[0 ... 255] = 0}}; // RAM initialized to 0s
unsigned short int addresses[512]; // Randomly generated logical addresses
int leastRecentlyUsedCalculation[PHYSICAL_PAGE_COUNT] = { [0 ... 63] = 0 }; // LRU calculation array
unsigned short int addresses[512]; // Randomly generated logical addresses
int leastRecentlyUsedCalculation[PHYSICAL_PAGE_COUNT] = {[0 ... 63] = 0}; // LRU calculation array
// Methods for VirtualMemory
struct MemoryAddress generateAddress(unsigned short int logicalAddress, unsigned int runNumber) {
// Generates a MemoryAddress datatype from the current address, as well as calculates page and offset
struct MemoryAddress generateAddress(unsigned short int logicalAddress, unsigned int runNumber)
{
unsigned short int offsetbitMask = 0b0000000011111111;
struct MemoryAddress generatedAddress;
// 16 bits for address ( 8 page, 8 offset)
generatedAddress.address = logicalAddress; // Set the logical address
generatedAddress.pageNumber = logicalAddress >> 8; // Moves 8 to the left (leaving page)
generatedAddress.address = logicalAddress; // Set the logical address
generatedAddress.pageNumber = logicalAddress >> 8; // Moves 8 to the right (leaving page)
generatedAddress.offset = logicalAddress & offsetbitMask; // Applies the bitmask to get the offset
generatedAddress.runNumber = runNumber; // Set the run number
generatedAddress.runNumber = runNumber; // Set the run number
return generatedAddress;
}
int LRU() {
// Least Recently Used (LRU) Algorithm
int LRU()
{
// Find the least recently used page
// Start at 0 and work down
int oldestPage = 0; // Initialize the oldest page to 0
int oldestPage = 0; // Initialize the oldest page to 0
int oldestRunNumber = leastRecentlyUsedCalculation[0]; // Initialize the oldest run number
for (int i = 1; i < PHYSICAL_PAGE_COUNT; i++) {
if (leastRecentlyUsedCalculation[i] < oldestRunNumber) {
oldestPage = i; // Update the oldest page
for (int i = 1; i < PHYSICAL_PAGE_COUNT; i++)
{
if (leastRecentlyUsedCalculation[i] < oldestRunNumber)
{
oldestPage = i; // Update the oldest page
oldestRunNumber = leastRecentlyUsedCalculation[i]; // Update the oldest run number
}
}
@@ -64,11 +77,16 @@ int LRU() {
return oldestPage; // Return the page number of the least recently used page
}
void loadIntoRAM(unsigned int logicalPageNumber) {
// Loads a DiskPage into RAM via its logical page number
// If there is no free page, it will use the LRU algorithm to find a victim page
void loadIntoRAM(unsigned int logicalPageNumber)
{
// Determine if there is a free page in RAM
int physicalPageNumber = -1;
for (int i = 0; i < PHYSICAL_PAGE_COUNT; i++) {
if (RAMTracker[i].valid == false) {
for (int i = 0; i < PHYSICAL_PAGE_COUNT; i++)
{
if (RAMTracker[i].valid == false)
{
physicalPageNumber = i; // Found a free page
printf("Found Free Frame %d in memory\n", physicalPageNumber);
break;
@@ -76,17 +94,22 @@ void loadIntoRAM(unsigned int logicalPageNumber) {
}
// If no free page, find "victim" page using LRU algorithm
if (physicalPageNumber == -1) physicalPageNumber = LRU();
if (physicalPageNumber == -1)
{
printf("No Free Page Frame. Invoking LRU Page Replacement Algorithm\n");
physicalPageNumber = LRU();
}
// Load from file into RAM using the free page number
FILE *fp = fopen("Back.bin", "rb"); // Open file for reading
unsigned char buf[256];
unsigned char buf[PAGE_SIZE];
fseek(fp, logicalPageNumber * PAGE_SIZE, SEEK_SET); // Move to target page
fread(buf, PAGE_SIZE, 1, fp); // Pull out page from the file
fclose(fp); // Close file
fread(buf, PAGE_SIZE, 1, fp); // Pull out page from the file
fclose(fp); // Close file
// Update RAM
for (int i = 0; i < PAGE_SIZE; i++) {
for (int i = 0; i < PAGE_SIZE; i++)
{
RAM[physicalPageNumber][i] = buf[i]; // Load the page into RAM
}
@@ -98,14 +121,20 @@ void loadIntoRAM(unsigned int logicalPageNumber) {
printf("Logical Page %d Now Mapped to Physical Page %d\n", logicalPageNumber, physicalPageNumber);
}
void readFromAddress(struct MemoryAddress logicalAddress) {
// Outermost method to initiate reading from a specific logical address
// Takes a MemoryAddress struct as input
void readFromAddress(struct MemoryAddress logicalAddress)
{
// Check if page is already loaded into RAM
if (LogicalRAMTracker[logicalAddress.pageNumber].valid != true) {
if (LogicalRAMTracker[logicalAddress.pageNumber].valid != true)
{
// Page is not loaded into RAM, so we need to calculate and load it
numPageFaults++;
printf("Page Not Mapped. Page Fault Number %d.\n", numPageFaults);
loadIntoRAM(logicalAddress.pageNumber); // Load the page into RAM
} else {
}
else
{
printf("Logical Page %d is in memory and mapped to Physical Page %d\n", logicalAddress.pageNumber, LogicalRAMTracker[logicalAddress.pageNumber].pageNumber);
}
@@ -116,33 +145,49 @@ void readFromAddress(struct MemoryAddress logicalAddress) {
// Page confirmed to be in RAM, so we can read from it
printf("Final address is Physical Page: %d Offset: %d\n", physicalPageNumber, logicalAddress.offset); // Print the final address
unsigned char data = RAM[physicalPageNumber][logicalAddress.offset]; // Read the data from RAM
printf("The value at that address: %d\n", data); // Print the data
unsigned char data = RAM[physicalPageNumber][logicalAddress.offset]; // Read the data from RAM
printf("The value at that address: %d\n", data); // Print the data
}
void finalOutput() {
printf("Final Output:\n");
printf("%d Total Page Faults\n", numPageFaults);
// Final outputs as per homework guidelines
// Also outputs as table
void finalOutput()
{
printf("Final Output:\n\n");
printf("%d Total Page Faults\n\n", numPageFaults);
for (int i = 0; i < LOGICAL_PAGE_COUNT; i++) {
if (LogicalRAMTracker[i].valid) { printf("Logical Page %d Mapped to Physical Page %d\n", i, LogicalRAMTracker[i].pageNumber); }
else { printf("Logical Page %d Not Mapped\n", i); }
for (int i = 0; i < LOGICAL_PAGE_COUNT; i++)
{
if (LogicalRAMTracker[i].valid)
{
printf("Logical Page %d Mapped to Physical Page %d\n", i, LogicalRAMTracker[i].pageNumber);
}
else
{
printf("Logical Page %d Not Mapped\n", i);
}
}
printf("\n\n");
printf("State of Physical RAM:\n");
printf("Logical Page Mappings:\n");
printf("Address = Row * 16 + Column (in Hex)\n");
printf("I.E: F (15) * 16 + F (15) = 255\n");
for (int col = 0; col < 16; col++) printf("\t%X", col);
printf("I.E: F (15) * 16 + F (15) = 255\n\n");
for (int col = 0; col < 16; col++)
printf("\t%X", col);
printf("\n");
for (int row = 0; row < 16; row++) {
for (int row = 0; row < 16; row++)
{
printf("%X \t", row);
for (int col = 0; col < 16; col++) {
for (int col = 0; col < 16; col++)
{
int index = row * 16 + col;
if (LogicalRAMTracker[index].valid) {
if (LogicalRAMTracker[index].valid)
{
printf("%d \t", LogicalRAMTracker[index].pageNumber);
} else {
printf(" \t"); // X for not mapped
}
else
{
printf(" \t"); // blank for not mapped
}
}
printf("\n");
@@ -152,25 +197,27 @@ void finalOutput() {
main(int argc, char *argv[])
{
srand(9); // all get same addresses
for (int i = 0; i < 512; i++) addresses[i] = rand() % 65535; // Logical Address Generation
for (int i = 0; i < 512; i++)
addresses[i] = rand() % 65535; // Logical Address Generation
// Generate File Contents
unsigned char buf[256]; // Contents of a page
for (int i = 0; i < 256; i++) buf[i] = (unsigned char)i; // Fill with 0-255
unsigned char buf[PAGE_SIZE]; // Contents of a page
FILE *fp = fopen("Back.bin", "wb"); // Open file for writing
for (int i = 0; i < 256; i++) fwrite(buf, 256, 1, fp); // Write 255 pages
fclose(fp); // Close file
//End Generate File Contents
for (int i = 0; i < 256; i++)
buf[i] = (unsigned char)i; // Fill with 0-255
for (int i = 0; i < PAGE_SIZE; i++)
fwrite(buf, PAGE_SIZE, 1, fp); // Write 255 pages
fclose(fp); // Close file
for (int i = 0; i < 512; i++)
{
struct MemoryAddress logicalAddress = generateAddress(addresses[i], i); // Generate the address via the struct
printf("Reference %d. Logical Address %d\n", i, logicalAddress.address); // Print the logical address
struct MemoryAddress logicalAddress = generateAddress(addresses[i], i); // Generate the address via the struct
printf("Reference %d. Logical Address %d\n", i, logicalAddress.address); // Print the logical address
printf("Logical Page %d, Offset %d\n", logicalAddress.pageNumber, logicalAddress.offset); // Print the page number and offset
readFromAddress(logicalAddress); // Read from the address (and perform memory operations if required))
readFromAddress(logicalAddress); // Read from the address (and perform memory operations if required))
printf("\n");
}
finalOutput();
return 0;
BIN
View File
Binary file not shown.