MIT-Curricular/OS/C/practice/test.c
2025-03-21 08:25:59 +05:30

179 lines
6.2 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
// Define the Process structure to hold scheduling details.
typedef struct {
int pid; // Process ID for display.
int arrival; // Arrival time.
int burst; // Burst time (total execution time).
int waiting; // Waiting time (calculated).
int turnaround; // Turnaround time (calculated).
int completion; // Completion time (calculated).
int remaining; // Remaining burst time (for preemptive SJF).
} Process;
// Function: fcfs_scheduling
// Implements the First-Come, First-Served scheduling algorithm.
void fcfs_scheduling(Process proc[], int n) {
// Sort processes by arrival time using bubble sort.
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (proc[j].arrival > proc[j + 1].arrival) {
Process temp = proc[j];
proc[j] = proc[j + 1];
proc[j + 1] = temp;
}
}
}
int current_time = 0; // Simulated current time.
for (int i = 0; i < n; i++) {
// If the CPU is idle, fast-forward current time to the arrival of the next process.
if (current_time < proc[i].arrival) {
current_time = proc[i].arrival;
}
// Waiting time is the time process has to wait from its arrival.
proc[i].waiting = current_time - proc[i].arrival;
// Turnaround time is waiting time plus burst time.
proc[i].turnaround = proc[i].waiting + proc[i].burst;
// Completion time is when the process finishes execution.
proc[i].completion = current_time + proc[i].burst;
// Update current time to include the burst time of this process.
current_time += proc[i].burst;
}
// Print the FCFS scheduling results.
printf("\n=== FCFS Scheduling Results (Child Process) ===\n");
printf("PID\tArrival\tBurst\tCompletion\tWaiting\tTurnaround\n");
for (int i = 0; i < n; i++) {
printf("%d\t%d\t%d\t%d\t\t%d\t%d\n",
proc[i].pid,
proc[i].arrival,
proc[i].burst,
proc[i].completion,
proc[i].waiting,
proc[i].turnaround);
}
}
// Function: preemptive_sjf
// Implements the Preemptive SJF (Shortest Job First) scheduling algorithm.
void preemptive_sjf(Process proc[], int n) {
// Initialize remaining time for each process.
for (int i = 0; i < n; i++) {
proc[i].remaining = proc[i].burst;
}
int complete = 0; // Number of completed processes.
int current_time = 0; // Simulated current time.
int smallest; // Index of process with smallest remaining time.
int finish_time; // Time when a process completes.
int found; // Flag indicating if a process is found at current time.
// Process scheduling until all processes complete.
while (complete != n) {
found = 0;
smallest = -1;
// Find process with minimum remaining time that has arrived.
for (int i = 0; i < n; i++) {
if (proc[i].arrival <= current_time && proc[i].remaining > 0) {
if (smallest == -1 || proc[i].remaining < proc[smallest].remaining) {
smallest = i;
found = 1;
}
}
}
// If no process is available at current_time, increment time.
if (!found) {
current_time++;
continue;
}
// Execute the selected process for one time unit.
proc[smallest].remaining--;
current_time++;
// When a process completes execution, update its times.
if (proc[smallest].remaining == 0) {
complete++;
finish_time = current_time;
// Completion time is the finish time.
proc[smallest].completion = finish_time;
// Turnaround time is finish time minus arrival time.
proc[smallest].turnaround = finish_time - proc[smallest].arrival;
// Waiting time is turnaround time minus burst time.
proc[smallest].waiting = proc[smallest].turnaround - proc[smallest].burst;
}
}
// Print the Preemptive SJF scheduling results.
printf("\n=== Preemptive SJF Scheduling Results (Parent Process) ===\n");
printf("PID\tArrival\tBurst\tCompletion\tWaiting\tTurnaround\n");
for (int i = 0; i < n; i++) {
printf("%d\t%d\t%d\t%d\t\t%d\t%d\n",
proc[i].pid,
proc[i].arrival,
proc[i].burst,
proc[i].completion,
proc[i].waiting,
proc[i].turnaround);
}
}
int main() {
int n;
// Prompt user to input the number of processes.
printf("Enter the number of processes: ");
fflush(stdout); // Ensure the prompt is displayed.
scanf("%d", &n);
// Declare two arrays for process data:
// - One for the child (FCFS) and one for the parent (Preemptive SJF).
Process processes[n];
Process processes_copy[n]; // Copy for parent's use.
// Loop to gather process details.
for (int i = 0; i < n; i++) {
processes[i].pid = i + 1; // Process IDs start at 1.
// Input arrival time.
printf("Enter arrival time for process %d: ", i + 1);
fflush(stdout);
scanf("%d", &processes[i].arrival);
// Input burst time.
printf("Enter burst time for process %d: ", i + 1);
fflush(stdout);
scanf("%d", &processes[i].burst);
// Copy process data for the parent process scheduling.
processes_copy[i] = processes[i];
}
// Fork the process to split execution into two scheduling algorithms.
pid_t pid = fork();
if (pid < 0) {
// Error handling for fork failure.
perror("Fork failed");
exit(EXIT_FAILURE);
}
else if (pid == 0) {
// Child process: Execute FCFS scheduling.
printf("\nChild process executing FCFS scheduling...\n");
fcfs_scheduling(processes, n);
exit(0); // End child process.
}
else {
// Parent process: Wait for child to finish and then execute Preemptive SJF.
wait(NULL);
printf("\nParent process executing Preemptive SJF scheduling...\n");
preemptive_sjf(processes_copy, n);
}
return 0;
}