0% found this document useful (0 votes)
18 views52 pages

Oslab (03 02 26)

The document provides implementations for simulating various Unix commands and CPU scheduling algorithms, including a copy command in C, FCFS, SJF, Priority, and Round Robin scheduling in Java. Each section includes code snippets, user inputs, and expected outputs for the respective algorithms. Additionally, it discusses controlling the number of open ports using semaphores in Java.

Uploaded by

chinnamsaikiran3
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views52 pages

Oslab (03 02 26)

The document provides implementations for simulating various Unix commands and CPU scheduling algorithms, including a copy command in C, FCFS, SJF, Priority, and Round Robin scheduling in Java. Each section includes code snippets, user inputs, and expected outputs for the respective algorithms. Additionally, it discusses controlling the number of open ports using semaphores in Java.

Uploaded by

chinnamsaikiran3
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

1.3.

1 SIMULATE UNIX COMMAND CP


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#define BUFFER_SIZE 1024
int main(int argc, char **argv) {
int source_fd, dest_fd; // File descriptors
ssize_t count; // Number of bytes read/written
char buffer[BUFFER_SIZE]; // Buffer to hold data during copy

// Check for insufficient parameters (need source and destination file names)
if (argc < 3) {
printf("Usage: %s <source_file> <destination_file>\n", argv[0]);
return 1;
}

// Open the source file in read-only mode


source_fd = open(argv[1], O_RDONLY);
if (source_fd == -1) {
perror("Error opening source file");
return 1;
}

// Create the destination file for writing; if it exists, overwrite it


// Permissions set to read/write for the user (S_IRUSR | S_IWUSR)
dest_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (dest_fd == -1) {
perror("Error creating destination file");
close(source_fd); // Close the source file before exiting
return 1;
}

// Read from source file and write to destination file in chunks


while ((count = read(source_fd, buffer, sizeof(buffer))) > 0) {
if (write(dest_fd, buffer, count) != count) {
perror("Error writing to destination file");
close(source_fd);
close(dest_fd);
return 1;
}
}

if (count == -1) {
perror("Error reading from source file");
}

// Close both files


close(source_fd);
close(dest_fd);

printf("File copied successfully from %s to %s\n", argv[1], argv[2]);


return 0;
}
OUTPUT:

*********************************************************************

2. Simulate the following CPU scheduling algorithms


(a)FCFS :

import [Link];

