-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPager.cpp
More file actions
229 lines (212 loc) · 7 KB
/
Pager.cpp
File metadata and controls
229 lines (212 loc) · 7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
// FILE: Pager.cpp
// A Bautista, B Franco, E Mora
// OS, Fall 2023, Transy U
//
// Driver for pager that can take in a number of pages and frames, a memory address file for a process,
// a framesize in a power of two number of bytes, and a paging alogrithm type
// this then utilizes the type given and the other arguments to conduct page replacement
// using the specified algorithm and the memory addresses
//
// http://www.graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
// https://cplusplus.com/reference/vector/vector/
//
#include "Pager.h"
#include "Table.h"
#include "Random.h"
#include "FIFO.h"
#include "MFU.h"
#include "LRU.h"
#include <fstream>
#include <iostream>
#include <cstring>
#include <stdlib.h>
using namespace std;
int main(int argc, char **argv){
Random random;
FIFO fifo;
MFU mfu;
LRU lru;
queue<int> addresses;
ifstream inputFile;
string fileLine;
char type[INPUT_MAX], frames[INPUT_MAX], fileName[INPUT_MAX], pages[INPUT_MAX], frameSize[INPUT_MAX];
int fileIndex,id;
// ensures a default is present in case a value is not specified
strcpy(type,DEFAULT_TYPE);
strcpy(frames,DEFAULT_FRAMES);
strcpy(fileName,DEFAULT_FILE);
strcpy(pages,DEFAULT_PAGES);
strcpy(frameSize,DEFAULT_SIZE);
fileIndex = commandErrorCheck(argc, argv);
if(fileIndex == -1){
exit(1);
}
else if(fileIndex){
strcpy(fileName,argv[fileIndex]);
}
int typeOption=0,pageOption=0,frameOption=0,sizeOption=0;
// stores the value of each specified argument so that it can be used in page replacement
for(int i=1;i<argc;i++){
if(!strcmp(argv[i],TYPE)){
typeOption++;
strcpy(type,argv[i+1]);
}
else if(!strcmp(argv[i],PAGES)){
pageOption++;
strcpy(pages,argv[i+1]);
}
else if(!strcmp(argv[i],FRAMES)){
frameOption++;
strcpy(frames,argv[i+1]);
}
else if(!strcmp(argv[i],FRAME_SIZE)){
sizeOption++;
strcpy(frameSize,argv[i+1]);
}
}
// ensures that no argument was specified twice
if(repeatErrorCheck(typeOption,pageOption,frameOption,sizeOption)) exit(1);
//makes sure that input numbers are valid if not we gracefully exit
if(!inputErrorCheck(pages,frames,frameSize)){
inputFile.open(fileName);
if(inputFile){
string fileInput;
int address;
inputFile >> fileInput;
if(idErrorCheck(fileInput)) exit(1);
id = atoi(fileInput.substr(2,fileInput.length()).c_str());
inputFile >> fileInput;
while(!inputFile.eof()){
address = atoi(fileInput.c_str());
if(loadErrorCheck(address,atoi(frameSize),atoi(pages))) exit(1);
addresses.push(address);
inputFile >> fileInput;
}
inputFile.close();
}
else{
cout << "\tERROR: File not opened\n";
exit(1);
}
}
else{
exit(1);
}
cout << "Paging for P_" << id << ":\n";
int totalPageFaults;
Table table(atoi(pages),atoi(frames),atoi(frameSize));
// call the appropriate method depending on the value of type
if(!strcmp(type,FIRST_IN_FIRST_OUT)){
totalPageFaults = fifo.fifoPager(addresses,table);
}
else if(!strcmp(type,LEAST_RECENT_USED)){
totalPageFaults = lru.LRUpager(addresses,table);
}
else if(!strcmp(type,RANDOM)){
totalPageFaults = random.randomPager(addresses,table);
}
else if(!strcmp(type,MOST_FREQUENT_USED)){
totalPageFaults = mfu.mfuPager(addresses,table);
}
cout << "\tTotal Page Faults: " << totalPageFaults << endl;
return 0;
}
bool repeatErrorCheck(int typeOption, int pageOption, int frameOption, int sizeOption){
bool error = false;
if(typeOption>1){
cout << "\tERROR: " << TYPE << " has been entered multiple times\n";
error = true;
}
if(pageOption>1){
cout << "\tERROR: " << PAGES << " has been entered multiple times\n";
error = true;
}
if(frameOption>1){
cout << "\tERROR: " << FRAMES << " has been entered multiple times\n";
error = true;
}
if(sizeOption>1){
cout << "\tERROR: " << FRAME_SIZE << " has been entered multiple times\n";
error = true;
}
return error;
}
bool inputErrorCheck(string pages, string frames, string frameSize){
bool error = false;
if(atoi(pages.c_str()) <= 0 || pages.find('.')!=string::npos){
cout << "\tERROR: Pages must be a positive integer\n";
error = true;
}
if((atoi(frames.c_str()) <= 0 || atoi(frames.c_str()) > MAX_FRAMES) || frames.find('.')!=string::npos){
cout << "\tERROR: Frames must be a positive integer between 1 and " << MAX_FRAMES << "\n";
error = true;
}
if(atoi(frameSize.c_str()) <= 0 || frameSize.find('.')!=string::npos){
cout << "\tERROR: Frame size must be a positive integer\n";
error = true;
}
else{
unsigned int frameBytes = atoi(frameSize.c_str());
if((frameBytes & (frameBytes - 1)) != 0){
cout << "\tERROR: Frame size must be a power of two\n";
error = true;
}
}
return error;
}
int commandErrorCheck(int argc, char** argv){
bool error = false;
int fileIndex = 0;
if(!strcmp(argv[argc-1],TYPE) || !strcmp(argv[argc-1],PAGES) || !strcmp(argv[argc-1],FRAMES) || !strcmp(argv[argc-1],FRAME_SIZE)){
cout << "\tERROR: " << argv[argc-1] << " requires an input\n";
error = true;
}
else{
for(int i=1;i<argc;i++){
// if one of the inputs is not a valid option and does not come after an option with a parameter then error
if(strcmp(argv[i],TYPE) && strcmp(argv[i],PAGES) && strcmp(argv[i],FRAMES) && strcmp(argv[i],FRAME_SIZE)){
if(strcmp(argv[i-1],TYPE) && strcmp(argv[i-1],PAGES) && strcmp(argv[i-1],FRAMES) && strcmp(argv[i-1],FRAME_SIZE)){
if(i!=argc-1){
cout << "\tERROR: " << argv[i] << " is not a valid option\n";
error = true;
}
else{
fileIndex = i;
}
}
}
else if(!strcmp(argv[i],TYPE)){
if(strcmp(argv[i+1],FIRST_IN_FIRST_OUT) && strcmp(argv[i+1],LEAST_RECENT_USED) && strcmp(argv[i+1],MOST_FREQUENT_USED) && strcmp(argv[i+1],RANDOM)){
cout << "\tERROR: " << argv[i+1] << " is not a valid type {FIFO|LRU|MFU|RANDOM}\n";
error = true;
}
}
}
}
if(error){
return -1;
}
return fileIndex;
}
// framesize is in bytes
bool loadErrorCheck(int address,int pageSize, int pages){
bool error = false;
// check if address is possible within given frames and size
if((address/pageSize) >= pages){
cout << "\tERROR: Address " << address << " cannot exist within " << pages << " " << pageSize << " byte pages\n";
error = true;
}
return error;
}
bool idErrorCheck(string fileInput){
bool error = false;
if(fileInput.find("P_") != 0 || fileInput.length() < 3){
cout << "\tERROR: Process id is not of form P_#\n";
error = true;
}
else if(atoi(fileInput.substr(2,fileInput.length()).c_str()) < 0 || fileInput.find('.')!=string::npos){
cout << "\tERROR: Process id must be a non-negative number\n";
error = true;
}
return error;
}