Help with Read me file

profilejontha11
jgilchrist_lab1_code.zip

JGilchrist_lab1 Code.txt

/* * File: week1ECET360.cpp * Author: JGilchrist * * Created on November 5, 2013, 8:20 PM */ #pragma GCC diagnostic ignored "-Wwrite-strings" //compiler directive? Cplusplus.com #include <cstdlib> // for EXIT_SUCCESS and EXIT_FAILURE #include <iostream> // for cout, endl, and cin #include <stdio.h> #include <sys/wait.h> // for wait() #include <unistd.h> // for pipe(), read(), write(), close(), fork(), and _exit() using namespace std; /*************************************** *Used from the the partial code given ****************************************/ /* Commander Process: */ int main(int argc, char** argv) { int result = 0; int pfd[2]; pid_t cpid; //cpid of type integer defined types.h //Via Paul Nichols bool parentLoop = true;//control variable for write loop, break?CPlusplus.con char userInput; //user input if (pipe(pfd) == -1) {//creating the pipe perror("pipe failed"); exit(EXIT_FAILURE); } //fork a child process after the pipe is made so they both have same PFD via http://www.advancedlinuxprogramming.com/alp-folder/alp-ch03-processes.pdf cpid = fork(); if (cpid == -1) {//if fork returned error exit perror("fork failed"); //via Paul Nichols exit(EXIT_FAILURE); } //wait for a second so child doesnt write over parent sleep(1);//linux sleep 1 second if using windows Sleep(milliseconds) if(cpid != 0) { //this is the parent-->Commander process************************************************* close(pfd[0]); //closing read end on parent...parent only writes cout << "commands are 'Q', 'U', 'P', or 'T' to quit"<<endl; while(parentLoop == true){ sleep(1);//linux sleep 1 second if using windows Sleep(milliseconds) cout << "enter a command: "; cin >> userInput; cout << endl; // cout for the user input if((userInput=='Q') || (userInput=='U')||(userInput=='P')){ /************************************************************************************ * The commander process accepts four commands: Used from the ILab Tab * 1. Q: End of one unit of time. * 2. U: Unblock the first simulated process in blocked queue. * 3. P: Print the current state of the system. * 4. T: Print the average turn around time, and terminate the system. *************************************************************************************/ //write info to pipe if(write(pfd[1], &userInput, sizeof(userInput)) < 0) exit(EXIT_FAILURE); //sleep(.5);//linux sleep 1 second if using windows Sleep(milliseconds) } else if(userInput == 'T'){ cout << "user input is T...Terminating parent" << endl; parentLoop = false; if(write(pfd[1], &userInput, 1) < 0){ perror("pipe write failed"); exit(EXIT_FAILURE); } } else { cout << "invalid input, please enter values of 'Q', 'U', 'P', or 'T' to quit\n" << endl; } } cout << "waiting for child process to close.."<<endl; close(pfd[1]);//close write end of pipe wait(NULL);// wait for child to close exit(EXIT_SUCCESS); }//end of parent process code**************************************************************************** else { //this is child--swap--> Process Manager process //execl( project_manager_loc , "Project_Manager", argv[1], &string1[0], (char *) 0); close(pfd[1]);//close write end of pipe char *project_manager_loc = "./Project_Manager"; char string1[12]; // A 32 bit number can't take more than 11 characters, + a terminating 0 snprintf(string1,12,"%i",pfd[0]); // Copy the file descriptor into a string char *args_1[] = {"Project_Manager", argv[0], &string1[0], (char *) 0}; execve( project_manager_loc , args_1, NULL); cout << "Error executing child...can not open" << endl; close(pfd[0]); cout << "exiting" << endl; }//end process _exit(result); }

Archive created by free jZip.url

[InternetShortcut] URL=http://www.jzip.com/archive_link

JGilchrist_Ilab2_execution_file.txt

/* * File: week1ECET360Execution.cpp * Author: JGilchrist * Tutor: Paul Nichols * References used: http://www.advancedlinuxprogramming.com/alp-folder/alp-ch03-processes.pdf * cplusplus.com, stackedoverflow.com * Created on November 10, 2013, 6:20 PM */ #include <cctype> // for toupper() #include <cstdlib> // for EXIT_SUCCESS and EXIT_FAILURE #include <cstring> // for strerror() #include <cerrno> // for errno #include <deque> // for deque (used for ready and blocked queues) #include <fstream> // for ifstream (used for reading simulated process programs) #include <iostream> // for cout, endl, and cin #include <sstream> // for stringstream (for parsing simulated process programs) #include <sys/wait.h> // for wait() #include <unistd.h> // for pipe(), read(), write(), close(), fork(), and _exit() #include <vector> // for vector (used for PCB table) #include <stdexcept> // std::out_of_range using namespace std; class Instruction {//file instruction format public: char operation; int intArg; string stringArg; }; /********************************************************************************************************* * Cpu is used to simulate the execution of a simulated process that is in running state. * It should include data members to store a pointer to the program array, current program counter value, * integer value, and time slice of that simulated process. In addition, it should store the number of * time units used so far in the current time slice. *********************************************************************************************************/ class Cpu { public: vector<Instruction> *pProgram;//this is a pointer to PcbEntry.program int programCounter; int value; int timeSlice;//curent time slice int timeSliceUsed;//time units used so far in current time slice }; enum State {//curent state of pcbEntry STATE_READY, STATE_RUNNING, STATE_BLOCKED }; class PcbEntry {//class of values to save in PCB table public: int processId; int parentProcessId; vector<Instruction> program;//program is a list Instruction class objects(char operation, int, string) unsigned int programCounter; int value; unsigned int priority; State state; unsigned int startTime; // For iLab 3, unused for iLab 2 unsigned int timeUsed; // For iLab 3, unused for iLab 2 }; unsigned int timestamp = 0; // The current simulation time. Cpu cpu; // The current CPU state. // For the states below, -1 indicates empty (since it is an invalid index).***see State description /***************************************************************************************************** * RunningState stores the PcbTable index of the currently running simulated process. *******************************************************************************************************/ int runningState = -1; // The index of the running process in the PCB table. /**************************************************************************************************** * ReadyState stores all simulated processes (PcbTable indices) that are ready to run. * This can be implemented using a queue or priority queue data structure. ****************************************************************************************************/ deque<int> readyState; // A queue of PCB indices for ready processes.(index) /***************************************************************************************************** * BlockedState stores all processes (PcbTable indices) that are currently blocked. * This can be implemented using a queue data structure. *******************************************************************************************************/ deque<int> blockedState; // A queue of PCB indices for blocked processes. // In this implementation, we'll never explicitly clear PCB entries and the // index in the table will always be the process ID. These choices waste memory, // but since this program is just a simulation it the easiest approach. // Additionally, debugging is simpler since table slots and process IDs are // never re-used. /********************************************************************************************************* * PcbTable is an array with one entry for every simulated process that hasn't finished its execution yet. * Each entry should include data members to store process id, parent process id, a pointer to program counter * value (initially 0), integer value, priority, state, start time, and CPU time used so far. ********************************************************************************************************/ vector<PcbEntry *> pcbTable; double cumulativeTimeDiff = 0; int numTerminatedProcesses = 0; // Sadly, C++ has no built-in way to trim strings: string& trim(string &argument) { string whitespace(" \t\n\v\f\r"); size_t found = argument.find_last_not_of(whitespace); if (found != string::npos) { argument.erase(found + 1); argument.erase(0, argument.find_first_not_of(whitespace)); } else { argument.clear(); // all whitespace } return argument; } bool createProgram(const string &filename, vector<Instruction> &program) { cout << "running creatProgram process " << endl; ifstream file; //open a stream to "init" named file int lineNum = 0; file.open(filename.c_str()); if (!file.is_open()) { cout << " file open: Error opening file " << filename << endl; return false; } while (file.good()) {//------------------- process init file -------------------------------------------- string line; getline(file, line); cout << " read from " << filename.c_str() << " : " << line << endl; trim(line); if (line.size() > 0) { Instruction instruction; instruction.operation = toupper(line[0]); instruction.stringArg = trim(line.erase(0, 1)); stringstream argStream(instruction.stringArg); switch (instruction.operation) { case 'S': // Integer argument. case 'A': // Integer argument. case 'D': // Integer argument. case 'F': // Integer argument. if (!(argStream >> instruction.intArg)) { cout << filename << ":" << lineNum << " - Invalid integer argument " << instruction.stringArg << " for " << instruction.operation << " operation" << endl; file.close(); return false; } break; case 'B': // No argument. case 'E': // No argument. break; case 'R': // String argument. // Note that since the string is trimmed on both ends, // filenames with leading or trailing whitespace (unlikely) // will not work. if (instruction.stringArg.size() == 0) { cout << filename << ":" << lineNum << " - Missing string argument" << endl; file.close(); return false; } break; default: cout << filename << ":" << lineNum << " - Invalid operation, " << instruction.operation << endl; file.close(); return false; } program.push_back(instruction); } lineNum++; }//-------------------------------- finished processing the file -------------------------/ file.close(); return true; } /********************************************************************************************* * Instructions S, A and D update the integer value stored in Cpu. ********************************************************************************************/ void set(int value){ cpu.value = value; cout << "running set process...setting cpu value to "<< cpu.value << endl; } void add(int value){ cpu.value = cpu.value + value; cout << "running +add process new cpu value = "<< cpu.value << endl; } void decrement(int value){ cpu.value = cpu.value - value; cout << "running -decrement process new cpu value = " << cpu.value << endl; } // Performs scheduling. void schedule() { cout << "running schedule process "; cout << " PID = " << runningState << " "; // 1. Return if there is still a processing running (runningState != -1). if (runningState == -1 && !readyState.empty()){//nothing running and process is in queue // 2. Get a new process to run, if possible, from the readystate queue. runningState = readyState.front();//retrieve the index of the pcbTable that is ready to run cout << "...loading new process from que pid is " << runningState << endl; readyState.pop_front();//remove it from queue push back-->pop front; // 3. If we were able to get a new process to run: // a. Mark the processing as running (update new process's PCB state) //***warning*** if pcbTable[location] does not exist you are exited!!!! pcbTable[runningState]->state = STATE_RUNNING; //cout << "SET NEW RUNNING STATE" << endl; // b. Update the CPU structure with the PCB entry details (program, // program counter, value, etc.) cpu.pProgram = &pcbTable[runningState]->program;//the whole list //cout << "SET NEW PROGRAM" << endl; cpu.programCounter = pcbTable[runningState]->programCounter; //cout << "SET NEW PROGRAM COUNTER" << endl; cpu.value = pcbTable[runningState]->value; //cout << "SET NEW VALUE" << endl; cpu.timeSlice = pcbTable[runningState]->startTime; //cout << "SET NEW TIMESLICE" << endl; cpu.timeSliceUsed = pcbTable[runningState]->timeUsed; } else if ((runningState == -1)&& (readyState.empty())) cout << "nothing in queue and nothing running blocked state = " << blockedState.size()<< " try and Unblock "<< endl; else cout << "...process is running" << endl; } /****************************************************************************************** * Instruction B moves the currently running simulated process to the blocked state * and moves a process from the ready state to the running state. * This will result in a context switch. *****************************************************************************************/ void block() { cout << "running block process " << endl; // 1. Add the PCB index of the running process (stored in runningState) to // the blocked queue. blockedState.push_back(runningState);//push back pull front // 2. Update the process's PCB entry // a. Change the PCB's state to blocked. // b. Store the CPU program counter in the PCB's program counter. // c. Store the CPU's value in the PCB's value cout << " adding pid = " << pcbTable[runningState]->processId << " to the block queue" <<endl; pcbTable[runningState]->state = STATE_BLOCKED; pcbTable[runningState]->programCounter = cpu.programCounter; pcbTable[runningState]->value = cpu.value; // 3. Update the running state to -1 (basically mark no process as running). // Note that a new process will be chosen to run later (via the Q command // code calling the schedule() function). runningState = -1; } /****************************************************************************************** * Instruction E terminates the currently running simulated process, frees up all memory * (e.g. program array) associated with that process and updates the PcbTable. * A simulated process from the ready state is moved to running state. * This also results in a context switch. *******************************************************************************************/ void end() { cout << "running end process " << endl; // TODO:Get the PCB entry of the running process. cumulativeTimeDiff = timestamp + 1 - pcbTable[runningState]->startTime; ++numTerminatedProcesses; runningState = -1; // memory will get freed when the simulation terminates. } /******************************************************************************************************* * Instruction F results in the creation of a new simulated process. A new entry is created in * the PcbTable for this new simulated process. A new (unique) process id is assigned and the * parent process id is process id of the parent simulated process. Start time is set to the current * Time value and CPU time used so far is set to 0. The program array and integer value of the new * simulated process are a copy of the program array and integer value of the parent simulated process. * The new simulated process has the same priority as the parent simulated process. * * The program counter value of the new simulated process is set to the instruction immediately * after the F instruction, while the program counter value of the of the parent simulated process * is set to n instructions after the next instruction (instruction immediately after F). * * The new simulated process is created in the ready state. *******************************************************************************************************/ void fork(int value) { cout << "running fork process " << endl; PcbEntry *myPCB = new PcbEntry(); myPCB->program = pcbTable[runningState]->program; if ((value > -2) && (value < 1000)){//ensure passed in method not out of bounds try{//catch all out of range myPCB->processId = pcbTable.size();//a PCB index+table.size myPCB->parentProcessId = pcbTable[runningState]->processId; myPCB->programCounter = cpu.programCounter; myPCB->value = cpu.value; myPCB->priority = pcbTable[runningState]->priority; myPCB->state = STATE_READY;//dont forget to add to ready queue myPCB->startTime = timestamp; pcbTable.push_back(myPCB);//queue push back, pull front readyState.push_back(myPCB->processId); cpu.programCounter = cpu.programCounter + value; cout << " forked process, pid = " << myPCB->processId << " and pushed it to the ready queue" << endl; } catch (const out_of_range& oor) { std::cerr << "Out of Range error: " << oor.what() << '\n'; } catch(const runtime_error& re) { cout << "Exception caught: " << re.what() << '\n'; } } else cout << "value is out of bounds" << endl; } /****************************************************************************************************** * The R instruction results in replacing the process image of the currently * running simulated process. Its program array is overwritten by the code in file filename, * program counter value is set to 0, and integer value is undefined. Note that all these changes * are made only in the Cpu data structure. Process id, parent process id, start time, * CPU time used so far, state, and priority remain unchanged. *****************************************************************************************************/ void replace(string &argument) { cout << "running replace process opening file " << endl; cpu.pProgram->clear();//shouldnt I read argument first? cout << "replace argument is " << argument << endl; if (!createProgram(argument, *cpu.pProgram)) {//storing file into pProgram cout << " ERROR can not open file!" << endl; cpu.programCounter = cpu.programCounter + 1; //do more error handling } else { cpu.programCounter = 0; cout << " createprogram..sucess" << endl; } } // Implements the Q command. /***************************************************************************************************** * On receiving a Q command, * the process manager executes the next instruction of the currently running simulated process, * increments program counter value (except for F or R instructions), increments Time, * and then performs scheduling. Note that scheduling may involve performing context switching. *****************************************************************************************************/ void quantum() { cout << "starting quantum process " << endl; Instruction instruction; if (runningState == -1) { cout << "No processes are running" << endl; ++timestamp; return; } if (cpu.programCounter < cpu.pProgram->size()) { instruction = (*cpu.pProgram)[cpu.programCounter]; cpu.programCounter++; } else { cout << "End of program reached without E operation" << endl; instruction.operation = 'E'; } switch (instruction.operation) { case 'S': set(instruction.intArg); break; case 'A': add(instruction.intArg); break; case 'D': decrement(instruction.intArg); break; case 'B': block(); break; case 'E': end(); break; case 'F': fork(instruction.intArg); break; case 'R': replace(instruction.stringArg); break; } ++timestamp; schedule(); } // Implements the U command. void unblock() { cout << "entered unblocked method" << endl; if(!blockedState.empty()){//check for empty queue int pcbIndex = blockedState.front(); cout << " unblocking PID = " << pcbIndex << " adding it to ready que" << endl; blockedState.pop_front(); readyState.push_back(pcbIndex); pcbTable[pcbIndex]->state = STATE_READY; schedule(); } else {cout << " blocked buffer was empty" << endl; } } /************************************************************************************************* * On receiving a P command, the process manager spawns a new reporter process. ************************************************************************************************/ void print() { cout << "Print command is not implemented until iLab 3" << endl; } // Function that implements the process manager. /************************************************************************************************* * The process manager process simulates four process management functions: * 1. creation of new (simulated) processes, * 2. replacing the current process image of a simulated process with a new process image, * 3. management of process state transitions, * 4. process scheduling. *************************************************************************************************/ int runProcessManager(int fileDescriptor) { PcbEntry *pcbEntry = new PcbEntry(); const char *INITPATH = "init"; // Attempt to create the init process. /******************************************************************************************************* * The process manager creates[createProgram()] the first simulated process (process id = 0) program from an input file * (filename: init). This is the only simulated process created by the process manager on its own. * All other simulated processes are created in response to the execution of the F instruction * *****************************************************************************************************/ if (!createProgram(INITPATH , pcbEntry->program)) { delete pcbEntry; return EXIT_FAILURE; } /******************************************************************************************************** * The process manager maintains six data structures: They are in the pcbEntry class * Time, Cpu, PcbTable, {[state::] ReadyState, BlockedState, and RunningState.} ******************************************************************************************************/ pcbEntry->processId = pcbTable.size(); pcbEntry->parentProcessId = -1; pcbEntry->programCounter = 0; pcbEntry->value = 0; pcbEntry->priority = 0; pcbEntry->state = STATE_RUNNING; // Time is an integer variable initialized to zero. pcbEntry->startTime = 0; pcbEntry->timeUsed = 0; /********************************************************************************************************* * PcbTable is an array with one entry for every simulated process that hasn't finished its execution yet. * Each entry should include data members to store process id, parent process id, a pointer to program counter * value (initially 0), integer value, priority, state, start time, and CPU time used so far. ********************************************************************************************************/ pcbTable.push_back(pcbEntry); runningState = pcbEntry->processId; cout << "Running init process, pid = " << pcbEntry->processId << endl; /********************************************************************************************************* * Cpu is used to simulate the execution of a simulated process that is in running state. * It should include data members to store a pointer to the program array, current program counter value, * integer value, and time slice of that simulated process. In addition, it should store the number of * time units used so far in the current time slice. *********************************************************************************************************/ cpu.pProgram = &(pcbEntry->program); cpu.programCounter = pcbEntry->programCounter; cpu.value = pcbEntry->value; timestamp = 0; double avgTurnaroundTime = 0; // Loop until a 'T' is read, then terminate. char ch; do { // Read a command character from the pipe. /**************************************************************************************************** * After creating the first process and initializing all its data structures, * the process manager repeatedly receives and processes one command at a time * from the commander process (read via the pipe). * **************************************************************************************************/ if (read(fileDescriptor, &ch, sizeof(ch)) != sizeof(ch)) { // Assume the parent process exited, breaking the pipe. break; } // Ignore whitespace characters. if (isspace(ch)) { continue; } // Convert commands to a common case so both lower and uppercase // commands can be used. ch = toupper(ch); switch (ch) { case 'Q': quantum(); break; case 'U': unblock(); break; case 'P': print(); break; /****************************************************************************************** * On receiving a T command, the process manager first spawns a reporter process and then * terminates after termination of the reporter process. The process manager ensures that * no more than one reporter process is running at any moment. *****************************************************************************************/ case 'T': if (numTerminatedProcesses != 0) { avgTurnaroundTime = cumulativeTimeDiff / (double)numTerminatedProcesses; } cout << "The average turnaround time is " << avgTurnaroundTime << "." << endl; break; default: cout << "Unknown command, " << ch << endl; } } while (ch != 'T'); // Cleanup any remaining PCB entries. for (vector<PcbEntry *>::iterator it = pcbTable.begin(); it != pcbTable.end(); it++) { delete *it; } pcbTable.clear(); return EXIT_SUCCESS; } //recieves a pipe descriptor int main(int argc, char** argv) { //variables} int result; int pfd[2]; //read arguments if(argc < 3) { cout << "You must provide a pipe adress descriptor " << endl; // Keeep command window open until user presses ENTER key cout << "Press ENTER key to exit" << endl; cin.ignore( ); exit(0); } pfd[0] = atoi(argv[2]); // Run the process manager. result = runProcessManager(pfd[0]); // Close the read end of the pipe for the process manager process (for // cleanup purposes). cout << "closing pipe...GOODBYE" << endl; close(pfd[0]);//close read end of pipe //exit (using the _exit() system call). exit(result); // Keeep command window open until user presses ENTER key cout << "Press ENTER key to exit" << endl; cin.ignore( ); return(0); }

JGilchrist_lab2 Code.txt

/* * File: week1ECET360.cpp * Author: JGilchrist * * Created on November 5, 2013, 8:20 PM */ #pragma GCC diagnostic ignored "-Wwrite-strings" //compiler directive? Cplusplus.com #include <cstdlib> // for EXIT_SUCCESS and EXIT_FAILURE #include <iostream> // for cout, endl, and cin #include <stdio.h> #include <sys/wait.h> // for wait() #include <unistd.h> // for pipe(), read(), write(), close(), fork(), and _exit() using namespace std; /*************************************** *Used from the the partial code given ****************************************/ /* Commander Process: */ int main(int argc, char** argv) { int result = 0; int pfd[2]; pid_t cpid; //cpid of type integer defined types.h //Via Paul Nichols bool parentLoop = true;//control variable for write loop, break?CPlusplus.con char userInput; //user input if (pipe(pfd) == -1) {//creating the pipe perror("pipe failed"); exit(EXIT_FAILURE); } //fork a child process after the pipe is made so they both have same PFD via http://www.advancedlinuxprogramming.com/alp-folder/alp-ch03-processes.pdf cpid = fork(); if (cpid == -1) {//if fork returned error exit perror("fork failed"); //via Paul Nichols exit(EXIT_FAILURE); } //wait for a second so child doesnt write over parent sleep(1);//linux sleep 1 second if using windows Sleep(milliseconds) if(cpid != 0) { //this is the parent-->Commander process************************************************* close(pfd[0]); //closing read end on parent...parent only writes cout << "commands are 'Q', 'U', 'P', or 'T' to quit"<<endl; while(parentLoop == true){ sleep(1);//linux sleep 1 second if using windows Sleep(milliseconds) cout << "enter a command: "; cin >> userInput; cout << endl; // cout for the user input if((userInput=='Q') || (userInput=='U')||(userInput=='P')){ /************************************************************************************ * The commander process accepts four commands: Used from the ILab Tab * 1. Q: End of one unit of time. * 2. U: Unblock the first simulated process in blocked queue. * 3. P: Print the current state of the system. * 4. T: Print the average turn around time, and terminate the system. *************************************************************************************/ //write info to pipe if(write(pfd[1], &userInput, sizeof(userInput)) < 0) exit(EXIT_FAILURE); //sleep(.5);//linux sleep 1 second if using windows Sleep(milliseconds) } else if(userInput == 'T'){ cout << "user input is T...Terminating parent" << endl; parentLoop = false; if(write(pfd[1], &userInput, 1) < 0){ perror("pipe write failed"); exit(EXIT_FAILURE); } } else { cout << "invalid input, please enter values of 'Q', 'U', 'P', or 'T' to quit\n" << endl; } } cout << "waiting for child process to close.."<<endl; close(pfd[1]);//close write end of pipe wait(NULL);// wait for child to close exit(EXIT_SUCCESS); }//end of parent process code**************************************************************************** else { //this is child--swap--> Process Manager process //execl( project_manager_loc , "Project_Manager", argv[1], &string1[0], (char *) 0); close(pfd[1]);//close write end of pipe char *project_manager_loc = "./Project_Manager"; char string1[12]; // A 32 bit number can't take more than 11 characters, + a terminating 0 snprintf(string1,12,"%i",pfd[0]); // Copy the file descriptor into a string char *args_1[] = {"Project_Manager", argv[0], &string1[0], (char *) 0}; execve( project_manager_loc , args_1, NULL); cout << "Error executing child...can not open" << endl; close(pfd[0]); cout << "exiting" << endl; }//end process _exit(result); }

