Last active
October 15, 2023 13:58
-
-
Save firas-jolha/538b705fead7ece3f66947842258972c to your computer and use it in GitHub Desktop.
os-lab06-2023
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
idx at bt | |
0 5 2 | |
1 7 6 | |
2 20 3 | |
3 3 8 | |
4 2 4 | |
5 3 1 | |
6 10 6 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <signal.h> | |
#include <string.h> | |
#include <sys/wait.h> | |
#include <sys/time.h> | |
#define PS_MAX 10 | |
// holds the scheduling data of one process | |
typedef struct{ | |
int idx; // process idx (index) | |
int at, bt, rt, wt, ct, tat; // arrival time, burst time, response time, waiting time, completion time, turnaround time. | |
int burst; // remaining burst (this should decrement when the process is being executed) | |
} ProcessData; | |
// the idx of the running process | |
int running_process = -1; // -1 means no running processes | |
// the total time of the timer | |
unsigned total_time; // should increment one second at a time by the scheduler | |
// data of the processes | |
ProcessData data[PS_MAX]; // array of process data | |
// array of all process pids | |
pid_t ps[PS_MAX]; // zero valued pids - means the process is terminated or not created yet | |
// size of data array | |
unsigned data_size; | |
void read_file(FILE* file){ | |
// TODO: extract the data of processes from the {file} | |
// and store them in the array {data} | |
// initialize ps array to zeros (the process is terminated or not created yet) | |
} | |
// send signal SIGCONT to the worker process | |
void resume(pid_t process) { | |
// TODO: send signal SIGCONT to the worker process if it is not in one of the states | |
// (1.not created yet or 2.terminated) | |
} | |
// send signal SIGTSTP to the worker process | |
void suspend(pid_t process) { | |
// TODO: send signal SIGTSTP to the worker process if it is not in one of the states | |
// (1.not created yet or 2.terminated) | |
} | |
// send signal SIGTERM to the worker process | |
void terminate(pid_t process) { | |
// TODO: send signal SIGTERM to the worker process if it is not in one of the states | |
// (1.not created yet or 2.terminated) | |
} | |
// create a process using fork | |
void create_process(int new_process) { | |
// TODO: stop the running process | |
// TODO: fork a new process and add it to ps array | |
// TODO: Now the idx of the running process is new_process | |
// TODO: The scheduler process runs the program "./worker {new_process}" | |
// using one of the exec functions like execvp | |
} | |
// find next process for running | |
ProcessData find_next_process() { | |
// location of next process in {data} array | |
int location = 0; | |
for(int i=0; i < data_size; i++) { | |
// TODO: find location of the next process to run from the {data} array | |
// Considering the scheduling algorithm FCFS | |
} | |
// if next_process did not arrive so far, | |
// then we recursively call this function after incrementing total_time | |
if(data[location].at > total_time){ | |
printf("Scheduler: Runtime: %u seconds.\nProcess %d: has not arrived yet.\n", total_time, location); | |
// increment the time | |
total_time++; | |
return find_next_process(); | |
} | |
// return the data of next process | |
return data[location]; | |
} | |
// reports the metrics and simulation results | |
void report(){ | |
printf("Simulation results.....\n"); | |
int sum_wt = 0; | |
int sum_tat = 0; | |
for (int i=0; i< data_size; i++){ | |
printf("process %d: \n", i); | |
printf(" at=%d\n", data[i].at); | |
printf(" bt=%d\n", data[i].bt); | |
printf(" ct=%d\n", data[i].ct); | |
printf(" wt=%d\n", data[i].wt); | |
printf(" tat=%d\n", data[i].tat); | |
printf(" rt=%d\n", data[i].rt); | |
sum_wt += data[i].wt; | |
sum_tat += data[i].tat; | |
} | |
printf("data size = %d\n", data_size); | |
float avg_wt = (float)sum_wt/data_size; | |
float avg_tat = (float)sum_tat/data_size; | |
printf("Average results for this run:\n"); | |
printf(" avg_wt=%f\n", avg_wt); | |
printf(" avg_tat=%f\n", avg_tat); | |
} | |
void check_burst(){ | |
for(int i = 0; i < data_size; i++) | |
if (data[i].burst > 0) | |
return; | |
// report simulation results | |
report(); | |
// terminate the scheduler :) | |
exit(EXIT_SUCCESS); | |
} | |
// This function is called every one second as handler for SIGALRM signal | |
void schedule_handler(int signum) { | |
// increment the total time | |
total_time++; | |
/* TODO | |
1. If there is a worker process running, then decrement its remaining burst | |
and print messages as follows: | |
"Scheduler: Runtime: {total_time} seconds" | |
"Process {running_process} is running with {data[running_process].burst} seconds left" | |
1.A. If the worker process finished its burst time, then the scheduler should terminate | |
the running process and prints the message: | |
"Scheduler: Terminating Process {running_process} (Remaining Time: {data[running_process].burst})" | |
then the scheduler waits for its termination and there will be no running processes anymore. | |
Since the process is terminated, we can calculate its metrics {ct, tat, wt} | |
2. After that, we need to find the next process to run {next_process}. | |
// this call will check the bursts of all processes | |
check_burst(); | |
3. If {next_process} is not running, then we need to check the current process | |
3.A. If the current process is running, then we should stop the current running process | |
and print the message: | |
"Scheduler: Stopping Process {running_process} (Remaining Time: {data[running_process].burst})" | |
3.B. set current process {next_process} as the running process. | |
3.C.1. then create a new process for {running_process} and print the message: | |
"Scheduler: Starting Process {running_process} (Remaining Time: {data[running_process].burst})" | |
Here we have the first response to the process {running_process} and we can calculate the metric {rt} | |
3.C.2. or resume the process {running_process} if it is stopped and print the message: | |
"Scheduler: Resuming Process {running_process} (Remaining Time: {data[running_process].burst})" | |
*/ | |
} | |
int main(int argc, char *argv[]) { | |
// read the data file | |
FILE *in_file = fopen(argv[1], "r"); | |
if (in_file == NULL) { | |
printf("File is not found or cannot open it!\n"); | |
exit(EXIT_FAILURE); | |
} else { | |
read_file(in_file); | |
} | |
// set a timer | |
struct itimerval timer; | |
// the timer goes off 1 second after reset | |
timer.it_value.tv_sec = 1; | |
timer.it_value.tv_usec = 0; | |
// timer increments 1 second at a time | |
timer.it_interval.tv_sec = 1; | |
timer.it_interval.tv_usec = 0; | |
// this counts down and sends SIGALRM to the scheduler process after expiration. | |
setitimer(ITIMER_REAL, &timer, NULL); | |
// register the handler for SIGALRM signal | |
signal(SIGALRM, schedule_handler); | |
// Wait till all processes finish | |
while(1); // infinite loop | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <signal.h> | |
#include <time.h> | |
#include <stdbool.h> | |
// 6 digits for big triangular numbers like 113050 | |
#define TRI_BASE 1000000 | |
// current process pid (which executed this program) | |
pid_t pid; | |
// current process idx (starts from 0) | |
int process_idx; | |
// number of triangular numbers found so far | |
long tris; | |
bool is_triangular(long n){ | |
for (long i = 1; i <= n; i++){ | |
if (i * (i + 1) == 2 * n){ | |
return true; | |
} | |
} | |
return false; | |
} | |
void signal_handler(int signum){ | |
// print info about number of triangulars found. | |
printf("Process %d (PID=<%d>): count of triangulars found so far is \e[0;31m%ld\e[0m\n", process_idx, pid, tris); | |
switch(signum) { | |
case SIGTSTP: | |
// pause the process indefinitely | |
printf("Process %d: stopping....\n", process_idx); | |
pause(); | |
break; | |
case SIGCONT: | |
// continue the process | |
printf("Process %d: resuming....\n", process_idx); | |
break; | |
case SIGTERM: | |
// terminate the process | |
printf("Process %d: terminating....\n", process_idx); | |
exit(EXIT_SUCCESS); | |
break; | |
default: | |
break; | |
} | |
} | |
// generates a big number n | |
long big_n() { | |
time_t t; | |
long n = 0; | |
srand((unsigned) time(&t)); | |
while(n < TRI_BASE) | |
n += rand(); | |
return n % TRI_BASE; | |
} | |
int main(int argc, char *argv[]){ | |
// TODO: get the process_idx from argv | |
// process idx | |
process_idx = .... | |
pid = getpid(); | |
// TODO: register the signals | |
long next_n = big_n() +1; | |
// The first message after creating the process | |
printf("Process %d (PID=<%d>): has been started\n", process_idx, pid); | |
printf("Process %d (PID=<%d>): will find the next trianguar number from [%ld, inf)\n", process_idx, pid, next_n); | |
// initialize counter | |
tris = 0; | |
while (true){ | |
// TODO: in an infinite loop, search for next triangular numbers starting from {next_n} | |
// Every time you find a new triangular number print the message: | |
// "Process {process_idx} (PID=<{pid}>): I found this triangular number \e[0;31m{next_n}\e[0m\n" | |
// and increase the count {tris} | |
next_n++; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment