OS Record Shreyas

Download as pdf or txt
Download as pdf or txt
You are on page 1of 61

EX 1 STUDY OF BASIC UNIX COMMANDS

11/7/24

AIM:
To execute the basic unix commands.

SAMPLE INPUT/OUTPUT:
RESULT:
Thus, basic commands are successfully executed.
EX 2 IMPLEMENTATION OF SYSTEM CALLS

25/7/24

AIM:

To write a program in C to implement system calls.

ALGORITHM:
• Include the necessary libraries.
• Open or create a file using open().
• Write data to the file with write().
• Close the file.
• Reopen the file, read its contents with read(), and print the data.
• Close the file again.
• Reopen the file, adjust the file offset using lseek(), read from the
new position, print the updated content, and close the file.
• Create the first child process using fork().
• In the parent process, use wait() to wait for the first child to finish.
• In the parent process, create a second child process with fork(),
wait for it to complete, and print the parent process ID.

CODE:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

void forkwait() {
printf("Initial process ID: %d\n", getpid());
int child1 = fork();
if (child1 == 0) {
printf("Child 1 process ID: %d\n", getpid());
exit(0);
} else {
wait(NULL);
int child2 = fork();
if (child2 == 0) {
printf("Child 2 process ID: %d\n", getpid());
exit(0);
} else {
wait(NULL);
printf("Parent process ID: %d\n", getpid());
}
}
}

int main() {
printf("Parent process ID: %d\n", getpid());
int fildes = open("new.txt", O_RDWR | O_CREAT, 0644);
if (fildes == -1) {
perror("Failed to open file");
return 1;
}

char content[] = "operating systems";


write(fildes, content, sizeof(content) - 1);
close(fildes);
fildes = open("new.txt", O_RDWR);
if (fildes == -1) {
perror("Failed to open file");
return 1;
}

char data_read[100] = {0};


read(fildes, data_read, sizeof(content) - 1);
printf("File content: %s\n", data_read);
close(fildes);
fildes = open("new.txt", O_RDWR);
if (fildes == -1) {
perror("Failed to open file");
return 1;
}

lseek(fildes, 3, SEEK_SET);
read(fildes, data_read, sizeof(content) - 4);
printf("File content after lseek: %s\n", data_read);
close(fildes);
forkwait();
return 0;
}
OUTPUT:

RESULT:
The program to implement system calls using C language is executed
successfully and output has been verified.
1/8/24 Implementation of IPC using Shared Memory, implementing zombie, orphan process
EX 3

AIM:
Q1. To Implement Interprocess communication using shared
memory.
Q2. To Implement Zombie process
Q3. To Implement Orphan process

ALGORITHM: Q1 Writing

1) Include necessary headers: stdio.h, stdlib.h, unistd.h, sys/shm.h, and


string.h.
2) Use shmget to create or access a shared memory segment with a
specified key and size.
3) Use shmat to attach the shared memory segment to the
process's address space.
4) Print the shared memory identifier and the address where the
segment is attached.
5) Prompt the user to enter data and read this input into a buffer.
6) Copy the user input from the buffer to the shared memory.
7) Print the data that was written to the shared memory.

CODE:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/shm.h>
#include<string.h>
int main()
{
int i;
void *shared_memory;
char buff[100];
int shmid;
shmid=shmget((key_t)2345, 1024, 0666|IPC_CREAT);
printf("Key of shared memory is %d\n",shmid);
shared_memory=shmat(shmid,NULL,0);
printf("Process attached at %p\n",shared_memory);
printf("Enter some data to write to shared memory\n");
read(0,buff,100);
strcpy(shared_memory,buff);
printf("You wrote : %s\n",(char *)shared_memory);
}
OUTPUT:

ALGORITHM: Q1: Reading

1) Include necessary headers for I/O and shared memory operations.


2) Use shmget to obtain the shared memory segment identifier.
3) Attach the shared memory segment to the process using shmat.
4) Display the shared memory identifier.
5) Print the address where the segment is attached.
6) Read and display the data from the shared memory.

CODE:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/shm.h>
#include<string.h>

int main(){
int i;
void *shared_memory;
char buff[100];
int shmid;
shmid=shmget((key_t)2345, 1024, 0666);
printf("Key of shared memory is %d\n",shmid);
shared_memory=shmat(shmid,NULL,0);
printf("Process attached at %p\n",shared_memory);
printf("Data read from shared memory is : %s\n",(char
*)shared_memory);
}
OUTPUT:

Q2: ALGORITHM:

□ Start the program.


□ Call fork() to create a child process.
□ Check if fork() returned a positive value.
□ If true, print "In parent process".
□ Sleep for 5 seconds.
□ If false, print "In child process".
□ Exit the program.

CODE:
OUTPUT

Q3: ALGORITHM:
□ Start the program.
□ Call fork() to create a child process.
□ Check if fork() returned a positive value.
□ If true, print "in parent process".
□ Check if fork() returned 0.
□ If true, sleep for 10 seconds and print "in child process".
□ End the program.

CODE:
OUTPUT:

RESULT:

Thus, implemented Interprocess communication using shared


memory and implemented Zombie process and implemented Orphan
process.
8/8/24 IMPLEMENTATION OF SCHEDULING
ALGORITHMS
EX 4

AIM:
To write c program to implement

a. FIRST COME FIRST SERVED

b. SHORTEST JOB FIRST

c. SHORTEST REMAINING TIME FIRST

ALGORITHM:
• Prompt the user to input the number of processes n.
• For each process, input its arrival time at[i] and burst time bt[i].
• Assign each process a unique process ID id[i].
• Prompt the user to choose one of the scheduling algorithms:
1. First-Come, First-Serve (FCFS)

2. Shortest Job First (SJF)

3. Shortest Remaining Time First (SRTF)


First-Come, First-Serve (FCFS):

• Sort the processes based on their arrival time using the


sorting function s(arr1, arr2, arr3, n).
• Initialize the current time cur to the arrival time of the first process.
• For each process:
o Print the start time, process ID, and end time in the Gantt chart.
o Calculate the completion time ct[i] as cur + bt[i].
o Calculate turnaround time tat[i] as ct[i] - at[i].
o Calculate waiting time wt[i] as tat[i] - bt[i].
• Compute the average turnaround time and average waiting time.

Shortest Job First (SJF):


• Initialize an array completed[] to keep track of completed processes.
• Set curtime to 0 and loop until all processes are scheduled.
• In each iteration:
o Find the process with the shortest burst time among those that
have arrived and are not yet completed.

o If no such process exists, increment curtime and repeat the search.


o Otherwise, execute the process and update its
completion time, turnaround time, and waiting time.
• Compute the average turnaround time and average waiting time.
Shortest Remaining Time First (SRTF):

• Initialize arrays remburst[] to store remaining burst times and


completed[] to keep track of completed processes.
• Set curtime to 0 and loop until all processes are completed.
• In each iteration:
o Find the process with the shortest remaining burst time among
those that have arrived and are not yet completed.
o If no such process exists, increment curtime and repeat the search.
o Otherwise, execute the process for one time unit, decrement its
remaining burst time, and update its completion time,
turnaround time, and waiting time if the process completes.
• Compute the average turnaround time and average waiting time.

• Display the process ID, arrival time, burst time, completion time,
turnaround time, and waiting time for each process.

• Display the average turnaround time and average waiting time.

CODE:

#include <stdio.h>

void s(int *arr1, int *arr2, int *arr3, int n) {


for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr1[j] > arr1[j + 1]) {
int temp1 = arr1[j];
int temp2 = arr2[j];
int temp3 = arr3[j];
arr1[j] = arr1[j + 1];
arr1[j + 1] = temp1;
arr2[j] = arr2[j + 1];
arr2[j + 1] = temp2;
arr3[j] = arr3[j + 1];
arr3[j + 1] = temp3;
}
}
}
}

void main() {
int n;
printf("Enter number of processes: ");
scanf("%d", &n);
int at[n], bt[n], id[n], ct[n], tat[n], wt[n], rt[n];
for (int i = 0; i < n; i++) {
printf("Enter arrival time: ");
scanf("%d", &at[i]);
printf("Enter burst time: ");
scanf("%d", &bt[i]);
id[i] = i + 1;
}

int choice;
printf("1-FIRST COME FIRST SERVE\n2-SHORTEST JOB FIRST\n3-
SHORTEST REMAINING TIME FIRST\n");
printf("Enter choice: ");
scanf("%d", &choice);

if (choice == 1) { // FCFS
printf("Gantt chart\n");
s(at, bt, id, n);
int cur = at[0];
for (int i = 0; i < n; i++) {
rt[i] = cur - at[i]; // Response time is when process starts first
printf("%d---process%d---", cur, id[i]);
cur += bt[i];
ct[i] = cur;
if (i == n - 1) printf("%d\n", cur);
}

for (int i = 0; i < n; i++) {


tat[i] = ct[i] - at[i];
wt[i] = tat[i] - bt[i];
}

printf("PID---Arrival Time---Burst Time---Completion Time---Turnaround


Time---Waiting Time---Response Time\n");
for (int i = 0; i < n; i++) {
printf("%d---%d---%d---%d---%d---%d---%d\n", id[i], at[i], bt[i], ct[i],
tat[i], wt[i], rt[i]);
}

} else if (choice == 2) { // SJF


int completed[n], curtime = 0;
for (int i = 0; i < n; i++) completed[i] = 0;

printf("Gantt chart:\n");
for (int i = 0; i < n; i++) {
int minburst = 10000000, index = -1;
for (int j = 0; j < n; j++) {
if (at[j] <= curtime && !completed[j] && bt[j] < minburst) {
minburst = bt[j];
index = j;
}
}

if (index == -1) {
curtime++;
i--;
continue;
}
rt[index] = curtime - at[index]; // Response time
printf("%d---process%d---", curtime, id[index]);
curtime += bt[index];
ct[index] = curtime;
completed[index] = 1;
if (i == n - 1) printf("%d\n", curtime);
}

} else if (choice == 3) { // SRTF


int remburst[n], completed[n], curtime = 0, comproc = 0;
for (int i = 0; i < n; i++) {
remburst[i] = bt[i];
completed[i] = 0;
}

printf("Gantt chart:\n");
while (comproc < n) {
int minburst = 10000000, index = -1;
for (int j = 0; j < n; j++) {
if (at[j] <= curtime && !completed[j] && remburst[j] < minburst) {
minburst = remburst[j];
index = j;
}
}

if (index == -1) {
curtime++;
continue;
}

if (remburst[index] == bt[index]) {
rt[index] = curtime - at[index]; // First time selection
}

printf("%d---process%d---", curtime, id[index]);


remburst[index]--;
curtime++;
if (remburst[index] == 0) {
ct[index] = curtime;
completed[index] = 1;
comproc++;
}
}
printf("%d\n", curtime);
}

// Calculate averages and display response times for all options


float avgct = 0, avgtat = 0, avgwt = 0, avgrt = 0;
for (int i = 0; i < n; i++) {
tat[i] = ct[i] - at[i];
wt[i] = tat[i] - bt[i];
avgct += ct[i];
avgtat += tat[i];
avgwt += wt[i];
avgrt += rt[i];
}

avgct /= n;
avgtat /= n;
avgwt /= n;
avgrt /= n;
printf("Average completion time: %.2f, Average turnaround time: %.2f,
Average waiting time: %.2f, Average response time: %.2f\n", avgct, avgtat,
avgwt, avgrt);
}
OUTPUT:
RESULT:
Thus a program to implement scheduling algorithms is executed
successfully and the output is verified.
EX 5 IMPLEMENTATION OF SCHEDULING ALGORITHMS
(ROUND ROBIN , PRIORITY)
22/08/24

AIM:
To write a C program to implement

a. ROUND ROBIN
b. PRIORITY SCHEDULING(preemptive)
c. PRIORITY SCHEDULING (nonpreemptive)

ALGORITHM:

1. Non-Preemptive Priority Scheduling


Steps:

1. Input:

• Number of processes.
• For each process: Burst time, Arrival time, Priority.
2. Sort Processes:

• First by Arrival Time.


• Then by Priority (among those with the same Arrival Time).
3. Calculate Times:

• For each process:


• Completion Time = End of previous process + Burst Time
• Turnaround Time = Completion Time - Arrival Time
• Waiting Time = Turnaround Time - Burst Time
• Response Time = Arrival Time
4. Output:

• Print PID, Burst Time, Priority, Arrival Time, Completion Time, Turnaround
Time, Waiting Time, and Response Time.
• Print the average completion time, average waiting time, average turnaround
time, average response time.

2. Preemptive Priority Scheduling


Steps:

1. Input:

• Number of processes.
• For each process: Burst time, Arrival time, Priority.
2. Initialization:

• Set remaining time for each process to its Burst Time.


• Set start time to -1 for all processes.

3. Scheduling:

• Track the current time.


• At each time unit:
• Find the highest priority process that has arrived and is not finished.
• If a process starts now, record its start time and calculate its Response Time.
• Decrease its remaining time by 1.
• If remaining time reaches 0, calculate Completion Time, Turnaround Time,
and Waiting Time for the process.
4. Output:

• Print PID, Burst Time, Priority, Arrival Time, Completion Time, Turnaround
Time, Waiting Time, and Response Time.
• Print the average completion time, average waiting time, average turnaround
time, average response time.

3. Round Robin Scheduling


Steps:

1. Input:

• Number of processes.
• For each process: Burst time, Arrival time.
• Time Quantum (the maximum time a process can run before being interrupted).
2. Initialization:

• Set remaining time for each process to its Burst Time.


• Set start time to -1 for all processes.
3. Scheduling:

• Track the current time.


• At each time unit, give each process a turn in a round-robin fashion:
• If a process's remaining time is greater than the quantum, reduce its
remaining time by the quantum and continue.
• If a process's remaining time is less than or equal to the quantum, finish it
and calculate its Completion Time, Turnaround Time, and Waiting Time.

4. Output:

• Print PID, Burst Time, Arrival Time, Completion Time, Turnaround Time,
Waiting Time, and Response Time.
• Print the average completion time, average waiting time, average turnaround
time, average response time.
CODE:

#include <stdio.h>

struct Process {
int pid; // Process ID
int burst_time; // Burst time
int priority; // Priority
int wait_time; // Waiting time
int turn_around_time; // Turnaround time
int completion_time; // Completion time
int response_time; // Response time
int remaining_time; // Remaining time (only for preemptive scheduling)
int start_time; // Start time (for response time calculation)
int arrival_time; // Arrival time
};

// Non-preemptive priority scheduling function


void nonPreemptivePriorityScheduling(struct Process proc[], int n) {
int i, j;
struct Process temp;
float total_wait_time = 0, total_turnaround_time = 0, total_completion_time = 0, total_response_time = 0;

// Sort processes based on arrival time


for (i = 0; i < n; i++) {
for (j = i + 1; j < n; j++) {
if (proc[i].arrival_time > proc[j].arrival_time) {
temp = proc[i];
proc[i] = proc[j];
proc[j] = temp;
}
}
}

// Sort by priority among processes that have arrived


for (i = 0; i < n; i++) {
for (j = i + 1; j < n; j++) {
if (proc[i].priority > proc[j].priority && proc[i].completion_time <= proc[j].arrival_time) {
temp = proc[i];
proc[i] = proc[j];
proc[j] = temp;
}
}
}

// Calculate times for the first process


proc[0].completion_time = proc[0].arrival_time + proc[0].burst_time;
proc[0].turn_around_time = proc[0].completion_time - proc[0].arrival_time;
proc[0].wait_time = proc[0].turn_around_time - proc[0].burst_time;
proc[0].response_time = proc[0].arrival_time;

total_wait_time += proc[0].wait_time;
total_turnaround_time += proc[0].turn_around_time;
total_completion_time += proc[0].completion_time;
total_response_time += proc[0].response_time;
for (i = 1; i < n; i++) {
proc[i].completion_time = proc[i - 1].completion_time + proc[i].burst_time;
proc[i].turn_around_time = proc[i].completion_time - proc[i].arrival_time;
proc[i].wait_time = proc[i].turn_around_time - proc[i].burst_time;
proc[i].response_time = proc[i].completion_time - proc[i].burst_time;

total_wait_time += proc[i].wait_time;
total_turnaround_time += proc[i].turn_around_time;
total_completion_time += proc[i].completion_time;
total_response_time += proc[i].response_time;
}

printf("Non-Preemptive Priority Scheduling:\n");


printf("PID\tBurst Time\tPriority\tArrival Time\tCompletion Time\tTurnaround Time\tWaiting
Time\tResponse Time\n");
for (i = 0; i < n; i++) {
printf("%d\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\n", proc[i].pid, proc[i].burst_time, proc[i].priority,
proc[i].arrival_time, proc[i].completion_time, proc[i].turn_around_time, proc[i].wait_time,
proc[i].response_time);
}

printf("\nAverage Completion Time: %.2f\n", total_completion_time / n);


printf("Average Turnaround Time: %.2f\n", total_turnaround_time / n);
printf("Average Waiting Time: %.2f\n", total_wait_time / n);
printf("Average Response Time: %.2f\n", total_response_time / n);
}

// Preemptive priority scheduling function


void preemptivePriorityScheduling(struct Process proc[], int n) {
int time = 0, completed = 0, i, min_priority;
int shortest = 0, finish_time;
int all_arrived = 0;
float total_wait_time = 0, total_turnaround_time = 0, total_completion_time = 0, total_response_time = 0;

for (i = 0; i < n; i++) {


proc[i].remaining_time = proc[i].burst_time;
proc[i].start_time = -1;
}

while (completed != n) {
min_priority = 9999;
shortest = -1;
all_arrived = 0;
for (i = 0; i < n; i++) {
if (proc[i].arrival_time <= time) {
all_arrived = 1;
if (proc[i].remaining_time > 0 && proc[i].priority < min_priority) {
min_priority = proc[i].priority;
shortest = i;
}
}
}

if (!all_arrived) {
time++;
continue;
}

if (shortest == -1) {
time++;
continue;
}

if (proc[shortest].start_time == -1) {
proc[shortest].start_time = time;
proc[shortest].response_time = time - proc[shortest].arrival_time;
}

proc[shortest].remaining_time--;
time++;

if (proc[shortest].remaining_time == 0) {
completed++;
finish_time = time;
proc[shortest].completion_time = finish_time;
proc[shortest].turn_around_time = proc[shortest].completion_time - proc[shortest].arrival_time;
proc[shortest].wait_time = proc[shortest].turn_around_time - proc[shortest].burst_time;

total_wait_time += proc[shortest].wait_time;
total_turnaround_time += proc[shortest].turn_around_time;
total_completion_time += proc[shortest].completion_time;
total_response_time += proc[shortest].response_time;
}
}

printf("Preemptive Priority Scheduling:\n");


printf("PID\tBurst Time\tPriority\tArrival Time\tCompletion Time\tTurnaround Time\tWaiting
Time\tResponse Time\n");
for (i = 0; i < n; i++) {
printf("%d\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\n", proc[i].pid, proc[i].burst_time, proc[i].priority,
proc[i].arrival_time, proc[i].completion_time, proc[i].turn_around_time, proc[i].wait_time,
proc[i].response_time);
}

printf("\nAverage Completion Time: %.2f\n", total_completion_time / n);


printf("Average Turnaround Time: %.2f\n", total_turnaround_time / n);
printf("Average Waiting Time: %.2f\n", total_wait_time / n);
printf("Average Response Time: %.2f\n", total_response_time / n);
}

// Round-robin scheduling function


void roundRobinScheduling(struct Process proc[], int n, int quantum) {
int time = 0, i, remaining = n;
int process_count = 0;
float total_wait_time = 0, total_turnaround_time = 0, total_completion_time = 0, total_response_time = 0;

for (i = 0; i < n; i++) {


proc[i].remaining_time = proc[i].burst_time;
proc[i].start_time = -1;
}
while (remaining != 0) {
process_count = 0;
for (i = 0; i < n; i++) {
if (proc[i].arrival_time <= time && proc[i].remaining_time > 0) {
process_count = 1;
if (proc[i].start_time == -1) {
proc[i].start_time = time;
proc[i].response_time = time - proc[i].arrival_time;
}

if (proc[i].remaining_time > quantum) {


time += quantum;
proc[i].remaining_time -= quantum;
} else {
time += proc[i].remaining_time;
proc[i].completion_time = time;
proc[i].turn_around_time = proc[i].completion_time - proc[i].arrival_time;
proc[i].wait_time = proc[i].turn_around_time - proc[i].burst_time;
proc[i].remaining_time = 0;
remaining--;

total_wait_time += proc[i].wait_time;
total_turnaround_time += proc[i].turn_around_time;
total_completion_time += proc[i].completion_time;
total_response_time += proc[i].response_time;
}
}
}
if (process_count == 0) {
time++;
}
}

printf("Round Robin Scheduling:\n");


printf("PID\tBurst Time\tArrival Time\tCompletion Time\tTurnaround Time\tWaiting Time\tResponse
Time\n");
for (i = 0; i < n; i++) {
printf("%d\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\n", proc[i].pid, proc[i].burst_time, proc[i].arrival_time,
proc[i].completion_time, proc[i].turn_around_time, proc[i].wait_time, proc[i].response_time);
}

printf("\nAverage Completion Time: %.2f\n", total_completion_time / n);


printf("Average Turnaround Time: %.2f\n", total_turnaround_time / n);
printf("Average Waiting Time: %.2f\n", total_wait_time / n);
printf("Average Response Time: %.2f\n", total_response_time / n);
}

int main() {
int n, i, quantum, choice, type;
printf("Enter the number of processes: ");
scanf("%d", &n);

struct Process proc[n];

printf("Choose the Scheduling Algorithm:\n");


printf("1. Priority Scheduling\n");
printf("2. Round Robin Scheduling\n");
printf("Enter your choice: ");
scanf("%d", &choice);

for (i = 0; i < n; i++) {


proc[i].pid = i + 1;
printf("Enter burst time for process %d: ", proc[i].pid);
scanf("%d", &proc[i].burst_time);
printf("Enter arrival time for process %d: ", proc[i].pid);
scanf("%d", &proc[i].arrival_time);
if (choice == 1) {
printf("Enter priority for process %d: ", proc[i].pid);
scanf("%d", &proc[i].priority);
}
}

if (choice == 1) {
printf("Choose the type of Priority Scheduling:\n");
printf("1. Non-Preemptive\n");
printf("2. Preemptive\n");
printf("Enter your choice: ");
scanf("%d", &type);
if (type == 1) {
nonPreemptivePriorityScheduling(proc, n);
} else if (type == 2) {
preemptivePriorityScheduling(proc, n);
} else {
printf("Invalid choice!\n");
}
} else if (choice == 2) {
printf("Enter the time quantum for Round Robin: ");
scanf("%d", &quantum);
roundRobinScheduling(proc, n, quantum);
} else {
printf("Invalid choice!\n");
}

return 0;
}
OUTPUT:
RESULT:
Thus a C program for implementing round robin and priority scheduling is implemented and
executed successfully.
EX 6 CREATION OF THREADS
29/8/24

AIM:
To write a C program for the creation of threads.

ALGORITHM:

□ Start
□ Initialize arrays for thread identifiers and arguments, and a variable for
error codes.
□ Create threads in a loop, passing thread-specific arguments and handling
any errors.
□ Wait for threads to complete in a loop, handling any errors encountered
during joining.
□ Print a completion message after all threads have finished.
End the program with a successful status code.

CODE:
#include <stdio.h>
#include
<pthread.h>

void* threadFunction(void* arg)


{ int threadNum = *((int*)arg);
printf("Hello from thread %d\n", threadNum);
pthread_exit(NULL);
}

int main() {
pthread_t
threads[5]; int
threadArgs[5]; int
resultCode;

for (int i = 0; i < 5; i++) {


threadArgs[i] = i; // Set the argument for each thread
resultCode = pthread_create(&threads[i], NULL, threadFunction,
&threadArgs[i]);
if (resultCode != 0) {
printf("Error creating thread %d: %d\n", i, resultCode);
return -1;
}
}

for (int i = 0; i < 5; i++) {


resultCode = pthread_join(threads[i], NULL);
if (resultCode != 0) {
printf("Error joining thread %d: %d\n", i,
resultCode); return -1;
}
}

printf("All threads completed successfully.\n");


return 0;
}

OUTPUT:

RESULT:
Thus, a C program has been created for the creation of threads.
Ex.No.7
SYNCHRONIZATION APPLICATIONS
05.09.2024

AIM:
1. To write a program for solving producer-consumer problem using semaphores.

2.To write a program for solving dining philosophers’ problem using


semaphores.

ALGORITHM 1:
• Setup:

Buffer: A list where producers add items and consumers remove items.
Semaphores:
• Empty: Counts how many spaces are free in the buffer.
• Full: Counts how many items are in the buffer.
• Mutex: Makes sure only one thread (producer or consumer) accesses the buffer at a time.

• Producer:

Loop:
1. Wait for an empty space in the buffer.
2. Lock the buffer (using mutex).
3. Add a new item to the buffer.
4. Unlock the buffer.
5. Signal that there's a new item in the buffer.
6. Repeat this for a set number of items.
• Consumer:

Loop:
1. Wait for an item to be available in the buffer.
2. Lock the buffer (using mutex).
3. Remove an item from the buffer.
4. Unlock the buffer.
5. Signal that there's now an extra free space in the buffer.
6. Repeat this for a set number of items.

• Finish:

Wait for all producers and consumers to finish.

Clean up resources.
ALGORITHM 2:
1. Initialize:
• Forks: Create a semaphore for each fork to control access.
• Print Mutex: Create a mutex to ensure thread-safe printing.

2. Philosopher Actions:

• Thinking:
1. Lock the print mutex.
2. Print that the philosopher is thinking.
3. Unlock the print mutex.
4. Sleep for a random time to simulate thinking.
• Eating:
1. Wait for the left and right forks (semaphores) to become available.
2. Lock the print mutex.
3. Print that the philosopher is eating with the forks.
4. Unlock the print mutex.
5. Sleep for a random time to simulate eating.
6. Signal the availability of the left and right forks (release semaphores).
3. Terminate:

• Wait for all philosopher threads to finish.


• Destroy all semaphores and the print mutex.

PROGRAM 1:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

#define BUFFER_SIZE 10
#define NUM_PRODUCERS 2
#define NUM_CONSUMERS 2
#define PRODUCE_COUNT 5
#define CONSUME_COUNT 5

int buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
sem_t empty;
sem_t full;
sem_t mutex;
int produced_count = 0;
int consumed_count = 0;
pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;

void* producer(void* arg) {


int item;
long producer_id = (long)arg;
for (int i = 0; i < PRODUCE_COUNT; i++) {
item = rand() % 100;
sleep(rand() % 3);

sem_wait(&empty);
sem_wait(&mutex);

buffer[in] = item;
printf("Producer %ld produced %d at index %d\n", producer_id, item, in);
in = (in + 1) % BUFFER_SIZE;

sem_post(&mutex);
sem_post(&full);
pthread_mutex_lock(&count_mutex);
produced_count++;
pthread_mutex_unlock(&count_mutex);
}

pthread_exit(NULL);
}

void* consumer(void* arg) {


int item;
long consumer_id = (long)arg;

for (int i = 0; i < CONSUME_COUNT; i++) {


sem_wait(&full);
sem_wait(&mutex);

item = buffer[out];
printf("Consumer %ld consumed %d from index %d\n", consumer_id, item, out);
out = (out + 1) % BUFFER_SIZE;

sem_post(&mutex);
sem_post(&empty);

pthread_mutex_lock(&count_mutex);
consumed_count++;
pthread_mutex_unlock(&count_mutex);

sleep(rand() % 3);
}

pthread_exit(NULL);
}

int main() {
pthread_t producers[NUM_PRODUCERS];
pthread_t consumers[NUM_CONSUMERS];

sem_init(&empty, 0, BUFFER_SIZE);
sem_init(&full, 0, 0);
sem_init(&mutex, 0, 1);

for (long i = 0; i < NUM_PRODUCERS; i++) {


pthread_create(&producers[i], NULL, producer, (void*)i);
}
for (long i = 0; i < NUM_CONSUMERS; i++) {
pthread_create(&consumers[i], NULL, consumer, (void*)i);
}

for (int i = 0; i < NUM_PRODUCERS; i++) {


pthread_join(producers[i], NULL);
}
for (int i = 0; i < NUM_CONSUMERS; i++) {
pthread_join(consumers[i], NULL);
}

sem_destroy(&empty);
sem_destroy(&full);
sem_destroy(&mutex);
pthread_mutex_destroy(&count_mutex);

printf("\nTotal produced items: %d\n", produced_count);


printf("Total consumed items: %d\n", consumed_count);

return 0;
}

PROGRAM 2:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

#define NUM_PHILOSOPHERS 5
sem_t forks[NUM_PHILOSOPHERS];
pthread_mutex_t print_mutex;
void* philosopher(void* num) {
int phil = *(int*)num;
int left = phil;
int right = (phil + 1) % NUM_PHILOSOPHERS;

while (1) {
pthread_mutex_lock(&print_mutex);
printf("Philosopher %d is thinking.\n", phil);
pthread_mutex_unlock(&print_mutex);
sleep(rand() % 3);
sem_wait(&forks[left]);
sem_wait(&forks[right]);

pthread_mutex_lock(&print_mutex);
printf("Philosopher %d is eating with forks %d and %d.\n", phil, left, right);
pthread_mutex_unlock(&print_mutex);
sleep(rand() % 3);
sem_post(&forks[left]);
sem_post(&forks[right]);

pthread_exit(NULL);
}
}

int main() {
pthread_t philosophers[NUM_PHILOSOPHERS];
int philosopher_numbers[NUM_PHILOSOPHERS];
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
sem_init(&forks[i], 0, 1);
}
pthread_mutex_init(&print_mutex, NULL);
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
philosopher_numbers[i] = i;
pthread_create(&philosophers[i], NULL, philosopher, (void*)&philosopher_numbers[i]);
}
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
pthread_join(philosophers[i], NULL);
}
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
sem_destroy(&forks[i]);
}
pthread_mutex_destroy(&print_mutex);

return 0;
}

OUTPUT 1:
OUTPUT 2:

RESULT:

Thus the C program for solving producer-consumer problem and dining philosophers’ problem is created
and executed successfully.
EX 8 INTERPROCESS COMMUNICATION USING PIPES
12/9/24

AIM:
To write a program for implementing inter
process communication using pipes.

ALGORITHM:
Create a Pipe: Initialize a pipe with two file descriptors, one for reading and one for writing.
• Prompt for User Input: Ask the user to enter a message.
• Read User Input: Capture the user’s input and remove any trailing newline character.
• Fork a Child Process: Create a new process. This new process will execute
concurrently with the parent process.
• In the Child Process:
• Close the write end of the pipe.
• Read the message from the read end of the pipe.
• Print the received message.
• Close the read end of the pipe.
• In the Parent Process:
• Close the read end of the pipe.
• Write the user’s message to the write end of the pipe.
• Close the write end of the pipe.
• Wait for the child process to complete.
• Terminate: Ensure proper termination of both processes and cleanup.

CODE:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>

int main() {
int fd[2];
pid_t pid;
char buffer[100];
char userInput[100];

if (pipe(fd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}

printf("Enter a message to send to the child process: ");


if (fgets(userInput, sizeof(userInput), stdin) == NULL)
{
perror("fgets");
exit(EXIT_FAILURE);
}

userInput[strcspn(userInput, "\n")] = '\0';


pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}

if (pid == 0) {
close(fd[1]);
read(fd[0], buffer, sizeof(buffer));
printf("Child received message: %s\n",
buffer); close(fd[0]);
exit(EXIT_SUCCESS);
} else {
close(fd[0]);
write(fd[1], userInput, strlen(userInput) + 1);
close(fd[1]);
wait(NULL);
}

return 0;
}

OUTPUT:
RESULT:
Thus implemented inter process communication using pipes and the output is shown.
EX 9 DEADLOCK DETECTION AND AVOIDANCE
26/9/24

AIM:
To write a program for deadlock avoidance mechanism.

To write a program for deadlock detection mechanism.

1)

ALGORITHM:
1. Create two 2D array representing the allocation and
maximum demand of each process.
2. Calculate Need Matrix.This is
calculated as: need[i][j]=max[i][j]
−alloc[i][j]
3. An array “f” keeps track of whether each process has been
completed
(1) or not (0).
4. The program iterates up to n times, checking for processes
that can proceed safely:
• For each process, it checks if all resources needed are
available (using the need matrix and avail array).
• If a process can proceed, it adds that process to the ans
array, marks it as completed, and updates the avail
array to reflect the resources released by that process.
5. If all processes are completed successfully, it prints the safe
sequence of process execution.
6. If any process remains incomplete, it indicates that no safe
sequence exists.

CODE:
#include <stdio.h>
int main()
{
int n, m, i, j, k;
n = 5;
m = 3;
int alloc[5][3] = {{ 0, 1, 0 },{ 2, 0, 0 },{ 3, 0, 2 },{ 2, 1, 1 },{ 0, 0, 2 }};
int max[5][3] = {{ 7, 5, 3 },{ 3, 2, 2 },{ 9, 0, 2 },{ 2, 2, 2 },{ 4, 3, 3 }};
int avail[3] = { 3, 3, 2 };
int f[n], ans[n], ind = 0;
for (k = 0; k < n; k++) {
f[k] = 0;
}
int need[n][m];
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++)
need[i][j] = max[i][j] - alloc[i][j];
}
int y = 0;
for (k = 0; k < 5; k++) {
for (i = 0; i < n; i++) {
if (f[i] == 0) {

int flag = 0;
for (j = 0; j < m; j++) {
if (need[i][j] > avail[j]){
flag = 1;
break;
}
}
if (flag == 0) {
ans[ind++] = i;
for (y = 0; y < m; y++)
avail[y] += alloc[i][y];
f[i] = 1;
}
}
}
}
int flag = 1;
for(int i=0;i<n;i++)
{
if(f[i]==0)
{
flag=0;
printf("It is not safe Sequence");
break;
}
}
if(flag==1)
{
printf("It is a safe Sequence\n");
for (i = 0; i < n - 1; i++)
printf("P%d -> ", ans[i]);
printf("P%d\n", ans[n - 1]);
}
return (0);
}

OUTPUT:

2)

ALGORITHM:
1. Create Allocation and Maximum matrix

2. Calculated Need Matrix as Need[i][j] = Max[i][j] – Allocation[i][j].

3. Create a finish array to track which processes have completed.Initialize a work array
with the values from the available resources.
4. For each process check if it can finish If it can finish Print that the process can finish ,
Release its allocated resources , Mark the process as finished.
5. If it cannot finish Print that the process cannot finish.

6. After exiting the loop, check the finish array, If any process is still not finished,
a deadlock is detected.
7. Finaly Print whether a deadlock was detected or not.

CODE:
#include <stdio.h>
#include <stdbool.h>
#define P 5
#define R 3
bool isDeadlocked(int allocation[P][R], int max[P][R], int need[P][R], int available[R]) {
bool finish[P] = {false};
int work[R];
for (int i = 0; i < R; i++) {
work[i] = available[i];
}
bool progress = true;
printf("process sequence:\n");
while (progress) {
progress = false;
for (int p = 0; p < P; p++) {
if (!finish[p]) {
bool canFinish = true;
for (int r = 0; r < R; r++) {
if (need[p][r] > work[r]) {
canFinish = false;
break;
}
}
if (canFinish) { printf("P
%d -> ", p);
for (int r = 0; r < R; r++) {
work[r] += allocation[p][r];
}
finish[p] = true;
progress = true;
} else {
printf("Process %d cannot finish.\n", p);
}
}
}
}
for (int p = 0; p < P; p++) {
if (!finish[p]) {
printf("\nDeadlock detected involving Process %d\n", p);
return true;
}
}
printf("\nNo deadlock detected.\n");
return false;
}
int main() {
int allocation[P][R] = {{0, 1, 0},{2, 0, 0},{0, 0, 1},{1, 0, 0},{0, 0, 0}};
int max[P][R] = {{0, 1, 1},{2, 1, 1},{1, 0, 2},{1, 1, 1},{0, 0, 1}};
int available[R] = {1, 1, 2};
int need[P][R];
for (int i = 0; i < P; i++) {
for (int j = 0; j < R; j++) {
need[i][j] = max[i][j] - allocation[i][j];
}
}
isDeadlocked(allocation, max, need, available);
return 0;
}

OUTPUT:

RESULT:
The program is executed successfully and output has been verified.
EX 10 PAGE REPLACEMENT ALGORITHMS
17/10/24

AIM:
To Write a C program to implement various page replacement
algorithms.

ALGORITHM 1:
1) Start with an empty page frame and set counters for page hits and page
faults to zero.
2) For each page in the list:

Check if the page is already in the frame:


If it is, count it as a hit.
If it isn't:
Count it as a fault.
If the frame is full, remove the oldest page.
Add the new page to the frame.
3) Display the current contents of the page frame along with the counts of hits and faults.

4) Continue until all pages have been processed.

ALGORITHM 2:
1) Start with an empty page frame and set counters for page hits
and page faults to zero.
2) For each page in the list:

Check if the page is in the frame:


If yes, count it as a hit.
If no:
Count it as a fault.
If the frame is full, find the page that will not be used for the longest time and replace it.
If the frame is not full, add the new page directly.
3) Display the current contents of the page frame, along with the counts of hits and faults.

4) Repeat until all pages have been processed.


ALGORITHM 3:
1) Start with an empty page frame and set counters for page hits
and page faults to zero.
2) For each page in the list:
Check if the page is in the frame:
If yes, count it as a hit.
If no:
Count it as a fault.
If the frame is full, find the page that was used least recently and replace it.
If the frame is not full, add the new page directly.
3) Display the current contents of the page frame, along with the counts of hits and faults.
4) Repeat until all pages have been processed.

ALGORITHM 4:
1) Start with an empty page frame and set counters for page hits
and page faults to zero.
2) For each page in the list:
Check if the page is in the frame:
If yes, count it as a hit.
If no:
Count it as a fault.
If the frame is full, find the page that was used most recently and replace it.
If the frame is not full, add the new page directly.
3) Display the current contents of the page frame, along with the counts of hits and faults.