public class FCFSScheduler {

// Process class to hold process details

static class Process {

int id; // Process ID

int arrivalTime; // Arrival time

int burstTime; // Burst time

int completionTime; // Completion time

int waitingTime; // Waiting time

int turnaroundTime; // Turnaround time

public Process(int id, int arrivalTime, int burstTime) {

[Link] = id;

[Link] = arrivalTime;

[Link] = burstTime;

}
public static void main(String[] args) {

Scanner scanner = new Scanner([Link]);

[Link]("Enter the number of processes: ");

int n = [Link]();

Process[] processes = new Process[n];

// Input process details

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

[Link]("\nEnter details for Process " + (i + 1) + ":");

[Link]("Arrival Time: ");

int arrival = [Link]();

[Link]("Burst Time: ");

int burst = [Link]();

processes[i] = new Process(i + 1, arrival, burst);

// Sort processes by arrival time for FCFS

// This is crucial for FCFS, as the process that arrives first is served first.

// If arrival times are the same, the order of input processes is maintained.

[Link](processes, (p1, p2) -> [Link] - [Link]);

// FCFS Scheduling Logic

int currentTime = 0;

float totalWaitingTime = 0;
float totalTurnaroundTime = 0;

for (Process p : processes) {

// If the CPU is idle until the process arrives

if (currentTime < [Link]) {

currentTime = [Link];

// Calculate completion time

[Link] = currentTime + [Link];

// Calculate turnaround time

[Link] = [Link] - [Link];

// Calculate waiting time

[Link] = [Link] - [Link];

// Update current time

currentTime = [Link];

totalWaitingTime += [Link];

totalTurnaroundTime += [Link];

// Display Results

[Link]("\n--- FCFS Scheduling Results ---");

[Link]("%-10s%-15s%-15s%-15s%-15s%-15s\n",

"Process", "Arrival Time", "Burst Time", "Completion Time", "Turnaround


Time", "Waiting Time");
for (Process p : processes) {

[Link]("%-10d%-15d%-15d%-15d%-15d%-15d\n",

[Link], [Link], [Link], [Link], [Link],


[Link]);

[Link]("\nAverage Waiting Time: %.2f\n", totalWaitingTime / n);

[Link]("Average Turnaround Time: %.2f\n", totalTurnaroundTime /


n);

[Link]();

OUTPUT:

Enter the number of processes: 2

Enter details for Process 1:

Arrival Time: 1

Burst Time: 9

Enter details for Process 2:

Arrival Time: 2

Burst Time: 5

--- FCFS Scheduling Results ---

Process ArrivalTime BurstTime CompletioTime TurnaroundTime Waiting Time

1 1 9 10 9 0

2 2 5 15 13 8
Average Waiting Time: 4.00

Average Turnaround Time: 11.00

[Link] the following CPU scheduling algorithms


b) SJF:

#include<stdio.h>

void main()

int bt[20],p[20],wt[20],tat[20],i,j,n,total=0,pos,temp;

float avg_wt,avg_tat;

printf("Enter number of process:");

scanf("%d",&n);

printf("\nEnter Burst Time:\n");

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

printf("p%d:",i+1);

scanf("%d",&bt[i]);

p[i]=i+1;

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

pos=i;

for(j=i+1;j<n;j++)

if(bt[j]<bt[pos])

pos=j;
}

temp=bt[i];

bt[i]=bt[pos];

bt[pos]=temp;

temp=p[i];

p[i]=p[pos];

p[pos]=temp;

wt[0]=0;

for(i=1;i<n;i++)

wt[i]=0;

for(j=0;j<i;j++)wt[i]+=bt[j];

total+=wt[i];

avg_wt=(float)total/n;

total=0;

printf("\nProcess\t Burst Time \tWaiting Time\tTurnaround Time");

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

tat[i]=bt[i]+wt[i];

total+=tat[i];

printf("\np%d\t\t %d\t\t %d\t\t\t%d",p[i],bt[i],wt[i],tat[i]);

avg_tat=(float)total/n;

printf("\n\nAverage Waiting Time=%f",avg_wt);

printf("\nAverage Turnaround Time=%f\n",avg_tat);


}

OUTPUT:

Enter number of process:2

Enter Burst Time:

p1:5

p2:4

Process Burst Time Waiting Time Turnaround Time

p2 4 0 4

p1 5 4 9

Average Waiting Time=2.000000

Average Turnaround Time=6.500000

2.( c ) Priority

import [Link];

public class priority{

public static void main(String args[]) {


Scanner s = new Scanner([Link]);

int x,n,p[],pp[],bt[],w[],t[],awt,atat,i;

p = new int[10];
pp = new int[10];
bt = new int[10];
w = new int[10];
t = new int[10];

//n is number of process


//p is process
//pp is process priority
//bt is process burst time
//w is wait time
// t is turnaround time
//awt is average waiting time
//atat is average turnaround time

[Link]("Enter the number of process : ");


n = [Link]();
[Link]("\n\t Enter burst time : time priorities \n");

for(i=0;i<n;i++)
{
[Link]("\nProcess["+(i+1)+"]:");
bt[i] = [Link]();
pp[i] = [Link]();
p[i]=i+1;
}

//sorting on the basis of priority


for(i=0;i<n-1;i++)
{
for(int j=i+1;j<n;j++)
{
if(pp[i]>pp[j])
{
x=pp[i];
pp[i]=pp[j];
pp[j]=x;
x=bt[i];
bt[i]=bt[j];
bt[j]=x;
x=p[i];
p[i]=p[j];
p[j]=x;
}
}
}
w[0]=0;
awt=0;
t[0]=bt[0];
atat=t[0];
for(i=1;i<n;i++)
{
w[i]=t[i-1];
awt+=w[i];
t[i]=w[i]+bt[i];
atat+=t[i];
}

//Displaying the process

[Link]("\n\nProcess \t Burst Time \t Wait Time \t Turn Around Time


Priority \n");
for(i=0;i<n;i++)
[Link]("\n "+p[i]+"\t\t "+bt[i]+"\t\t "+w[i]+"\t\t "+t[i]+"\t\t
"+pp[i]+"\n");
awt/=n;
atat/=n;
[Link]("\n Average Wait Time : "+awt);
[Link]("\n Average Turn Around Time : "+atat);

}
}

OUTPUT:

Enter the number of process : 3

Enter burst time : time priorities

Process[1]:2

Process[2]:3

Process[3]:2

Process Burst Time Wait Time Turn Around Time Priority

3 2 0 2 0

2 3 2 5 1
1 2 5 7 3

Average Wait Time : 2

Average Turn Around Time : 4

2(d) Round Robin

import [Link];

public class RoundRobin {

public static void main(String[] args) {

Scanner s = new Scanner([Link]);

int[] burstTime, waitingTime, turnAroundTime,


remainingBurstTime;

int numProcesses, quantum, totalWaitingTime = 0,


totalTurnAroundTime = 0;

[Link]("Enter number of processes: ");

numProcesses = [Link]();

burstTime = new int[numProcesses];

waitingTime = new int[numProcesses];

turnAroundTime = new int[numProcesses];

remainingBurstTime = new int[numProcesses];

[Link]("Enter burst time for each process:");

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

[Link]("P[" + (i + 1) + "]: ");


burstTime[i] = [Link]();

remainingBurstTime[i] = burstTime[i]; // Copy burst time to


remaining burst time

[Link]("Enter time quantum: ");

quantum = [Link]();

int currentTime = 0; // Current time

int completedProcesses = 0;

// Index 'i' cycles through processes, implementing the round-robin


queue logic

for (int i = 0; completedProcesses != numProcesses; i = (i + 1) %


numProcesses) {

// Check if the current process still has remaining burst time

if (remainingBurstTime[i] > 0) {

// If remaining time is more than quantum, execute for


quantum time

if (remainingBurstTime[i] > quantum) {

currentTime += quantum;

remainingBurstTime[i] -= quantum;

// If remaining time is less than or equal to quantum, execute


completely

else {

currentTime += remainingBurstTime[i];

waitingTime[i] = currentTime - burstTime[i]; // Calculate


waiting time
remainingBurstTime[i] = 0; // Mark process as completed

completedProcesses++;

// Calculate Turnaround Time and Total Times

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

turnAroundTime[i] = burstTime[i] + waitingTime[i];

totalWaitingTime += waitingTime[i];

totalTurnAroundTime += turnAroundTime[i];

// Print results

[Link]("\nProcess\t\tBurst Time\tWaiting Time\


tTurnaround Time");

[Link]("-------------------------------------------------------");

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

[Link]("P[" + (i + 1) + "]\t\t" + burstTime[i] + "\t\t"


+ waitingTime[i] + "\t\t" + turnAroundTime[i]);

[Link]("\nAverage Waiting Time: " + (float)


totalWaitingTime / numProcesses);

[Link]("Average Turnaround Time: " + (float)


totalTurnAroundTime / numProcesses);

[Link]();

OUTPUT:
number of processes: 3

Enter burst time for each process:

P[1]: 3

P[2]: 2

P[3]: 4

Enter time quantum: 2

Process Burst Time Waiting Time Turnaround Time

-------------------------------------------------------

P[1] 3 4 7

P[2] 2 2 4

P[3] 4 5 9

Average Waiting Time: 3.6666667

Average Turnaround Time: 6.6666665

2.2 (a) Control the number of ports opened by the operating system with
( a )Semaphore

//These lines import necessary classes from Java's networking and concurrency
libraries. ServerSocket is used to open ports, and classes
from [Link] are crucial for multi-threading and synchronization
mechanisms.

import [Link];

import [Link];

import [Link];

import [Link];

import [Link];

import [Link];

import [Link];
public class PortControlWithSemaphore {

// Define the maximum number of concurrent ports/connections your app can


use

private static final int MAX_CONCURRENT_PORTS = 5;

//A constant integer variable is defined, setting the limit for how many ports can
be open simultaneously (in this case, 5).

private static final Semaphore SEMAPHORE = new


Semaphore(MAX_CONCURRENT_PORTS);

//A static, thread-safe (due to later synchronization) list is declared to keep track
of all currently open ServerSocket objects for later cleanup.

private static final List<ServerSocket> openSockets = new ArrayList<>();

//The main method starts here. An ExecutorService is created with a thread pool
size of 10. This service will manage the threads that attempt to open ports.

public static void main(String[] args) throws InterruptedException {

ExecutorService executor = [Link](10);

//A loop runs 10 times, creating 10 separate tasks. Each task is submitted to
the ExecutorService using a lambda expression () -> openPort(port). This
effectively tries to open ports 8000 through 8009 concurrently.

// Try to initiate 10 "port opening" tasks

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

final int port = 8000 + i;

[Link](() -> openPort(port));

//[Link]() stops the executor from accepting new


tasks. [Link](...) makes the main thread pause and wait for
up to one minute for all submitted tasks (the 10 port opening attempts) to
complete before proceeding.
[Link]();

[Link](1, [Link]);

//This block handles the cleanup phase. After all threads have finished their
simulated work, the program iterates through the openSockets list and closes all
of them.

// Clean up open sockets after demonstration

[Link]("\nClosing all open sockets.");

for (ServerSocket socket : openSockets) {

try {

[Link]();

} catch (Exception e) {

[Link]();

[Link]("Finished.");

//This is the core logic method executed by each thread. The crucial line
is [Link]();. This method blocks the current thread if all 5
permits are currently in use. The thread will wait here until a permit is available.
Once a permit is successfully acquired, the code proceeds.

private static void openPort(int portNumber) {

try {

// Acquire a permit from the semaphore (waits if limit is


reached)

[Link]("Attempting to acquire permit for port "


+portNumber + "...");

[Link]();
[Link]("Permit acquired for port " + portNumber +
". Opening port...");

//This is the "critical section"—the code that must be executed only when a
permit is held.

1. A ServerSocket is instantiated, actually opening the network port.


2. synchronized (openSockets) is used to protect the shared openSockets list from
concurrent modification by multiple threads. The socket is added to the list.

// --- CRITICAL SECTION: Code that requires a limited resource (the port) ---
ServerSocket serverSocket = new ServerSocket(portNumber);

synchronized (openSockets) {

[Link](serverSocket);

[Link]("Port " + portNumber + " opened


successfully.");

// -------------------------------------------------------------------------

// Simulate the port being used for a short duration ie for 2 sec

[Link](2000);

//This finally block is essential for robust concurrency management.

 [Link](); is called here to ensure that the permit


is always returned to the semaphore pool, regardless of whether the operations
within the try block succeeded or threw an exception (e.g., if the port was
already in use and new ServerSocket(portNumber) failed). This prevents
resource leaks and deadlocks.
 The catch blocks handle potential errors like InterruptedException (if the
thread is asked to stop while sleeping or waiting for a permit) or IOException (if
the port cannot be opened).

} catch (InterruptedException e) {

[Link]().interrupt();

} catch ([Link] e) {
[Link]("Could not open port " + portNumber + ": "
+ [Link]());

} finally {

// Ensure the permit is always released, even if an error occurs

[Link]("Releasing permit for port " + portNumber


+ ".");

[Link]();

OUTPUT:

Attempting to acquire permit for port 8003...

Attempting to acquire permit for port 8004...

Permit acquired for port 8004. Opening port...

Attempting to acquire permit for port 8000...

Permit acquired for port 8000. Opening port...

Attempting to acquire permit for port 8002...

Permit acquired for port 8002. Opening port...

Attempting to acquire permit for port 8001...

Permit acquired for port 8003. Opening port...

Attempting to acquire permit for port 8005...

Attempting to acquire permit for port 8006...

Permit acquired for port 8001. Opening port...

Attempting to acquire permit for port 8007...

Attempting to acquire permit for port 8008...

Attempting to acquire permit for port 8009...

Port 8000 opened successfully.

Port 8003 opened successfully.


Port 8002 opened successfully.

Port 8004 opened successfully.

Port 8001 opened successfully.

Releasing permit for port 8000.

Releasing permit for port 8003.

Permit acquired for port 8005. Opening port...

Releasing permit for port 8001.

Port 8005 opened successfully.

Releasing permit for port 8002.

Permit acquired for port 8008. Opening port...

Port 8008 opened successfully.

Releasing permit for port 8004.

Permit acquired for port 8006. Opening port...

Permit acquired for port 8009. Opening port...

Port 8006 opened successfully.

Port 8009 opened successfully.

Permit acquired for port 8007. Opening port...

Port 8007 opened successfully.

Releasing permit for port 8005.

Releasing permit for port 8008.

Releasing permit for port 8006.

Releasing permit for port 8009.

Releasing permit for port 8007.

Closing all open sockets.

Finished.

2.2(b) Control the number of ports opened by the operating system with
( b)Monitors

import [Link];

import [Link];

public class PortControllerMonitor {

// Maximum number of ports allowed at a time

private static final int MAX_CONCURRENT_PORTS = 5;

// Current number of ports in use

private int currentPorts = 0;

// ================= MONITOR METHOD =================

////Only one thread can execute these methods at a time


This is automatic locking → Monitor property

// synchronized ensures mutual exclusion

public synchronized void acquirePort(int portNumber) throws


InterruptedException {

[Link]([Link]().getName() +

": Trying to acquire port " + portNumber);

// Condition check (Monitor condition variable)

while (currentPorts == MAX_CONCURRENT_PORTS) {

[Link]([Link]().getName() +

": No ports available. Waiting...");

wait(); // Thread goes to waiting state


}

// Port is available

currentPorts++;

[Link]([Link]().getName() +

": Acquired port " + portNumber +

" | Ports in use: " + currentPorts);

// ================= MONITOR METHOD =================

public synchronized void releasePort(int portNumber) {

currentPorts--;

[Link]([Link]().getName() +

": Released port " + portNumber +

" | Ports in use: " + currentPorts);

//Wakes up waiting threads when a port is released


Standard monitor signaling

notifyAll(); // Wake up waiting threads

// ================= MAIN METHOD =================

public static void main(String[] args) {

PortControllerMonitor controller = new PortControllerMonitor();


// Create more threads than available ports

ExecutorService executor = [Link](10);

for (int i = 1; i <= 10; i++) {

final int port = 8080 + i;

[Link](() -> {

try {

[Link](port);

// Simulate port usage

[Link](2000);

} catch (InterruptedException e) {

[Link]("Thread interrupted");

} finally {

[Link](port);

});

[Link]();

OUTPUT:
pool-1-thread-1: Trying to acquire port 8081

pool-1-thread-1: Acquired port 8081 | Ports in use: 1

pool-1-thread-10: Trying to acquire port 8090

pool-1-thread-10: Acquired port 8090 | Ports in use: 2

pool-1-thread-9: Trying to acquire port 8089

pool-1-thread-9: Acquired port 8089 | Ports in use: 3

pool-1-thread-8: Trying to acquire port 8088

pool-1-thread-8: Acquired port 8088 | Ports in use: 4

pool-1-thread-7: Trying to acquire port 8087

pool-1-thread-7: Acquired port 8087 | Ports in use: 5

pool-1-thread-6: Trying to acquire port 8086

pool-1-thread-6: No ports available. Waiting...

pool-1-thread-5: Trying to acquire port 8085

pool-1-thread-5: No ports available. Waiting...

pool-1-thread-4: Trying to acquire port 8084

pool-1-thread-4: No ports available. Waiting...

pool-1-thread-3: Trying to acquire port 8083

pool-1-thread-3: No ports available. Waiting...

pool-1-thread-2: Trying to acquire port 8082

pool-1-thread-2: No ports available. Waiting...

pool-1-thread-10: Released port 8090 | Ports in use: 4

pool-1-thread-6: Acquired port 8086 | Ports in use: 5

pool-1-thread-2: No ports available. Waiting...

pool-1-thread-3: No ports available. Waiting...

pool-1-thread-4: No ports available. Waiting...

pool-1-thread-5: No ports available. Waiting...

pool-1-thread-8: Released port 8088 | Ports in use: 4


pool-1-thread-7: Released port 8087 | Ports in use: 3

pool-1-thread-9: Released port 8089 | Ports in use: 2

pool-1-thread-1: Released port 8081 | Ports in use: 1

pool-1-thread-5: Acquired port 8085 | Ports in use: 2

pool-1-thread-4: Acquired port 8084 | Ports in use: 3

pool-1-thread-3: Acquired port 8083 | Ports in use: 4

pool-1-thread-2: Acquired port 8082 | Ports in use: 5

pool-1-thread-6: Released port 8086 | Ports in use: 4

pool-1-thread-5: Released port 8085 | Ports in use: 3

pool-1-thread-4: Released port 8084 | Ports in use: 2

pool-1-thread-3: Released port 8083 | Ports in use: 1

pool-1-thread-2: Released port 8082 | Ports in use: 0

---------------------------------**********-------------------------------------------

3.1 Write a program to illustrate concurrent execution of threads using


pthreads library.

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h> // For sleep()

#include <pthread.h>

// Function that the first thread will execute

void *thread_function1(void *arg) {

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

printf("Thread 1 is running (iteration %d)\n", i);

sleep(1); // Sleep for 1 second to illustrate concurrency

}
printf("Thread 1 finished.\n");

return NULL;

// Function that the second thread will execute

void *thread_function2(void *arg) {

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

printf("Thread 2 is running (iteration %d)\n", i);

sleep(2); // Sleep for 2 seconds

printf("Thread 2 finished.\n");

return NULL;

int main() {

pthread_t thread1_id;

pthread_t thread2_id;

printf("Main thread: Creating Thread 1 and Thread 2\n");

// Create the first thread

// pthread_create(thread_pointer, attributes, start_routine,


argument)

if (pthread_create(&thread1_id, NULL, thread_function1, NULL) !=


0) {

fprintf(stderr, "Error creating thread 1\n");

return 1;

}
// Create the second thread

if (pthread_create(&thread2_id, NULL, thread_function2, NULL) !=


0) {

fprintf(stderr, "Error creating thread 2\n");

return 1;

printf("Main thread: Both threads created. Waiting for them to


finish...\n");

// Wait for the first thread to finish

if (pthread_join(thread1_id, NULL) != 0) {

fprintf(stderr, "Error joining thread 1\n");

return 1;

// Wait for the second thread to finish

if (pthread_join(thread2_id, NULL) != 0) {

fprintf(stderr, "Error joining thread 2\n");

return 1;

printf("Main thread: Both threads finished. Exiting.\n");

return 0;

OUTPUT:
Main thread: Creating Thread 1 and Thread 2

Thread 1 is running (iteration 0)

Thread 2 is running (iteration 0)

Main thread: Both threads created. Waiting for them to finish...

Thread 1 is running (iteration 1)

Thread 2 is running (iteration 1)

Thread 1 is running (iteration 2)

Thread 1 is running (iteration 3)

Thread 2 is running (iteration 2)

Thread 1 is running (iteration 4)

Thread 1 finished.

Thread 2 finished.

Main thread: Both threads finished. Exiting.

3.2 Write a program to solve producer-consumer problem using Semaphores.


#include <stdio.h>

#include <stdlib.h>

#include <pthread.h>

#include <semaphore.h>

#include <unistd.h>

#define BUFFER_SIZE 10

#define NUM_PRODUCERS 1

#define NUM_CONSUMERS 1

int buffer[BUFFER_SIZE];

int in = 0; // Index for the next item to be produced


int out = 0; // Index for the next item to be consumed

sem_t empty; // Counts the number of empty slots in the buffer

sem_t full; // Counts the number of full slots in the buffer

pthread_mutex_t mutex; // Mutex lock for critical section (buffer


access)

void* producer(void* arg) {

int item_produced;

for (int i = 0; i < 20; i++) { // Produce 20 items

item_produced = i;

// Wait for an empty slot (decrement empty semaphore)

sem_wait(&empty);

// Acquire the mutex lock

pthread_mutex_lock(&mutex);

// --- Critical Section ---

buffer[in] = item_produced;

printf("Producer produced item %d at slot %d\n",


item_produced, in);

in = (in + 1) % BUFFER_SIZE;

// --- End of Critical Section ---

// Release the mutex lock

pthread_mutex_unlock(&mutex);

// Signal that a slot is full (increment full semaphore)

sem_post(&full);
// Sleep for a short duration to simulate work

usleep(rand() % 1000000);

return NULL;

void* consumer(void* arg) {

int item_consumed;

for (int i = 0; i < 20; i++) { // Consume 20 items

// Wait for a full slot (decrement full semaphore)

sem_wait(&full);

// Acquire the mutex lock

pthread_mutex_lock(&mutex);

// --- Critical Section ---

item_consumed = buffer[out];

printf("Consumer consumed item %d from slot %d\n",


item_consumed, out);

out = (out + 1) % BUFFER_SIZE;

// --- End of Critical Section ---

// Release the mutex lock

pthread_mutex_unlock(&mutex);

// Signal that a slot is empty (increment empty semaphore)

sem_post(&empty);
// Sleep for a short duration to simulate work

usleep(rand() % 2000000);

return NULL;

int main() {

pthread_t prod_threads[NUM_PRODUCERS],
cons_threads[NUM_CONSUMERS];

// Initialize semaphores:

// sem_init(&semaphore, pshared, value);

// pshared = 0 means the semaphore is shared between threads of a


process.

// initial value of 'empty' is BUFFER_SIZE

sem_init(&empty, 0, BUFFER_SIZE);

// initial value of 'full' is 0

sem_init(&full, 0, 0);

// Initialize mutex

pthread_mutex_init(&mutex, NULL);

// Create producer threads

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

pthread_create(&prod_threads[i], NULL, producer, NULL);

// Create consumer threads

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

pthread_create(&cons_threads[i], NULL, consumer, NULL);


}

// Join threads (wait for them to finish)

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

pthread_join(prod_threads[i], NULL);

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

pthread_join(cons_threads[i], NULL);

// Destroy semaphores and mutex

sem_destroy(&empty);

sem_destroy(&full);

pthread_mutex_destroy(&mutex);

return 0;

OUTPUT:

Producer produced item 0 at slot 0

Consumer consumed item 0 from slot 0

Producer produced item 1 at slot 1

Consumer consumed item 1 from slot 1

Producer produced item 2 at slot 2

Consumer consumed item 2 from slot 2

Producer produced item 3 at slot 3

Consumer consumed item 3 from slot 3


Producer produced item 4 at slot 4

Producer produced item 5 at slot 5

Consumer consumed item 4 from slot 4

Producer produced item 6 at slot 6

Producer produced item 7 at slot 7

Producer produced item 8 at slot 8

Consumer consumed item 5 from slot 5

Producer produced item 9 at slot 9

Consumer consumed item 6 from slot 6

Producer produced item 10 at slot 0

Producer produced item 11 at slot 1

Producer produced item 12 at slot 2

Producer produced item 13 at slot 3

Producer produced item 14 at slot 4

Consumer consumed item 7 from slot 7

Producer produced item 15 at slot 5

Consumer consumed item 8 from slot 8

Consumer consumed item 9 from slot 9

Producer produced item 16 at slot 6

Producer produced item 17 at slot 7

Consumer consumed item 10 from slot 0

Producer produced item 18 at slot 8

Consumer consumed item 11 from slot 1

Producer produced item 19 at slot 9

Consumer consumed item 12 from slot 2

Consumer consumed item 13 from slot 3

Consumer consumed item 14 from slot 4


Consumer consumed item 15 from slot 5

Consumer consumed item 16 from slot 6

Consumer consumed item 17 from slot 7

Consumer consumed item 18 from slot 8

Consumer consumed item 19 from slot 9

4.1 Implement the following memory allocation methods for fixed partition
a) First fit b) Worst fit c) Best fit

(a) FIRST FIT


public class FirstFitMemoryAllocation {

/*

* Implements the First Fit memory allocation algorithm.

* blockSize Array of fixed memory block sizes.

* m The number of memory blocks.

* processSize Array of process sizes.

* n The number of processes.

*/

public static void implementFirstFit(int[] blockSize, int m, int[] processSize,


int n) {

int[] allocation = new int[n]; // Array to store the block index allocated to a
process

for (int i = 0; i < n; i++) { // Iterate through each process

for (int j = 0; j < m; j++) { // Find the first sufficient block

if (blockSize[j] >= processSize[i]) {

allocation[i] = j; // Allocate block j to process i

blockSize[j] -= processSize[i]; // Reduce available memory in the


block

break; // Move to the next process

[Link]("\nProcess No.\tProcess Size\tBlock no.");

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

[Link](" " + (i + 1) + "\t\t" + processSize[i] + "\t\t");

if (allocation[i] != -1) {
[Link](allocation[i] + 1);

} else {

[Link]("Not Allocated");

public static void main(String[] args) {

int[] blockSize = {100, 500, 200, 300, 600}; // Example memory block sizes

int[] processSize = {212, 417, 112, 426}; // Example process sizes

int m = [Link];

int n = [Link];

implementFirstFit(blockSize, m, processSize, n);

OUTPUT:

Process [Link] Size Block no.

1 212 2

2 417 5

3 112 2

4 426 1

(b) Worst fit

// Java implementation of worst - Fit algorithm


public class GFG

// Method to allocate memory to blocks as per worst fit

// algorithm

static void worstFit(int blockSize[], int m, int processSize[],

int n)

// Stores block id of the block allocated to a

// process

int allocation[] = new int[n];

// Initially no block is assigned to any process

for (int i = 0; i < [Link]; i++)

allocation[i] = -1;

// pick each process and find suitable blocks

// according to its size ad assign to it

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

// Find the best fit block for current process

int wstIdx = -1;

for (int j=0; j<m; j++)

if (blockSize[j] >= processSize[i])

if (wstIdx == -1)

wstIdx = j;
else if (blockSize[wstIdx] < blockSize[j])

wstIdx = j;

// If we could find a block for current process

if (wstIdx != -1)

// allocate block j to p[i] process

allocation[i] = wstIdx;

// Reduce available memory in this block.

blockSize[wstIdx] -= processSize[i];

[Link]("\nProcess No.\tProcess Size\tBlock no.");

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

[Link](" " + (i+1) + "\t\t" + processSize[i] + "\t\t");

if (allocation[i] != -1)

[Link](allocation[i] + 1);

else

[Link]("Not Allocated");

[Link]();

}
// Driver Method

public static void main(String[] args)

int blockSize[] = {100, 500, 200, 300, 600};

int processSize[] = {212, 417, 112, 426};

int m = [Link];

int n = [Link];

worstFit(blockSize, m, processSize, n);

OUTPUT:

Process No. Process Size Block no.

1 212 5

2 417 2

3 112 5

4 426 Not Allocated

( C ) BEST FIT

import [Link];

public class BestFitFixedPartition {

/**
* Allocates processes to memory blocks using the Best Fit algorithm in a fixed
partitioning scheme.
*
* @param blockSize Array of sizes of memory blocks. This array will be
modified to reflect remaining free space.
* @param processSize Array of sizes of processes that need to be allocated
memory.
*/
public static void bestFit(int[] blockSize, int[] processSize) {
int m = [Link];
int n = [Link];

// Array to store the block ID allocated to a process


// (allocation[i] = j means process i is allocated to block j)
int[] allocation = new int[n];

// Initially, set all processes to not allocated (-1)


[Link](allocation, -1);

// Traverse all processes


for (int i = 0; i < n; i++) {
// Find the best fit block for the current process
int bestIdx = -1;
for (int j = 0; j < m; j++) {
if (blockSize[j] >= processSize[i]) {
if (bestIdx == -1 || blockSize[j] < blockSize[bestIdx]) {
bestIdx = j;
}
}
}

// If a suitable block was found


if (bestIdx != -1) {
// Allocate the block to the process
allocation[i] = bestIdx;

// Reduce available memory in that block


blockSize[bestIdx] -= processSize[i];
}
}

[Link]("\nProcess No. Process Size Block No.");


for (int i = 0; i < n; i++) {
[Link](" " + (i + 1) + " " + processSize[i] + " ");
if (allocation[i] != -1) {
[Link](allocation[i] + 1);
} else {
[Link]("Not Allocated");
}
[Link]();
}
}

// Driver Method
public static void main(String[] args) {
// Example memory blocks (fixed partitions)
int[] blockSize = {100, 500, 200, 300, 600};

// Example processes with their required sizes


int[] processSize = {212, 417, 112, 426};

[Link]("Initial Memory Blocks: " +


[Link](blockSize));
[Link]("Processes to Allocate: " +
[Link](processSize));

bestFit(blockSize, processSize);

[Link]("\nRemaining Block Sizes: " +


[Link](blockSize));
}
}
OUTPUT:
Initial Memory Blocks: [100, 500, 200, 300, 600]
Processes to Allocate: [212, 417, 112, 426]

Process No. Process Size Block No.


1 212 4
2 417 2
3 112 3
4 426 5

Remaining Block Sizes: [100, 83, 88, 88, 174]

4(b) Simulate the following page replacement algorithms


a) FIFO b) LRU c) LFU

(a)FIFO
// Java implementation of FIFO page replacement
// in Operating Systems.

import [Link];
import [Link];
import [Link];

class Test
{
// Method to find page faults using FIFO
static int pageFaults(int pages[], int n, int capacity)
{
// To represent set of current pages. We use
// an unordered_set so that we quickly check
// if a page is present in set or not
HashSet<Integer> s = new HashSet<>(capacity);

// To store the pages in FIFO manner


Queue<Integer> indexes = new LinkedList<>() ;

// Start from initial page


int page_faults = 0;
for (int i=0; i<n; i++)
{
// Check if the set can hold more pages
if ([Link]() < capacity)
{
// Insert it into set if not present
// already which represents page fault
if (![Link](pages[i]))
{
[Link](pages[i]);
// increment page fault
page_faults++;

// Push the current page into the queue


[Link](pages[i]);
}
}

// If the set is full then need to perform FIFO


// i.e. remove the first page of the queue from
// set and queue both and insert the current page
else
{
// Check if current page is not already
// present in the set
if (![Link](pages[i]))
{
//Pop the first page from the queue
int val = [Link]();

[Link]();

// Remove the indexes page


[Link](val);

// insert the current page


[Link](pages[i]);

// push the current page into


// the queue
[Link](pages[i]);

// Increment page faults


page_faults++;
}
}
}

return page_faults;
}

// Driver method
public static void main(String args[])
{
int pages[] = {7, 0, 1, 2, 0, 3, 0, 4,
2, 3, 0, 3, 2};

int capacity = 4;
[Link](pageFaults(pages, [Link], capacity));
}
}
OUTPUT: 7

(b) LRU
// Java implementation of above algorithm
import [Link];
import [Link];
import [Link];

class Test
{
// Method to find page faults using indexes
static int pageFaults(int pages[], int n, int capacity)
{
// To represent set of current pages. We use
// an unordered_set so that we quickly check
// if a page is present in set or not
HashSet<Integer> s = new HashSet<>(capacity);

// To store least recently used indexes


// of pages.
HashMap<Integer, Integer> indexes = new HashMap<>();

// Start from initial page


int page_faults = 0;
for (int i=0; i<n; i++)
{
// Check if the set can hold more pages
if ([Link]() < capacity)
{
// Insert it into set if not present
// already which represents page fault
if (![Link](pages[i]))
{
[Link](pages[i]);

// increment page fault


page_faults++;
}

// Store the recently used index of


// each page
[Link](pages[i], i);
}
// If the set is full then need to perform lru
// i.e. remove the least recently used page
// and insert the current page
else
{
// Check if current page is not already
// present in the set
if (![Link](pages[i]))
{
// Find the least recently used pages
// that is present in the set
int lru = Integer.MAX_VALUE, val=Integer.MIN_VALUE;

Iterator<Integer> itr = [Link]();

while ([Link]()) {
int temp = [Link]();
if ([Link](temp) < lru)
{
lru = [Link](temp);
val = temp;
}
}

// Remove the indexes page


[Link](val);
//remove lru from hashmap
[Link](val);
// insert the current page
[Link](pages[i]);

// Increment page faults


page_faults++;
}

// Update the current page index


[Link](pages[i], i);
}
}

return page_faults;
}

// Driver method
public static void main(String args[])
{
int pages[] = {7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2};

int capacity = 4;

[Link](pageFaults(pages, [Link], capacity));


}
}
OUTPUT: 6

( C ) LFU
import [Link].*;

public class LFUPageFaults {


/* Counts no. of page faults */
static int pageFaults(int n, int c, int[] pages)
{
// Initialise count to 0
int count = 0;

// To store elements in memory of size c


List<Integer> v = new ArrayList<Integer>();
// To store frequency of pages
Map<Integer, Integer> mp
= new HashMap<Integer, Integer>();

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


// Find if element is present in memory or not
int idx = [Link](pages[i]);

// If element is not present


if (idx == -1) {
// If memory is full
if ([Link]() == c) {
// Decrease the frequency
int leastFreqPage = [Link](0);
[Link](leastFreqPage,
[Link](leastFreqPage) - 1);

// Remove the first element as


// It is least frequently used
[Link](0);
}

// Add the element at the end of memory


[Link](pages[i]);
// Increase its frequency
[Link](pages[i],
[Link](pages[i], 0) + 1);

// Increment the count


count++;
}
else {
// If element is present
// Remove the element
// And add it at the end
// Increase its frequency
int page = [Link](idx);
[Link](page);
[Link](page, [Link](page) + 1);
}

// Compare frequency with other pages


// starting from the 2nd last page
int k = [Link]() - 2;

// Sort the pages based on their frequency


// And time at which they arrive
// if frequency is same
// then, the page arriving first must be placed
// first
while (k >= 0
&& [Link]([Link](k))
> [Link]([Link](k + 1))) {
[Link](v, k, k + 1);
k--;
}
}

// Return total page faults


return count;
}

/* Driver program to test pageFaults function*/


public static void main(String[] args)
{
int[] pages = { 1, 2, 3, 4, 2, 1, 5 };
int n = 7, c = 3;

[Link]("Page Faults = "


+ pageFaults(n, c, pages));
[Link]("Page Hits = "
+ (n - pageFaults(n, c, pages)));
}
}

OUTPUT:
Page Faults = 6
Page Hits = 1

4(c) Simulate Paging Technique of memory management

import [Link].*;

public class PagingSimulation {


// Define constants for memory sizes
final int MEMORY_SIZE = 256; // Physical memory size in bytes
final int PAGE_SIZE = 32; // Page/Frame size in bytes
final int NUM_FRAMES = MEMORY_SIZE / PAGE_SIZE; // Number of
physical frames (8)
final int NUM_PAGES = 16; // Number of logical pages (for a conceptual
process)

// Data structures
int[] physicalMemory; // Represents physical memory frames
int[] pageTable; // Maps logical pages to physical frames
boolean[] frameStatus; // Tracks availability of physical frames

public PagingSimulation() {
physicalMemory = new int[MEMORY_SIZE];
pageTable = new int[NUM_PAGES];
frameStatus = new boolean[NUM_FRAMES];
[Link](pageTable, -1); // Initialize page table: -1 indicates not loaded
[Link](frameStatus, false); // All frames are initially free
}

// Load a page into an available frame


public void loadPage(int pageNum, int frameNum) {
if (pageNum >= 0 && pageNum < NUM_PAGES && frameNum >= 0 &&
frameNum < NUM_FRAMES) {
pageTable[pageNum] = frameNum;
frameStatus[frameNum] = true;
[Link]("Page " + pageNum + " loaded into Frame " + frameNum);
} else {
[Link]("Invalid page or frame number.");
}
}

// Translate a logical address to a physical address


public int translateAddress(int logicalAddress) {
// A logical address consists of a page number and an offset
int pageNum = logicalAddress / PAGE_SIZE; // Page number
int offset = logicalAddress % PAGE_SIZE; // Offset within the page

if (pageNum >= 0 && pageNum < NUM_PAGES) {


int frameNum = pageTable[pageNum];

if (frameNum != -1) {
// Address translation: Physical Address = (Frame Number * Page Size) +
Offset
int physicalAddress = (frameNum * PAGE_SIZE) + offset;
return physicalAddress;
} else {
[Link]("Page Fault: Page " + pageNum + " not in memory.");
// In a real OS, a page fault handler would load the page from secondary
storage
return -1; // Indicate page fault
}
} else {
[Link]("Invalid logical address.");
return -1;
}
}

// Helper method to find the first available frame (simple allocation)


public int findAvailableFrame() {
for (int i = 0; i < NUM_FRAMES; i++) {
if (!frameStatus[i]) {
return i;
}
}
return -1; // No free frames
}

public static void main(String[] args) {


PagingSimulation simulator = new PagingSimulation();
Scanner in = new Scanner([Link]);

// Simulate loading a few pages


int frame1 = [Link]();
if (frame1 != -1) [Link](0, frame1);
int frame2 = [Link]();
if (frame2 != -1) [Link](1, frame2);
int frame3 = [Link]();
if (frame3 != -1) [Link](2, frame3);

// User interaction for address translation


while (true) {
[Link]("\nEnter a Logical Address to translate (or a negative
number to exit):");
int logicalAddr = [Link]();

if (logicalAddr < 0) break;

int physicalAddr = [Link](logicalAddr);


if (physicalAddr != -1) {
[Link]("Logical Address " + logicalAddr + " translates to
Physical Address " + physicalAddr);
}
}
[Link]();
}
}

OUTPUT:

Page 0 loaded into Frame 0


Page 1 loaded into Frame 1
Page 2 loaded into Frame 2

Enter a Logical Address to translate (or a negative number to exit):


1000
Invalid logical address.

Enter a Logical Address to translate (or a negative number to exit):


1
Logical Address 1 translates to Physical Address 1

Enter a Logical Address to translate (or a negative number to exit):


3
Logical Address 3 translates to Physical Address 3

Enter a Logical Address to translate (or a negative number to exit):


0
Logical Address 0 translates to Physical Address 0
Enter a Logical Address to translate (or a negative number to exit):
-1

You might also like