week2.png

JGilchrist_Lab3_7.txt

#define ENABLE_COMMANDER #define ENABLE_REPORTER #include <cctype> // for toupper() #include <cstdlib> // for EXIT_SUCCESS and EXIT_FAILURE #include <cstring> // for strerror() #include <cerrno> // for errno #include <deque> // for deque (used for ready and blocked queues) #include <fstream> // for ifstream (used for reading simulated process programs) #include <iostream> // for cout, endl, and cin #include <sstream> // for stringstream (for parsing simulated process programs) #include <sys/wait.h> // for wait() #include <unistd.h> // for pipe(), read(), write(), close(), fork(), and _exit() #include <vector> // for vector (used for PCB table) using namespace std; class Instruction { public: char operation; int intArg; string stringArg; }; class Cpu { public: vector<Instruction> *pProgram; int programCounter; int value; int timeSlice; int timeSliceUsed; }; enum State { STATE_READY, STATE_RUNNING, STATE_BLOCKED, STATE_END }; class PcbEntry { public: int processId; int parentProcessId; vector<Instruction> program; unsigned int programCounter; int value; unsigned int priority; State state; unsigned int startTime; unsigned int timeUsed; }; // The number of valid priorities. #define NUM_PRIORITIES 4 // An array that maps priorities to their allotted time slices. static const unsigned int PRIORITY_TIME_SLICES[NUM_PRIORITIES] = { 1, 2, 4, 8 }; unsigned int timestamp = 0; Cpu cpu; // For the states below, -1 indicates empty (since it is an invalid index). int runningState = -1; // The index of the running process in the PCB table. // readyStates is an array of queues. Each queue holds PCB indices for ready processes // of a particular priority. deque<int> readyStates[NUM_PRIORITIES]; deque<int> blockedState; // A queue fo PCB indices for blocked processes. deque<int> deadState; // In this implementation, we'll never explicitly clear PCB entries and the // index in the table will always be the process ID. These choices waste memory, // but since this program is just a simulation it the easiest approach. // Additionally, debugging is simpler since table slots and process IDs are // never re-used. vector<PcbEntry *> pcbTable; double cumulativeTimeDiff = 0; int numTerminatedProcesses = 0; // Sadly, C++ has no built-in way to trim strings: string &trim(string &argument) { string whitespace(" \t\n\v\f\r"); size_t found = argument.find_last_not_of(whitespace); if (found != string::npos) { argument.erase(found + 1); argument.erase(0, argument.find_first_not_of(whitespace)); } else { argument.clear(); // all whitespace } return argument; } bool createProgram(const string &filename, vector<Instruction> &program) { ifstream file; int lineNum = 0; program.clear(); file.open(filename.c_str()); if (!file.is_open()) { cout << "Error opening file " << filename << endl; return false; } while (file.good()) { string line; getline(file, line); trim(line); if (line.size() > 0) { Instruction instruction; instruction.operation = toupper(line[0]); instruction.stringArg = trim(line.erase(0, 1)); stringstream argStream(instruction.stringArg); switch (instruction.operation) { case 'S': // Integer argument. case 'A': // Integer argument. case 'D': // Integer argument. case 'F': // Integer argument. if (!(argStream >> instruction.intArg)) { cout << filename << ":" << lineNum << " - Invalid integer argument " << instruction.stringArg << " for " << instruction.operation << " operation" << endl; file.close(); return false; } break; case 'B': // No argument. case 'E': // No argument. break; case 'R': // String argument. // Note that since the string is trimmed on both ends, // filenames with leading or trailing whitespace (unlikely) // will not work. if (instruction.stringArg.size() == 0) { cout << filename << ":" << lineNum << " - Missing string argument" << endl; file.close(); return false; } break; default: cout << filename << ":" << lineNum << " - Invalid operation, " << instruction.operation << endl; file.close(); return false; } program.push_back(instruction); } lineNum++; } file.close(); return true; } // Implements the S operation. void set(int value) { cpu.value = value; cout << "Set CPU value to " << value << endl; } // Implements the A operation. void add(int value) { cpu.value += value; cout << "Incremented CPU value by " << value << endl; } // Implements the D operation. void decrement(int value) { cpu.value -= value; cout << "Decremented CPU value by " << value << endl; } // Performs scheduling. void schedule() { // TODO: Debug and test //If runningState != -1 AND the cpu.timeSliceUsed equals or exceeds // cpu.timeSlice: cout <<" cpu timeslice Used " << cpu.timeSliceUsed<<endl; cout <<" cpu timeslice " << cpu.timeSlice<<endl; if ((runningState != -1) && (cpu.timeSliceUsed >= cpu.timeSlice)){ // 1. Get the PCB entry for runningState. PcbEntry *myPCB = pcbTable[runningState]; // 2. Lower the process priority (remember since the highest priority is zero, // you actually have to increment the priority to lower it). Also make sure to // not increment the priority past its maximum value. if (myPCB->priority >= 0 && myPCB->priority < (NUM_PRIORITIES - 1)) myPCB->priority++; // 3. Push runningState on to the end of the correct readyStates queue (hint: use // pcbEntry.priority to select the correct queue. switch (myPCB->priority) { case 0 : readyStates[0].push_back(runningState); break; case 1 : readyStates[1].push_back(runningState); break; case 2 : readyStates[2].push_back(runningState); break; case 3 : readyStates[3].push_back(runningState); break; default: cout << "Invalid running state" << endl; break; } // 4. Update the pcbEntry: // a. Set state to STATE_READY. // b. Set the programCounter to cpu.programCounter. // c. Set the value to cpu.value. // d. Increment timeUsed by cpu.timeSliceUsed. myPCB->state = STATE_READY; myPCB->programCounter = cpu.programCounter; myPCB->value = cpu.value; myPCB->timeUsed = myPCB->timeUsed + cpu.timeSliceUsed; cout << " time this process has used = " << myPCB->timeUsed << endl; cout << " scheduler is ending process and decreasing priority to "<< myPCB->priority <<"\n" << endl; // 5. Set runningState to -1. runningState = -1; } if (runningState != -1) {//the correct priority program is running cout << " correct process is running exiting scheduler" << endl; return; } cout << " loading new process from "; // TODO: Debug and test // Get a new process to run, if possible, from the ready queue in // priority order. Remember that the highest priority is zero! The code below // needs to be updated/replaced since right now it only uses the highest priority // queue. if(!readyStates[0].empty()){ runningState = readyStates[0].front(); cout << "priority 0 " << endl; readyStates[0].pop_front(); } else if(!readyStates[1].empty()){ runningState = readyStates[1].front(); cout << "priority 1" << endl; readyStates[1].pop_front(); } else if(!readyStates[2].empty()){ runningState = readyStates[2].front(); cout << "priority 2 " << endl; readyStates[2].pop_front(); } else if(!readyStates[3].empty()){ runningState = readyStates[3].front(); cout << "priority 3 " << endl; readyStates[3].pop_front(); } else cout << "ERROR ready state has invalid state entries"; // Make sure there is a process to run. if (runningState != -1) { // Mark the process as running. PcbEntry *pcbEntry = pcbTable[runningState]; pcbEntry->state = STATE_RUNNING; // Update the CPU with new PCB entry details. cpu.pProgram = &pcbEntry->program; cpu.programCounter = pcbEntry->programCounter; cpu.value = pcbEntry->value; // TODO: Debug and test // Set cpu.timeSlice to the correct value (hint: use the // global PRIORITY_TIME_SLICES array and pcbEntry->priority) switch (pcbEntry->priority) { case 0 : cpu.timeSlice = PRIORITY_TIME_SLICES[0]; cout << " setting cpu.timeslice to 1"<<endl; break; case 1 : cpu.timeSlice = PRIORITY_TIME_SLICES[1]; cout << " setting cpu.timeslice to 2"<<endl; break; case 2 : cpu.timeSlice = PRIORITY_TIME_SLICES[2]; cout << " setting cpu.timeslice to 4"<<endl; break; case 3 : cpu.timeSlice = PRIORITY_TIME_SLICES[3]; cout << " setting cpu.timeslice to 8"<<endl; break; default: cout << "ERROR setting cpu timeslice Invalid priority" << endl; break; } // TODO: Debug and test // Set cpu->timeSliceUsed to zero. cpu.timeSliceUsed = 0; cout << "Process running, pid = " << pcbEntry->processId << endl; } } // Implements the B operation. void block() { PcbEntry *pcbEntry = pcbTable[runningState]; //TODO there is a problem with pcb time used counter will this fix it pcbEntry->timeUsed += cpu.timeSliceUsed + 1;//add 1 for CPU time to block the process // TODO: Debug and test // Raise the process priority (remember since the highest priority is zero, // you actually have to decrement the priority to raise it). Also make sure to // not decrement the priority below zero. if (pcbEntry->priority > 0) pcbEntry->priority--; blockedState.push_back(runningState); pcbEntry->state = STATE_BLOCKED; pcbEntry->programCounter = cpu.programCounter; pcbEntry->value = cpu.value; runningState = -1; cout << "Blocked process, pid = " << pcbEntry->processId << endl; } // Implements the E operation. void end() { PcbEntry *pcbEntry = pcbTable[runningState]; //TODO there is a problem with pcb timused will this fix it? pcbEntry->timeUsed = pcbEntry->timeUsed + cpu.timeSliceUsed + 1;//add 1 to account for e operation // Add 1 to account for the time to execute the E operation. cumulativeTimeDiff += (double)(timestamp + 1 - pcbEntry->startTime); numTerminatedProcesses++; cout << "Ended process, pid = " << pcbEntry->processId << endl; pcbEntry->state = STATE_END; deadState.push_back(runningState); runningState = -1; } // Implements the F operation. void fork(int value) { int pcbIndex = (int)pcbTable.size(); PcbEntry *runningPcbEntry = pcbTable[runningState]; PcbEntry *pcbEntry = new PcbEntry(); pcbEntry->processId = pcbIndex; pcbEntry->parentProcessId = runningPcbEntry->processId; pcbEntry->program = runningPcbEntry->program; pcbEntry->programCounter = cpu.programCounter; pcbEntry->value = cpu.value; pcbEntry->priority = runningPcbEntry->priority; pcbEntry->state = STATE_READY; pcbEntry->startTime = timestamp + 1; pcbEntry->timeUsed = 0; pcbTable.push_back(pcbEntry); // TODO: debug and test //Update the line below to use the correct readyStates queue. readyStates[pcbEntry->priority].push_back(pcbIndex); cout << "Forked new process, pid = " << pcbEntry->processId << endl; if ((value < 0) || (cpu.programCounter + value >= (int)cpu.pProgram->size())) { cout << "Error executing F operation, ending parent process" << endl; end(); } cpu.programCounter += value; } // Implements the R operation. void replace(string &argument) { if (!createProgram(argument, *cpu.pProgram)) { cout << "Error executing R operation, ending process" << endl; end(); return; } cpu.programCounter = 0; cout << "Replaced process with " << argument << ", pid = " << pcbTable[runningState]->processId << endl; } // Implements the Q command. void quantum() { Instruction instruction; if (runningState == -1) { cout << "No processes are running" << endl; ++timestamp; return; } if (cpu.programCounter < (int)cpu.pProgram->size()) { instruction = (*cpu.pProgram)[cpu.programCounter]; cpu.programCounter++; } else { cout << "End of program reached without E operation" << endl; instruction.operation = 'E'; } switch (instruction.operation) { case 'S': set(instruction.intArg); break; case 'A': add(instruction.intArg); break; case 'D': decrement(instruction.intArg); break; case 'B': block(); break; case 'E': end(); break; case 'F': fork(instruction.intArg); break; case 'R': replace(instruction.stringArg); break; } timestamp++; // TODO: degug and test // Increment cpu.timeSliceUsed. cpu.timeSliceUsed++; schedule(); } // Implements the U command. void unblock() { if (!blockedState.empty()) { int pcbIndex = blockedState.front(); PcbEntry *pcbEntry = pcbTable[pcbIndex]; blockedState.pop_front(); // TODO: debug and test. PHIL << "this process does not increment the timeStamp, because it comes from Commander?" // Update the line below to use the correct readyStates queue. readyStates[pcbEntry->priority].push_back(pcbIndex); pcbEntry->state = STATE_READY; cout << "Unblocked process, pid = " << pcbEntry->processId << endl; } schedule(); } void printReadyQue(int *myArray){ for (unsigned int j = 0; j < NUM_PRIORITIES; j++){ if (!readyStates[j].empty()){ cout << "READY STATE PRIORITY " << j << " QUEUE:\n pid | ppid | priority | value | start time | cpu time used |" << endl; for (unsigned int i = 0; i < readyStates[j].size(); i++) { int pcbIndex = readyStates[j][i]; PcbEntry *pcbEntry = pcbTable[pcbIndex]; printf("% *d % *d % *d % *d % *d % *d \n" , 7 , pcbEntry->processId , 11, pcbEntry->parentProcessId, 10, pcbEntry->priority, 10, pcbEntry->value, 10, pcbEntry->startTime, 10, pcbEntry->timeUsed); myArray[j] = myArray[j]+1;//increment prioriety myArray[4] += pcbEntry->timeUsed;//sum } } } } void printProcess(int *myArray){ int myTimeUsed = 0; const int NUM_STATE = 4; State myState[NUM_STATE] = {STATE_READY , STATE_RUNNING, STATE_BLOCKED, STATE_END}; for (int j =1; j < NUM_STATE; j++){ switch (j) { case 1: cout << "RUNNING PROCESSSES:\n pid | ppid | priority | value | start time | cpu time used |" << endl; break; case 2: if (!blockedState.empty()) cout << "BLOCKED PROCESSSES:\n pid | ppid | priority | value | start time | cpu time used |" << endl; break; case 3: if (!deadState.empty()) cout << "DEAD PROCESSSES:\n pid | ppid | priority | value | start time | cpu time used |" << endl; break; default: cout << "ERROR!!!!!"; break; } for(unsigned int readyEntry = 0; readyEntry < pcbTable.size(); readyEntry++){ if (pcbTable[readyEntry]->state == myState[j] ){ if (pcbTable[readyEntry]->state == STATE_RUNNING)myTimeUsed = pcbTable[runningState]->timeUsed+cpu.timeSliceUsed; else myTimeUsed = pcbTable[readyEntry]->timeUsed; printf("% *d % *d % *d % *d % *d % *d \n" , 7 , pcbTable[readyEntry]->processId , 11, pcbTable[readyEntry]->parentProcessId, 10, pcbTable[readyEntry]->priority, 10, pcbTable[readyEntry]->value, 10, pcbTable[readyEntry]->startTime, 10, myTimeUsed); myArray[pcbTable[readyEntry]->priority]++;//increment prioriety myArray[4] += myTimeUsed; } } } } void printPriorieties(int *prioritieList){ cout << endl; for (int i =0; i<4; i++){ if ( prioritieList[i] != 0) cout << "number of processes with priority "<< i << " is: " << prioritieList[i] << endl; } if ((int)timestamp == prioritieList[4]) cout << "\nCURRENT TIME: " << timestamp << " = " << "total CPU TIME USED: "<< prioritieList[4] << endl; else cout << "PCB total time does not match this can only happen if no process was running" << endl; } // Implements the P command. void print() { #ifdef ENABLE_REPORTER pid_t pid; pid = fork(); if (pid == -1) { cout << "fork:" << strerror(errno) << endl; return; } if (pid != 0) { // Wait for the reporter process to exit. wait(NULL); return; } #endif #ifdef ENABLE_REPORTER // TODO: debug and test //Implement all of the printing logic. int prioritieList[NUM_PRIORITIES + 1] = {0,0,0,0,0};//+ one for sum[4] counter cout << "\n----------------------------------------------------------------------" << endl; //cout << "CURRENT TIME: " << timestamp<< endl; printReadyQue(prioritieList);//prints the processes in ready state by que printProcess(prioritieList);// prints the rest of the processes printPriorieties(prioritieList); cout << "----------------------------------------------------------------------\n"<<endl; _exit(EXIT_SUCCESS); #endif } // Function that implements the process manager. int runProcessManager(int fileDescriptor) { PcbEntry *pcbEntry = new PcbEntry(); // Attempt to create the init process. if (!createProgram("Users/JGilchrist/Desktop/ECET365/week1/" , pcbEntry->program)) { delete pcbEntry; return EXIT_FAILURE; } pcbEntry->processId = (int)pcbTable.size(); pcbEntry->parentProcessId = -1; pcbEntry->programCounter = 0; pcbEntry->value = 0; pcbEntry->priority = 0; pcbEntry->state = STATE_RUNNING; pcbEntry->startTime = 0; pcbEntry->timeUsed = 0; pcbTable.push_back(pcbEntry); runningState = pcbEntry->processId; cout << "Running init process, pid = " << pcbEntry->processId << endl; cpu.pProgram = &(pcbEntry->program); cpu.programCounter = pcbEntry->programCounter; cpu.value = pcbEntry->value; timestamp = 0; double avgTurnaroundTime = 0; // Loop until a 'T' is read, then terminate. char ch; do { // Read a command character from the pipe. if (read(fileDescriptor, &ch, sizeof(ch)) != sizeof(ch)) { // Assume the parent process exited, breaking the pipe. break; } // Ignore whitespace characters. if (isspace(ch)) { continue; } // Convert commands to a common case so both lower and uppercase // commands can be used. ch = toupper(ch); switch (ch) { case 'Q': quantum(); break; case 'U': unblock(); break; case 'P': print(); break; case 'T': if (numTerminatedProcesses != 0) { avgTurnaroundTime = cumulativeTimeDiff / (double)numTerminatedProcesses; } cout << "The average turnaround time is " << avgTurnaroundTime << "." << endl; break; default: cout << "Unknown command, " << ch << endl; break; } } while (ch != 'T'); // Cleanup any remaining PCB entries. for (vector<PcbEntry *>::iterator it = pcbTable.begin(); it != pcbTable.end(); it++) { delete *it; } pcbTable.clear(); return EXIT_SUCCESS; } // Main function that implements the commander. int main(int argc, char *argv[]) { #ifdef ENABLE_COMMANDER int pipeDescriptors[2]; pid_t processMgrPid; char ch; int result; // Create a pipe. if (pipe(pipeDescriptors) == -1) { // Print an error message to help debugging. cout << "pipe: " << strerror(errno) << endl; return EXIT_FAILURE; } // Create the process manager process. processMgrPid = fork(); if (processMgrPid == -1) { // Print an error message to help debugging. cout << "fork: " << strerror(errno) << endl; return EXIT_FAILURE; } if (processMgrPid == 0) { // The process manager process is running. // Close the unused write end of the pipe for the process manager // process. close(pipeDescriptors[1]); // Run the process manager. result = runProcessManager(pipeDescriptors[0]); // Close the read end of the pipe for the process manager process (for // cleanup purposes). close(pipeDescriptors[0]); _exit(result); } else { // The commander process is running. // Close the unused read end of the pipe for the commander process. close(pipeDescriptors[0]); // Loop until a 'T' is written or until the pipe is broken. do { sleep(1); cout << "Input a command: "; // Read a command character from the standard input. cin >> ch; cout << endl; // Pass commands to the process manager process via the pipe. if (write(pipeDescriptors[1], &ch, sizeof(ch)) != sizeof(ch)) { // Assume the child process exited, breaking the pipe. break; } } while (ch != 'T'); // Wait for the process manager to exit. wait(&result); // Close the write end of the pipe for the commander process (for // cleanup purposes). close(pipeDescriptors[1]); } return result; #else // Run the Process Manager directly. return runProcessManager(fileno(stdin)); #endif }

lab3_7.png