4) Repeat until all pages have been processed.

Program 1:
FCFS:
#include <stdio.h>
#define MAX_PAGES 100
void fcfsPageReplacement(int pages[], int numPages, int
capacity) {
int pageFrame[MAX_PAGES];
int pageFaults = 0;
int pageHits = 0;
int i, j;
int isPageFound;

for (i = 0; i < capacity; i++) {


pageFrame[i] = -1;
}

for (i = 0; i < numPages; i++) {


isPageFound = 0;

for (j = 0; j < capacity; j++) {


if (pageFrame[j] == pages[i]) {
isPageFound = 1;
pageHits++;
break;
}
}
if (!isPageFound) {
pageFaults++;
if (i >= capacity) {
for (j = 0; j < capacity - 1; j++) {
pageFrame[j] = pageFrame[j + 1];
}
pageFrame[capacity - 1] = pages[i];
} else {
pageFrame[i] = pages[i];
}
}
printf("Current pages in frame: ");
for (j = 0; j < capacity; j++) {
if (pageFrame[j] != -1) {
printf("%d ", pageFrame[j]);
}
}
printf("| Page hits: %d, Page faults: %d\n", pageHits,
pageFaults);
}
}
int main() {
int pages[] = {1, 2, 3, 1, 4, 2, 5, 1, 2, 3, 4, 5};
int numPages = sizeof(pages) / sizeof(pages[0]);
int capacity = 3;

fcfsPageReplacement(pages, numPages, capacity);


return 0;
}

Program 2:
OPR:
#include <stdio.h>
#define MAX_PAGES 100
void fcfsPageReplacement(int pages[], int numPages, int
capacity) {
int pageFrame[MAX_PAGES];
int pageFaults = 0;
int pageHits = 0;
int i, j;
int isPageFound;

for (i = 0; i < capacity; i++) {


pageFrame[i] = -1;
}

for (i = 0; i < numPages; i++) {


isPageFound = 0;
for (j = 0; j < capacity; j++) {
if (pageFrame[j] == pages[i]) {
isPageFound = 1;
pageHits++;
break;
}
}
if (!isPageFound) {
pageFaults++;
if (i >= capacity) {
for (j = 0; j < capacity - 1; j++) {
pageFrame[j] = pageFrame[j + 1];
}
pageFrame[capacity - 1] = pages[i];
} else {
pageFrame[i] = pages[i];
}
}
printf("Current pages in frame: ");
for (j = 0; j < capacity; j++) {
if (pageFrame[j] != -1) {
printf("%d ", pageFrame[j]);
}
}
printf("| Page hits: %d, Page faults: %d\n", pageHits,
pageFaults);
}
}
int main() {
int pages[] = {1, 2, 3, 1, 4, 2, 5, 1, 2, 3, 4, 5};
int numPages = sizeof(pages) / sizeof(pages[0]);
int capacity = 3;
fcfsPageReplacement(pages, numPages, capacity);
return 0;
}

Program 2:
OPR:
#include <stdio.h>
#include <limits.h>
#define MAX_PAGES 100

int findOptimalPage(int pages[], int pageFrame[], int numPages,


int currentIndex, int capacity) {
int furthestIndex = -1;
int pageToReplace = -1;

for (int i = 0; i < capacity; i++) {


int j;
for (j = currentIndex; j < numPages; j++) {
if (pageFrame[i] == pages[j]) {
if (j > furthestIndex) {
furthestIndex = j;
pageToReplace = i;
}
break;
}
}
if (j == numPages) {
return i;
}
}
return pageToReplace;
}
void optimalPageReplacement(int pages[], int numPages, int
capacity) {
int pageFrame[MAX_PAGES];
int pageFaults = 0;
int pageHits = 0;
int currentIndex;

for (int i = 0; i < capacity; i++) {


pageFrame[i] = -1;
}

for (currentIndex = 0; currentIndex < numPages; currentIndex+


+) {
int isPageFound = 0;

for (int j = 0; j < capacity; j++) {


if (pageFrame[j] == pages[currentIndex]) {
isPageFound = 1;
pageHits++;
break;
}
}

if (!isPageFound) {
pageFaults++;
if (currentIndex >= capacity) {
int indexToReplace = findOptimalPage(pages,
pageFrame, numPages, currentIndex + 1, capacity);
pageFrame[indexToReplace] = pages[currentIndex];
} else {
pageFrame[currentIndex] = pages[currentIndex];
}
}
printf("Current pages in frame: ");
for (int j = 0; j < capacity; j++) {
if (pageFrame[j] != -1) {
printf("%d ", pageFrame[j]);
}
}
printf("| Page hits: %d, Page faults: %d\n", pageHits,
pageFaults);
}
}
int main() {
int pages[] = {1, 2, 3, 1, 4, 2, 5, 1, 2, 3, 4, 5};
int numPages = sizeof(pages) / sizeof(pages[0]);
int capacity = 3;

optimalPageReplacement(pages, numPages, capacity);

return 0;
}

Program 3:

LRU:
#include <stdio.h>
#include <stdbool.h>
#define MAX_PAGES 100

int findLRU(int pages[], int pageFrame[], int numPages, int


currentIndex, int capacity) {
int lruIndex = -1;
int lruTime = -1;

for (int i = 0; i < capacity; i++) {


int j;
for (j = currentIndex - 1; j >= 0; j--) {
if (pageFrame[i] == pages[j]) {
if (j < lruTime || lruTime == -1) {
lruTime = j;
lruIndex = i;
}
break;
}
}
if (j < 0) {
return i;
}
}
return lruIndex;
}

void lruPageReplacement(int pages[], int numPages, int capacity)


{
int pageFrame[MAX_PAGES];
int pageFaults = 0;
int pageHits = 0;

for (int i = 0; i < capacity; i++) {


pageFrame[i] = -1;
}

for (int currentIndex = 0; currentIndex < numPages;


currentIndex++) {
bool isPageFound = false;

for (int j = 0; j < capacity; j++) {


if (pageFrame[j] == pages[currentIndex]) {
isPageFound = true;
pageHits++;
break;
}
}
if (!isPageFound) {
pageFaults++;
if (currentIndex >= capacity) {
int indexToReplace = findLRU(pages, pageFrame,
numPages, currentIndex, capacity);
pageFrame[indexToReplace] = pages[currentIndex];
} else {
pageFrame[currentIndex] = pages[currentIndex];
}
}
printf("Current pages in frame: ");
for (int j = 0; j < capacity; j++) {
if (pageFrame[j] != -1) {
printf("%d ", pageFrame[j]);
}
}
printf("| Page hits: %d, Page faults: %d\n", pageHits,
pageFaults);
}
}
int main() {
int pages[] = {1, 2, 3, 1, 4, 2, 5, 1, 2, 3, 4, 5};
int numPages = sizeof(pages) / sizeof(pages[0]);
int capacity = 3;
lruPageReplacement(pages, numPages, capacity);
return 0;
}
Program 4:
MRU:
#include <stdio.h>
#include <stdbool.h>
#define MAX_PAGES 100

int findMRU(int pages[], int pageFrame[], int currentIndex, int


capacity) {
int mruIndex = -1;
int mruTime = -1;

for (int i = 0; i < capacity; i++) {


if (pageFrame[i] != -1) {
for (int j = currentIndex - 1; j >= 0; j--) {
if (pageFrame[i] == pages[j]) {
if (j > mruTime) {
mruTime = j;
mruIndex = i;
}
break;
}
}
}
}

return mruIndex;
}

void mruPageReplacement(int pages[], int numPages, int


capacity) {
int pageFrame[MAX_PAGES];
int pageFaults = 0;
int pageHits = 0;
for (int i = 0; i < capacity; i++) {
pageFrame[i] = -1;
}

for (int currentIndex = 0; currentIndex < numPages;


currentIndex++) {
bool isPageFound = false;
for (int j = 0; j < capacity; j++) {
if (pageFrame[j] == pages[currentIndex]) {
isPageFound = true;
pageHits++;
break;
}
}

if (!isPageFound) {
pageFaults++;
if (currentIndex >= capacity) {
int indexToReplace = findMRU(pages, pageFrame,
currentIndex, capacity);
pageFrame[indexToReplace] = pages[currentIndex];
pageFrame[currentIndex] = pages[currentIndex];
}
}

printf("Current pages in frame: ");


for (int j = 0; j < capacity; j++) {
if (pageFrame[j] != -1) {
printf("%d ", pageFrame[j]);
}
}
printf("| Page hits: %d, Page faults: %d\n", pageHits,
pageFaults);
}
}
int main() {
int pages[] = {1, 2, 3, 1, 4, 2, 5, 1, 2, 3, 4, 5};
int numPages = sizeof(pages) / sizeof(pages[0]);
int capacity = 3;
mruPageReplacement(pages, numPages, capacity);
return 0;
}

Sample Input/Output 1:
FCFS:
Sample Input/Output 2:
OPR:

Sample Input/Output 3:
LRU:
Sample Input/Output 4:
MRU:

RESULT:
Thus C programs for implementing various Page replacement
algorithms are created and executed successfully.

You might also like