0% found this document useful (0 votes)
11 views

OS_LAB file

Operating System Lab Amrit Campus

Uploaded by

tikapoudel798
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

OS_LAB file

Operating System Lab Amrit Campus

Uploaded by

tikapoudel798
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 55

Experiment No.

1
Study of basic Commands in Linux Operating System.

Theory
Linux is a powerful, open-source operating system kernel that forms the foundation for a wide variety of
operating systems, known as distributions (distros). Initially developed by Linus Torvalds in 1991, Linux
is celebrated for its stability, security, and flexibility. It supports a range of hardware platforms and is
commonly used in servers, desktops, and embedded systems.
Some of the basic commands in Linux OS are as:
1. File and Directory Management
• ls- List files and directories in the current directory.

• cd- Change directory.

• pwd – Print working directory; shows the current directory path.

• mkdir – Make a new directory.

• rmdir – Remove an empty directory.

2. System Information and Monitoring


• df – Display disk space usage.
• du – Show disk usage for files and directories.

• top – Display running processes and system resource usage.

• uname – Display system information.

• free – Display memory usage.

3. Package Management
• sudo apt update – Update the package list.
• sudo apt upgrade – Upgrade all installed packages.

• sudo apt install – Install a new package.

• sudo apt remove – Remove an installed package.

4. Networking Commands
• ifconfig – View network interface configurations.

• ping – Test network connection to another machine.


5. Managing Processes
• ps – View currently running processes.

• kill – Terminate a process.

6. System Shutdown and Reboot


• shutdown – Shutdown the system.

• reboot – Reboot the system.


Experiment No.2
Write a program to implementation of Thread and Process.
Thread:
Source code:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void* threadFunction(void* arg) {


printf("Thread is running...\n");
sleep(1); // Simulate work
printf("Thread has finished execution.\n");
return NULL;
}

int main() {
pthread_t thread;
printf("Creating a thread...\n");

// Create a new thread


pthread_create(&thread, NULL, threadFunction, NULL);

// Wait for the thread to finish


pthread_join(thread, NULL);

printf("Thread has been joined.\n");


return 0;
}

Output:

Process :

Source code:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
pid_t pid = fork();

if (pid == 0) {
// Child process
printf("Child process (PID: %d) is running...\n", getpid());
sleep(1); // Simulate work
printf("Child process finished.\n");
} else if (pid > 0) {
// Parent process
printf("Parent process (PID: %d) is waiting for child to finish...\n", getpid());
wait(NULL); // Wait for the child process to finish
printf("Parent process finished.\n");
} else {
// Fork failed
printf("Fork failed.\n");
}

return 0;
}

Output :

Conclusion:
Hence, using threads and processes efficiently is crucial for optimizing program performance and
ensuring responsiveness in applications.
Experiment No.3
Write a C program to implementation of producer-consumer problem using Semaphores.
Source code:
#include <stdlib.h>
int mutex = 1, full = 0, empty = 10, data = 0;
void producer()
{
--mutex;
++full;
--empty;
data++;
printf("\nProducer produces item number: %d\n", data);
++mutex;
}
void consumer()
{
--mutex;
--full;
++empty;
printf("\nConsumer consumes item number: %d.\n", data);
data--;
++mutex;
}
int main()
{
int n, i;
printf("IMPLEMENTATION OF PRODUCER-CONSUMER PROBLEM\n");
printf("\n1. Enter 1 for Producer \n2. Enter 2 for Consumer \n3. Enter 3 to Exit");
for (i = 1; i > 0; i++)
{
printf("\nEnter your choice: ");
scanf("%d", &n);
switch (n)
{
case 1:
if ((mutex == 1) && (empty != 0))
producer();
else
printf("The Buffer is full! Producer cannot produce!");
break;
case 2:
if ((mutex == 1) && (full != 0))
consumer();
else
printf("The Buffer is empty! Consumer cannot consume!");
break;
case 3:
printf("Exiting program.\n");
exit(0);
break;
}
}
}
Output :

Conclusion:
The above C-program for the implementation of Producer-Consumer problem demonstrates the
importance of synchronization in a multi-threaded environment to ensure correct and efficient
execution.
Experiment No.4

Write a C program to simulate the concept of Dining Philosophers problem.


Source code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

#define N 3 // Number of philosophers


#define THINKING 0
#define HUNGRY 1
#define EATING 2
#define LEFT (ph_num + N - 1) % N
#define RIGHT (ph_num + 1) % N
#define MAX_CYCLES 2 // Number of eating cycles

int state[N], phil_num[N] = {0, 1, 2};


sem_t mutex;
sem_t S[N];

void test(int ph_num);


void take_fork(int ph_num);
void put_fork(int ph_num);
void *philosopher(void *num);

int main()
{
printf("Megh Raj Rasailee \nSIMULATION OF DINING-PHILOSOPHERS PROBLEM\n\n");

pthread_t thread_id[N];

// Initialize the semaphores


sem_init(&mutex, 0, 1); // Semaphore for critical section

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


{
sem_init(&S[i], 0, 0); // Initialize each philosopher semaphore
}

// Create philosopher threads


for (int i = 0; i < N; i++)
{
pthread_create(&thread_id[i], NULL, philosopher, &phil_num[i]);
}

// Join philosopher threads (wait for completion)


for (int i = 0; i < N; i++)
{
pthread_join(thread_id[i], NULL);
}

return 0;
}

void *philosopher(void *num)


{
int *ph_num = (int *)num;
int cycle = 0;

while (cycle < MAX_CYCLES)


{
printf("Philosopher %d is thinking.\n", *ph_num + 1);
sleep(1); // Simulate thinking
take_fork(*ph_num);
printf("Philosopher %d is eating.\n", *ph_num + 1);
sleep(1); // Simulate eating
put_fork(*ph_num);
cycle++;
printf("Philosopher %d is putting down forks and is now thinking.\n", *ph_num + 1);
}

printf("Philosopher %d has finished after %d cycles.\n", *ph_num + 1, MAX_CYCLES);


return NULL;
}

void take_fork(int ph_num)


{
sem_wait(&mutex); // Enter critical section
state[ph_num] = HUNGRY;
printf("Philosopher %d is hungry.\n", ph_num + 1);
test(ph_num); // Try to eat if both neighbors aren't eating
sem_post(&mutex); // Exit critical section
sem_wait(&S[ph_num]); // Block if unable to eat
}

void put_fork(int ph_num)


{
sem_wait(&mutex); // Enter critical section
state[ph_num] = THINKING;
test(LEFT); // Check if left neighbor can eat
test(RIGHT); // Check if right neighbor can eat
sem_post(&mutex); // Exit critical section
}

void test(int ph_num)


{
if (state[ph_num] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING)
{
state[ph_num] = EATING;
sem_post(&S[ph_num]); // Let philosopher eat
}
}
Output:

Conclusion :
The Dining-philosophers problem illustrates the importance of proper synchronization in a concurrent
system to avoid deadlock and ensure that all processes (philosophers) have a fair chance to access
shared resources (forks).
Experiment No.5
Write a C program to simulate the following non-preemptive CPU scheduling algorithms to find
turnaround time and waiting time.
a) FCFS b) SJF c) Priority

a)FCFS( First Come First Serve)


Algorithm:
Step 1: Start the process
Step 2: Accept the number of processes in the ready Queue.
Step 3: For each process in the ready Queue, assign the process name and the burst time.
Step 4: Set the waiting of the first process as 0 and its burst time as its turnaround time.
Step 5: For each process in the ready Queue calculate
− Waiting time (n) = waiting time (n-1) + Burst time (n-1)
− Turnaround time (n)= waiting time(n)+Burst time(n)
Step 6: Calculate
− Average waiting time = Total waiting Time / Number of process
− Average Turnaround time=Total Turnaround Time /Number of process
Step 7: Stop the process

Source code:
#include <stdio.h>
void fcfs(int n, int bt[]) {
int wt[n], tat[n], total_wt = 0, total_tat = 0;
wt[0] = 0; // Waiting time for the first process is 0

// Calculate waiting time for each process


for (int i = 1; i < n; i++)
wt[i] = wt[i - 1] + bt[i - 1];

// Calculate turnaround time and accumulate total waiting/turnaround time


for (int i = 0; i < n; i++) {
tat[i] = bt[i] + wt[i];
total_wt += wt[i];
total_tat += tat[i];
}

// Output the results


printf("\nFCFS Scheduling\n");
printf("Process\t\tBurst Time\tWaiting Time\tTurnaround Time\n");
for (int i = 0; i < n; i++)
printf("%d\t\t%d\t\t%d\t\t%d\n", i + 1, bt[i], wt[i], tat[i]);

// Calculate and print average waiting and turnaround time


float avg_wt = (float)total_wt / n;
float avg_tat = (float)total_tat / n;
printf("\nAverage Waiting Time: %.2f\n", avg_wt);
printf("Average Turnaround Time: %.2f\n", avg_tat);
}

int main() {
printf("Megh Raj Rasailee\n\n");
int n;
printf("Enter the number of processes: ");
scanf("%d", &n);
int bt[n];
printf("Enter burst times:\n");
for (int i = 0; i < n; i++) {
printf("Process %d: ", i + 1);
scanf("%d", &bt[i]);
}

fcfs(n, bt);

return 0;
}
Output:

b) SJF(Shortest Job First )


Algorithm:
Step 1: Start the process
Step 2: Accept the number of processes in the ready Queue
Step 3: For each process in the ready Queue, assign the process id and accept the CPU burst time
Step 4: Start the ready Queue according the shortest Burst time by sorting according to lowest to
highest burst time.
Step 5: Set the waiting time of the first process as 0 and its turnaround time as its Burst time.
Step 6: Sort the processes names based on their Burst time
Step 7: For each process in the ready queue, calculate
− Waiting time(n)= waiting time (n-1) + Burst time (n-1)
− Turnaround time (n)= waiting time(n)+Burst time(n)
Step 8: Calculate
− Average waiting time = Total waiting Time / Number of process
− Average Turnaround time = Total Turnaround Time / Number of process
Step 9: Stop the process

Source code:
#include <stdio.h>
void sjf(int n, int bt[])
{
int wt[n], tat[n], temp, pos;
int total_wt = 0, total_tat = 0;
for (int i = 0; i < n; i++)
{
pos = i;
for (int j = i + 1; j < n; j++)
{
if (bt[j] < bt[pos])
pos = j;
}
temp = bt[i];
bt[i] = bt[pos];
bt[pos] = temp;
}
wt[0] = 0;
for (int i = 1; i < n; i++)
wt[i] = wt[i - 1] + bt[i - 1];
for (int i = 0; i < n; i++)
{
tat[i] = bt[i] + wt[i];
total_wt += wt[i];
total_tat += tat[i];
}
printf("\nSJF Scheduling\n");
printf("Process\t\tBurst Time\tWaiting Time\tTurnaround Time\n");
for (int i = 0; i < n; i++)
printf("%d\t\t%d\t\t%d\t\t%d\n", i + 1, bt[i], wt[i], tat[i]);
float avg_wt = (float)total_wt / n;
float avg_tat = (float)total_tat / n;
printf("\nAverage Waiting Time: %.2f\n", avg_wt);
printf("Average Turnaround Time: %.2f\n", avg_tat);
}
int main()
{
printf("Megh Raj Rasailee\n");
int n;
printf("Enter the number of processes: ");
scanf("%d", &n);
int bt[n];
printf("Enter burst times:\n");
for (int i = 0; i < n; i++)
{
printf("Process %d: ", i + 1);
scanf("%d", &bt[i]);
}
sjf(n, bt);
return 0;
}
Output:

c) Priority
Algorithm:
Step 1: Start the process
Step 2: Accept the number of processes in the ready Queue.
Step 3: For each process in the ready Queue, assign the process id and accept the CPU burst time.
Step 4: Sort the ready Queue according to the priority number.
Step 5: Set the waiting of the first process as 0 and its burst time as its turnaround time.
Step 6: Arrange the processes based on process priority.
Step 7: For each process in the ready Queue calculate
− Waiting time(n) = waiting time (n-1) + Burst time (n-1)
− Turnaround time (n) = waiting time(n) + Burst time(n)
Step 8: Calculate
− Average waiting time = Total waiting Time / Number of process
− Average Turnaround time = Total Turnaround Time / Number of process
Step 9: Stop the process

Source code:
#include <stdio.h>
void priority(int n, int bt[], int pr[])
{
int wt[n], tat[n], temp, pos, total_wt = 0, total_tat = 0;
for (int i = 0; i < n; i++)
{
pos = i;
for (int j = i + 1; j < n; j++)
{
if (pr[j] < pr[pos])
pos = j;
}
temp = pr[i];
pr[i] = pr[pos];
pr[pos] = temp;
temp = bt[i];
bt[i] = bt[pos];
bt[pos] = temp;
}
wt[0] = 0;
for (int i = 1; i < n; i++)
wt[i] = wt[i - 1] + bt[i - 1];
for (int i = 0; i < n; i++)
{
tat[i] = bt[i] + wt[i];
total_wt += wt[i];
total_tat += tat[i];
}
printf("\nPriority Scheduling :Non-preemptive\n");
printf("Process\t\tBurst Time\tPriority\tWaiting Time\tTurnaround Time\n");
for (int i = 0; i < n; i++)
printf("%d\t\t%d\t\t%d\t\t%d\t\t%d\n", i + 1, bt[i], pr[i], wt[i], tat[i]);
float avg_wt = (float)total_wt / n;
float avg_tat = (float)total_tat / n;
printf("\nAverage Waiting Time: %.2f\n", avg_wt);
printf("Average Turnaround Time: %.2f\n", avg_tat);
}
int main()
{
printf("Megh Raj Rasailee\n");
int n;
printf("Enter the number of processes: ");
scanf("%d", &n);
int bt[n], pr[n];
printf("Enter burst times and priorities:\n");
for (int i = 0; i < n; i++)
{
printf("Process %d - Burst Time: ", i + 1);
scanf("%d", &bt[i]);
printf("Process %d - Priority: ", i + 1);
scanf("%d", &pr[i]);
}
priority(n, bt, pr);
return 0;
}
Output:

Conclusion:
Hence, he simulation of non-preemptive scheduling algorithms FCFS, SJF, and Priority shows how
different methods affect process management.
Experiment No.6
Write a C program to simulate the following preemptive CPU scheduling algorithms to find turnaround
time and waiting time of Round Robin algorithm.

Algorithm:
Step 1: Start the process
Step 2: Initialize a queue to keep track of processes.
Step 3: Assign the CPU to the first process in the queue and execute process for time quantum.
Step 4: If the process is not finished, move it to the end of the queue with the remaining burst time.
Step 5: Continue until all processes are completed.
Step 6: Calculate
− Average waiting time = Total waiting Time / Number of process
− Average Turnaround time = Total Turnaround Time / Number of process
Source code:
#include <stdio.h>
void roundRobin(int n, int bt[], int quantum)
{
int wt[n], tat[n], rem_bt[n], total_wt = 0, total_tat = 0;
for (int i = 0; i < n; i++)
rem_bt[i] = bt[i];
int t = 0, done;
while (1)
{
done = 1;
for (int i = 0; i < n; i++)
{
if (rem_bt[i] > 0)
{
done = 0;
if (rem_bt[i] > quantum)
{
t += quantum;
rem_bt[i] -= quantum;
}
else
{
t += rem_bt[i];
wt[i] = t - bt[i];
rem_bt[i] = 0;
}
}
}
if (done)
break;
}
for (int i = 0; i < n; i++)
tat[i] = bt[i] + wt[i];
printf("\nRound Robin Scheduling\n");
printf("Process\tBurst Time\tWaiting Time\tTurnaround Time\n");
for (int i = 0; i < n; i++)
{
total_wt += wt[i];
total_tat += tat[i];
printf("%d\t%d\t\t%d\t\t%d\n", i + 1, bt[i], wt[i], tat[i]);
}
printf("\nAverage Waiting Time: %.2f", (float)total_wt / n);
printf("\nAverage Turnaround Time: %.2f\n", (float)total_tat / n);
}
int main()
{
printf("Megh Raj Rasailee\n");
int n, quantum;
printf("Enter the number of processes: ");
scanf("%d", &n);
int bt[n];
printf("Enter burst times:\n");
for (int i = 0; i < n; i++)
{
printf("Process %d: ", i + 1);
scanf("%d", &bt[i]);
}
printf("Enter time quantum: ");
scanf("%d", &quantum);
roundRobin(n, bt, quantum);
return 0;
}

Output:

Conlcusion:
Hence , Round Robin ensures fairness among all processes,while Preemptive Priority scheduling is better
for time-sensitive or prioritized tasks.
Experiment No.7
Write a program to simulate Banker’s Algorithm for Dead Lock Avoidance.

Algorithm:
Step 1: Initialization
− Calculate the Need matrix using Need[i][j] = Max[i][j] - Allocation[i][j].
Step 2: Safety Check
− Initialize Work as Available and set Finish[i] = false for all processes.
− Find an unfinished process i with Need[i] <= Work. If found, update Work = Work +
Allocation[i], mark Finish[i] = true, and repeat until no such process exists.
− If all processes are finished, the system is safe; otherwise, it is unsafe.
Step 3: Resource Request
− Check if Request[i] <= Need[i] and Request[i] <= Available. If not, deny the request.
− Temporarily allocate resources: Available = Available -Request[i], Allocation[i] = Allocation[i]
+ Request[i], and Need[i] = Need[i] - Request[i].
− Perform the Safety Check. If safe, grant the request; otherwise, roll back changes and deny the
request.

Source code:
#include <stdio.h>
int max[100][100], alloc[100][100], need[100][100], avail[100], n, r;
void input()
{
int i, j;
printf("Enter the number of Processes: ");
scanf("%d", &n);
printf("Enter the number of Resources Instances: ");
scanf("%d", &r);
printf("Enter the Max Matrix:\n");
for (i = 0; i < n; i++)
{
for (j = 0; j < r; j++)
scanf("%d", &max[i][j]);
}
printf("Enter the Allocation Matrix:\n");
for (i = 0; i < n; i++)
{
for (j = 0; j < r; j++)
scanf("%d", &alloc[i][j]);
}
printf("Enter the Available Resources:\n");
for (j = 0; j < r; j++)
scanf("%d", &avail[j]);
}
void show()
{
int i, j;
printf("Process\tAllocation\tMax\tAvailable\n");
for (i = 0; i < n; i++)
{
printf("P%d\t", i);
for (j = 0; j < r; j++)
printf("%d ", alloc[i][j]);
printf("\t\t");
for (j = 0; j < r; j++)
printf("%d ", max[i][j]);
printf("\t");
if (i == 0)
{
for (j = 0; j < r; j++)
printf("%d ", avail[j]);
}
printf("\n");
}
}
void cal()
{
int finish[100], safe[100], flag = 1, i, j, k, c1 = 0;
for (i = 0; i < n; i++)
finish[i] = 0;
for (i = 0; i < n; i++)
{
for (j = 0; j < r; j++)
need[i][j] = max[i][j] - alloc[i][j];
}
printf("\n");
while (flag)
{
flag = 0;
for (i = 0; i < n; i++)
{
int can_proceed = 1;
if (finish[i] == 0)
{
for (j = 0; j < r; j++)
{
if (need[i][j] > avail[j])
{
can_proceed = 0;
break;
}
}
if (can_proceed)
{
for (j = 0; j < r; j++)
{
avail[j] += alloc[i][j];
}
finish[i] = 1;
flag = 1;
safe[c1++] = i;
}
}
}
}
printf("\nThe safe sequence is: (");
for (i = 0; i < c1; i++)
printf("P%d ", safe[i]);
printf(")\n");
if (c1 == n)
{
printf("The system is in a safe state.\n");
}
else
{
printf("Processes are in deadlock.\n");
printf("System is in an unsafe state.\n");
}
}
int main()
{
printf("Megh Raj Rasailee\nBANKER'S ALGORITHM FOR DEADLOCK AVOIDANCE\n\n");
input();
show();
cal();
return 0;
}

Output:

Conclusion:
Hence,the above program demonstrates how the Banker's Algorithm can be used as a preventive measure
to maintain system stability and ensure that all processes can complete their execution safely.
Experiment No.8
Write a program to simulate Banker’s Algorithm for Dead Lock Prevention

Algorithm:
Step 1: Initialization
− Calculate the Need matrix using Need[i][j] = Max[i][j] - Allocation[i][j].
Step 2: Safety Check
− Initialize Work as Available and set Finish[i] = false for all processes.
− Find an unfinished process i with Need[i] <= Work. If found, update Work = Work +
Allocation[i], mark Finish[i] = true, and repeat until no such process exists.
− If all processes are finished, the system is safe; otherwise, it is unsafe.
Step 3: Resource Request
− Check if Request[i] <= Need[i] and Request[i] <= Available. If not, deny the request.
− Temporarily allocate resources: Available = Available -Request[i], Allocation[i] = Allocation[i]
+ Request[i], and Need[i] = Need[i] - Request[i].
− Perform the Safety Check. If safe, grant the request; otherwise, roll back changes and deny the
request.

Source code:
#include <stdio.h>
#include <stdbool.h>
#define P 5
#define R 3
bool isSafe(int available[], int max[P][R], int allocation[P][R])
{
int need[P][R];
int finish[P] = {0};
int safeSeq[P];
int work[R];
for (int i = 0; i < R; i++)
work[i] = available[i];
for (int i = 0; i < P; i++)
{
for (int j = 0; j < R; j++)
need[i][j] = max[i][j] - allocation[i][j];
}
int count = 0;
while (count < P)
{
bool found = false;
for (int i = 0; i < P; i++)
{
if (finish[i] == 0)
{
bool canAllocate = true;
for (int j = 0; j < R; j++)
{
if (need[i][j] > work[j])
{
canAllocate = false;
break;
}
}
if (canAllocate)
{
for (int j = 0; j < R; j++)
{
work[j] += allocation[i][j];
}
safeSeq[count++] = i;
finish[i] = 1;
found = true;
}
}
}
if (!found)
{
printf("System is not in a safe state.\n");
return false;
}
}
printf("System is in a safe state.\nSafe Sequence is: ");
for (int i = 0; i < P; i++)
printf("P%d ", safeSeq[i]);
printf("\n");
return true;
}
int main()
{
printf("Megh Raj Rasailee\nBANKER'S ALGORITHM FOR DEADLOCK PREVENTION\n\n");
int available[R];
int max[P][R];
int allocation[P][R];
printf("Enter the available resources (R1, R2, ...):\n");
for (int i = 0; i < R; i++)
scanf("%d", &available[i]);
printf("Enter the maximum resources matrix (for each process and resource):\n");
for (int i = 0; i < P; i++)
{
printf("Process %d: ", i);
for (int j = 0; j < R; j++)
scanf("%d", &max[i][j]);
}
printf("Enter the allocation matrix (for each process and resource):\n");
for (int i = 0; i < P; i++)
{
printf("Process %d: ", i);
for (int j = 0; j < R; j++)
scanf("%d", &allocation[i][j]);
}
isSafe(available, max, allocation);
return 0;
}
Output:

Conclusion:
Hence, this approach helps maintain system stability and avoids potential deadlocks by preventing unsafe
resource allocations.
Experiment No.9
Write a program to simulate the MVT and MFT memory management techniques.

Source code:
//MVT Memory management technique
#include <stdio.h>
int main()
{
printf("Megh Raj Rasailee\nMVT MEMORY MANAGEMENT TECHNIQUE\n");
int ms, mp[10], i, temp, n = 0;
char ch = 'Y';
printf("Enter the total memory available (in Bytes): ");
scanf("%d", &ms);
temp = ms;
for (i = 0; ch == 'Y'; i++, n++)
{
printf("\nEnter memory required for process %d (in Bytes): ", i + 1);
scanf("%d", &mp[i]);
if (mp[i] <= temp)
{
printf("Memory is allocated for Process %d.", i + 1);
temp = temp - mp[i];
}
else
{
printf("Memory is Full.");
break;
}
printf("\nDo you want to continue (Y/N): ");
scanf(" %c", &ch);
}
printf("\nTotal Memory Available: %d", ms);
printf("\n\tPROCESS\t MEMORY ALLOCATED ");
for (i = 0; i < n; i++)
printf("\n \t%d\t\t%d", i + 1, mp[i]);
printf("\nTotal Memory Allocated: %d", ms - temp);
printf("\nTotal External Fragmentation: %d", temp);
return 0;
}

//MFT Memory management technique


#include <stdio.h>

int main() {
printf("Megh Raj Rasailee\n");
printf("MFT MEMORY MANAGEMENT TECHNIQUE\n");
int ms, bs, nob, ef, n;
int mp[10], tif = 0;
int i, p = 0;
printf("Enter the total memory available (in Bytes): ");
scanf("%d", &ms);
printf("Enter the block size (in Bytes): ");
scanf("%d", &bs);
nob = ms / bs;
ef = ms - (nob * bs);
printf("\nEnter the number of processes: ");
scanf("%d", &n);
for (i = 0; i < n; i++) {
printf("Enter memory required for process %d (in Bytes): ", i + 1);
scanf("%d", &mp[i]);
}
printf("\nNo. of Blocks available in memory: %d", nob);
printf("\nPROCESS\t MEMORY REQ.\t ALLOCATED\tINTERNAL FRAGMENTATION");
for (i = 0; i < n && p < nob; i++) {
printf("\n %d\t\t%d", i + 1, mp[i]);
if (mp[i] > bs) {
printf("\t\tNO\t---");
} else {
printf("\t\tYES\t%d", bs - mp[i]);
tif += (bs - mp[i]);
p++;
}
}
if (i < n) {
printf("\nMemory is Full, Remaining Processes cannot be accommodated.");
}
printf("\nTotal Internal Fragmentation = %d", tif);
printf("\nTotal External Fragmentation = %d\n", ef);
return 0;
}
Output:

Conclusion:
MFT is simpler and more predictable but less efficient in handling varying process sizes. MVT offers
better utilization of memory but requires more complex management to handle fragmentation.
Experiment No.10
Write a program to simulate paging technique of memory management.

Source code:
#include <stdio.h>
int main()
{
printf("Megh Raj Rasailee\nPAGING TECHNIQUE\n");
int ms, ps, nop, np, rempages, i, j, x, y, pa, offset;
int s[10], fno[10][20];
printf("\nEnter the memory size (in Bytes): ");
scanf("%d", &ms);
printf("Enter the page size (in Bytes): ");
scanf("%d", &ps);
nop = ms / ps;
printf("The number of pages available in memory are: %d ", nop);
printf("\nEnter the number of processes: ");
scanf("%d", &np);
rempages = nop;
for (i = 1; i <= np; i++)
{
printf("\nEnter the number of pages required for process %d: ", i);
scanf("%d", &s[i]);
if (s[i] > rempages)
{
printf("\nMemory is full. Cannot allocate more pages.");
break;
}
rempages = rempages - s[i];
printf("Enter the page table for process %d(page numbers): ", i);
for (j = 0; j < s[i]; j++)
scanf("%d", &fno[i][j]);
}
printf("\nEnter logical address to find Physical Address ");
printf("\nEnter process number, page number and offset: ");
scanf("%d %d %d", &x, &y, &offset);
if (x > np || y >= s[i] || offset >= ps)
printf("\nInvalid process number or page number or offset.");
else
{
pa = fno[x][y] * ps + offset;
printf("The physical address is: %d", pa);
}
return 0;
}
Output:

Conclusion:
Hence, the above C-program demonstrated that paging efficiently manages memory by dividing it into
fixed-size pages and frames.
Experiment No.11
Write a C program to simulate the FIRST-FIT contiguous memory allocation technique.

Source code:
#include <stdio.h>
#define MAX_BLOCKS 25
#define MAX_PROCESSES 25
int main()
{
printf("Megh Raj Rasailee\nMEMORY MANAGEMENT SCHEME- FIRST FIT\n\n");
int i, j, blockno, blocksize[MAX_BLOCKS];
int processno, processsize[MAX_PROCESSES];
int allocatedBlock[MAX_PROCESSES];
printf("Enter the number of memory blocks: ");
scanf("%d", &blockno);
printf("Enter the sizes of each memory blocks:-\n");
for (i = 0; i < blockno; i++)
{
printf("Block %d: ", i + 1);
scanf("%d", &blocksize[i]);
}
printf("Enter the number of processes: ");
scanf("%d", &processno);
printf("Enter the sizes of each processes:-\n");
for (i = 0; i < processno; i++)
{
printf("Process %d: ", i + 1);
scanf("%d", &processsize[i]);
allocatedBlock[i] = -1;
}
printf("\nProcess_no:\tProcess_size:\tBlock_no:\tFragment in Block:\n");
for (i = 0; i < processno; i++)
{
int allocated = 0;
for (j = 0; j < blockno; j++)
{
if (processsize[i] <= blocksize[j])
{
allocatedBlock[i] = j;
printf("%d\t\t%d\t\t%d\t\t%d\n", i + 1, processsize[i], j + 1, blocksize[j] - processsize[i]);
blocksize[j] -= processsize[i];
allocated = 1;
break;
}
}
if (!allocated)
{
printf("%d\t\t%d\t\tNot Allocated\t---\n", i + 1, processsize[i]);
}
}
return 0;
}
Ouput:
Conclusion:
Hence, First-Fit contiguous memory allocation technique is effective for quick allocation but may suffer
from fragmentation over time, potentially causing inefficient memory usage.
Experiment No.12
Write a C program to simulate the BEST-FIT contiguous memory allocation technique.

Source code:
#include <stdio.h>
#define MAX_BLOCKS 25
#define MAX_PROCESSES 25
int main()
{
printf("Megh Raj Rasailee\nMEMORY MANAGEMENT SCHEME- BEST FIT\n\n");
int i, j, blockno, blocksize[MAX_BLOCKS];
int processno, processsize[MAX_PROCESSES];
int allocatedBlock[MAX_PROCESSES];
printf("Enter the number of memory blocks: ");
scanf("%d", &blockno);
printf("Enter the sizes of each memory block:\n");
for (i = 0; i < blockno; i++)
{
printf("Block %d: ", i + 1);
scanf("%d", &blocksize[i]);
}
printf("Enter the number of processes: ");
scanf("%d", &processno);
printf("Enter the sizes of each process:\n");
for (i = 0; i < processno; i++)
{
printf("Process %d: ", i + 1);
scanf("%d", &processsize[i]);
allocatedBlock[i] = -1;
}
printf("\nProcess_no:\tProcess_size:\tBlock_no:\tFragment in Block:\n");
for (i = 0; i < processno; i++)
{
int bestFitIndex = -1;
int minFragment = 999999;
for (j = 0; j < blockno; j++)
{
if (processsize[i] <= blocksize[j] && blocksize[j] - processsize[i] < minFragment)
{
minFragment = blocksize[j] - processsize[i];
bestFitIndex = j;
}
}
if (bestFitIndex != -1)
{
allocatedBlock[i] = bestFitIndex;
printf("%d\t\t%d\t\t%d\t\t%d\n", i + 1, processsize[i], bestFitIndex + 1, minFragment);
blocksize[bestFitIndex] -= processsize[i];
}
else
{
printf("%d\t\t%d\t\tNot Allocated\t---\n", i + 1, processsize[i]);
}
}
return 0;
}

Output:

Conclusion:
Hence, in the Best-Fit memory allocation technique, the program finds the most optimal block to
minimize wasted space.
Experiment No.13
Write a C program to simulate the WORST-FIT contiguous memory allocation technique.

Source code:
#include <stdio.h>
#define MAX_BLOCKS 25
#define MAX_PROCESSES 25
int main()
{
printf("Megh Raj Rasailee\nMEMORY MANAGEMENT SCHEME - WORST FIT\n\n");
int i, j, blockno, blocksize[MAX_BLOCKS];
int processno, processsize[MAX_PROCESSES];
int allocatedBlock[MAX_PROCESSES];
printf("Enter the number of memory blocks: ");
scanf("%d", &blockno);
printf("Enter the sizes of each memory block:\n");
for (i = 0; i < blockno; i++)
{
printf("Block %d: ", i + 1);
scanf("%d", &blocksize[i]);
}
printf("Enter the number of processes: ");
scanf("%d", &processno);
printf("Enter the sizes of each process:\n");
for (i = 0; i < processno; i++)
{
printf("Process %d: ", i + 1);
scanf("%d", &processsize[i]);
allocatedBlock[i] = -1;
}
printf("\nProcess_no:\tProcess_size:\tBlock_no:\tFragment in Block:\n");
for (i = 0; i < processno; i++)
{
int worstFitIndex = -1;
int maxFragment = -1;
for (j = 0; j < blockno; j++)
{
if (processsize[i] <= blocksize[j] && blocksize[j] - processsize[i] > maxFragment)
{
maxFragment = blocksize[j] - processsize[i];
worstFitIndex = j;
}
}
if (worstFitIndex != -1){
allocatedBlock[i] = worstFitIndex;
printf("%d\t\t%d\t\t%d\t\t%d\n", i + 1, processsize[i], worstFitIndex + 1, maxFragment);
blocksize[worstFitIndex] -= processsize[i];
}
else{
printf("%d\t\t%d\t\tNot Allocated\t---\n", i + 1, processsize[i]);
}
}
return 0;
}
Output:

Conclusion:
The Worst-Fit technique prioritizes leaving large free memory chunks by allocating processes to the
largest available blocks which can result in inefficient use of memory for smaller processes.
Experiment No.14
Write a C program to simulate FIFO page replacement algorithm.
Algorithm:
Step 1: Start the process.
Step 2: Declare the size with respect to page length.
Step 3: Check the need of replacement from the page to memory.
Step 4: Check the need of replacement from old page to new page in memory.
Step 5: Form a queue to hold all pages and insert the page require memory into the queue.
Step 6: Check for bad replacement and page fault.
Step 7: Get the number of processes to be inserted.
Step 8: Display the values and stop the process

Source code:
#include <stdio.h>
void display(int frames[], int num_frames)
{
for (int i = 0; i < num_frames; i++)
{
if (frames[i] == -1)
printf("- ");
else
printf("%d ", frames[i]);
}
}
int main()
{
int num_frames, num_pages, pages[50], frames[10], page_faults = 0, next_replace = 0;
printf("Megh Raj Rasailee\nFIFO PAGE REPLACEMENT ALGORITHM\n\n");
printf("Enter the number of frames: ");
scanf("%d", &num_frames);
for (int i = 0; i < num_frames; i++)
frames[i] = -1;
printf("Enter the number of pages: ");
scanf("%d", &num_pages);
printf("Enter the reference string (page numbers): ");
for (int i = 0; i < num_pages; i++)
scanf("%d", &pages[i]);
printf("\nPage\tFrames\t\tStatus\n-------------------------------------\n");
for (int i = 0; i < num_pages; i++)
{
int page = pages[i], found = 0;
for (int j = 0; j < num_frames; j++)
{
if (frames[j] == page)
{
found = 1;
break;
}
}
if (!found)
{
frames[next_replace] = page;
next_replace = (next_replace + 1) % num_frames;
page_faults++;
printf("%d\t", page);
display(frames, num_frames);
printf("\tPage Fault\n");
}
else
{
printf("%d\t", page);
display(frames, num_frames);
printf("\tNo Page Fault\n");
}
}
printf("Total Page Faults: %d\n", page_faults);
return 0;
}

Output:

Conclusion:
The FIFO page replacement algorithm is simple but can cause more page faults in certain cases as it
replaces the oldest page first, without considering future references, leading to inefficient use of memory
in some scenarios.
Experiment No.15
Write a C program to simulate LRU page replacement algorithm.

Algorithm:
Step 1: Start the process.
Step 2: Declare the size.
Step 3: Get the number of pages to be inserted.
Step 4: Get the value, and declare counter and stack.
Step 5: Select the least recently used page by counter value and stack them according to the selection.
Step 6: Display the values, and stop the process
Source code:
#include <stdio.h>
void display(int frames[], int num_frames){
for (int i = 0; i < num_frames; i++) {
if (frames[i] == -1)
printf("- ");
else
printf("%d ", frames[i]);
}
}
int findLRU(int age[], int num_frames){
int lru_index = 0;
for (int i = 1; i < num_frames; i++) {
if (age[i] < age[lru_index]) {
lru_index = i;
}
}
return lru_index;
}
int main(){
int num_frames, num_pages, pages[50], frames[10], age[10], page_faults = 0, time = 0;
printf("Megh Raj Rasailee\nLRU PAGE REPLACEMENT ALGORITHM\n\n");
printf("Enter the number of frames: ");
scanf("%d", &num_frames);
for (int i = 0; i < num_frames; i++) {
frames[i] = -1;
age[i] = -1;
}
printf("Enter the number of pages: ");
scanf("%d", &num_pages);
printf("Enter the reference string (page numbers): ");
for (int i = 0; i < num_pages; i++)
scanf("%d", &pages[i]);
printf("\nPage\tFrames\t\tStatus\n-------------------------------------\n");
for (int i = 0; i < num_pages; i++) {
int page = pages[i], found = 0;
for (int j = 0; j < num_frames; j++) {
if (frames[j] == page){
found = 1;
age[j] = time++;
break;
}
}
if (!found){
int lru_index = findLRU(age, num_frames);
frames[lru_index] = page;
age[lru_index] = time++;
page_faults++;
printf("%d\t", page);
display(frames, num_frames);
printf("\tPage Fault\n");
}
else{
printf("%d\t", page);
display(frames, num_frames);
printf("\tNo Page Fault\n");
}
}
printf("Total Page Faults: %d\n", page_faults);
return 0;
}

Output:

Conclusion:
Hence Least Recently Used (LRU) page replacement algorithm minimizes page faults by utilizing past
usage information of the pages and replaces the least recently used pages.
Experiment No.16
Write a C program to simulate LFU page replacement algorithm.

Algorithm:
Step 1: Start the process.
Step 2: Read the number of pages, frames, and each page value.
Step 3: Search for the page in the frames; if it is found, update its frequency.
Step 4: If page isn’t found and there is a free frame, allocate the page to free frame and set its frequency.
Step 5: If no frame is free, replace the page with the least frequently used page.
Step 6: Print the total number of page faults and stop the process.
Source code:
#include <stdio.h>
#include <limits.h>
void display(int frames[], int num_frames, int freq[]){
for (int i = 0; i < num_frames; i++) {
if (frames[i] == -1)
printf(" - ");
else
printf("%d(%d) ", frames[i], freq[i]);
}
}
int find_lfu(int freq[], int num_frames){
int min_freq = INT_MAX, lfu_index = 0;
for (int i = 0; i < num_frames; i++) {
if (freq[i] < min_freq) {
min_freq = freq[i];
lfu_index = i;
}
}
return lfu_index;
}
int main(){
int num_frames, num_pages, pages[50], frames[10], freq[10], page_faults = 0;
printf("Megh Raj Rasailee\nLFU PAGE REPLACEMENT ALGORITHM\n\n");
printf("Enter the number of frames: ");
scanf("%d", &num_frames);
for (int i = 0; i < num_frames; i++){
frames[i] = -1;
freq[i] = 0;
}
printf("Enter the number of pages: ");
scanf("%d", &num_pages);
printf("Enter the reference string (page numbers): ");
for (int i = 0; i < num_pages; i++)
scanf("%d", &pages[i]);
printf("\nPage\tFrames\t\t\tStatus\n---------------------------------------------\n");
for (int i = 0; i < num_pages; i++) {
int page = pages[i], found = 0;
for (int j = 0; j < num_frames; j++) {
if (frames[j] == page) {
found = 1;
freq[j]++;
break;
}
}
if (!found) {
int replace_index = find_lfu(freq, num_frames);
frames[replace_index] = page;
freq[replace_index] = 1;
page_faults++;
printf("%d\t", page);
display(frames, num_frames, freq);
printf("\tPage Fault\n");
}
else {
printf("%d\t", page);
display(frames, num_frames, freq);
printf("\tNo Page Fault\n");
}
}
printf("Total Page Faults: %d\n", page_faults);
return 0;
}

Output:

Conclusion:
Hence the LFU algorithm efficiently manages page replacement by tracking the
frequency of page accesses, ensuring that the page with the least number of accesses is replaced first
when a page fault occurs.
Experiment No.17
Write a C program to simulate Optimal page replacement algorithm.

Algorithm:
Step 1: Start the process.
Step 2: Read number of pages and frames, and also read each page value.
Step 3: Search for page in frames and if not available allocate free frame.
Step 4: If no frame is free, replace the page with the page that is lastly used.
Step 5: Print page number of page faults, and Stop the process.
Source code:
#include <stdio.h>
void display(int frames[], int num_frames){
for (int i = 0; i < num_frames; i++){
if (frames[i] == -1)
printf("- ");
else
printf("%d ", frames[i]);
}
}
int findOptimal(int frames[], int num_frames, int pages[], int curr_page_index, int num_pages){
int index = -1, farthest = curr_page_index;
for (int i = 0; i < num_frames; i++) {
int j;
for (j = curr_page_index; j < num_pages; j++){
if (frames[i] == pages[j]) {
if (j > farthest){
farthest = j;
index = i;
}
break;
}
}
if (j == num_pages){
return i;
}
}
return (index == -1) ? 0 : index;
}
int main(){
int num_frames, num_pages, pages[50], frames[10], page_faults = 0;
printf("Megh Raj Rasailee \nOPTIMAL PAGE REPLACEMENT ALGORITHM\n\n");
printf("Enter the number of frames: ");
scanf("%d", &num_frames);
for (int i = 0; i < num_frames; i++)
frames[i] = -1;
printf("Enter the number of pages: ");
scanf("%d", &num_pages);
printf("Enter the reference string (page numbers): ");
for (int i = 0; i < num_pages; i++)
scanf("%d", &pages[i]);
printf("\nPage\tFrames\t\tStatus\n-------------------------------------\n");
for (int i = 0; i < num_pages; i++){
int page = pages[i], found = 0;
for (int j = 0; j < num_frames; j++) {
if (frames[j] == page){
found = 1;
break;
}
}
if (!found){
int replace_index = findOptimal(frames, num_frames, pages, i + 1, num_pages);
frames[replace_index] = page;
page_faults++;
printf("%d\t", page);
display(frames, num_frames);
printf("\tPage Fault\n");
}
else {
printf("%d\t", page);
display(frames, num_frames);
printf("\tNo Page Fault\n");
}
}
printf("Total Page Faults: %d\n", page_faults);
return 0;
}

Output:

Conclusion:
Hence, the Optimal Page Replacement Algorithm effectively minimizes page faults by replacing the page
that will not be used for longest period in the future.
Experiment No.18
Write a C program to simulate the following file organization techniques.
a) Single level directory b) Two level directory c) Hierarchical

Source code:

a)Single level directory

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct File
{
char name[20];
struct File *next;
};
struct File *createFile(char *name)
{
struct File *newFile = (struct File *)malloc(sizeof(struct File));
strcpy(newFile->name, name);
newFile->next = NULL;
return newFile;
}
void addFileToDirectory(struct File **head, char *fileName)
{
struct File *newFile = createFile(fileName);
newFile->next = *head;
*head = newFile;
}
void displayFiles(struct File *file)
{
while (file)
{
printf(" %s\n", file->name);
file = file->next;
}
}
int main()
{
printf("Megh Raj Rasailee\nSINGLE LEVEL DIRECTORY\n\n");
struct File *rootDirectory = NULL;
addFileToDirectory(&rootDirectory, "file1.txt");
addFileToDirectory(&rootDirectory, "file2.txt");
printf("Files in Root Directory:\n");
displayFiles(rootDirectory);
return 0;
}

b)Two level directory

#include<stdio.h>
#include <string.h>
#include <stdlib.h>
struct File{
char name[20];
struct File *next;
};
struct Directory{
char name[20];
struct File *files;
};
struct File *createFile(char *name){
struct File *newFile = (struct File *)malloc(sizeof(struct File));
strcpy(newFile->name, name);
newFile->next = NULL;
return newFile;
}
void addFileToDirectory(struct Directory *dir, char *fileName){
struct File *newFile = createFile(fileName);
newFile->next = dir->files;
dir->files = newFile;
}
void displayFiles(struct File *file){
while (file)
{
printf(" %s\n", file->name);
file = file->next;
}
}
void displayDirectory(struct Directory *dir){
printf("User Directory: %s\n", dir->name);
printf("Files:\n");
displayFiles(dir->files);
}
int main() {
printf("Megh Raj Rasailee\nTWO LEVEL DIRECTORY\n\n");
struct Directory user1, user2;
strcpy(user1.name, "User1");
strcpy(user2.name, "User2");
user1.files = NULL;
user2.files = NULL;
addFileToDirectory(&user1, "user1_file1.txt");
addFileToDirectory(&user2, "user2_file1.txt");
displayDirectory(&user1);
displayDirectory(&user2);
return 0;
}

c)Hierarchical

#include <stdio.h>
#include<stdlib.h>
#include <string.h>
struct Node{
char name[20];
int isFile;
struct Node *subDirs, *next;
};
struct Node *createNode(char *name, int isFile){
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
strcpy(newNode->name, name);
newNode->isFile = isFile;
newNode->subDirs = NULL;
newNode->next = NULL;
return newNode;
}
void addSubNode(struct Node *parent, struct Node *subNode){
subNode->next = parent->subDirs;
parent->subDirs = subNode;
}
void display(struct Node *node, int level) {
while (node)
{
for (int i = 0; i < level; i++)
printf(" ");
printf("%s", node->isFile ? "File: " : "Directory: ");
printf("%s\n", node->name);
if (!node->isFile)
{
display(node->subDirs, level + 1);
}
node = node->next;
}
}
int main() {
printf("\nHIERARCHICAL DIRECTORY\n\n");
struct Node *root = createNode("Root", 0);
struct Node *user1 = createNode("User1", 0);
struct Node *user2 = createNode("User2", 0);
addSubNode(root, user1);
addSubNode(root, user2);
struct Node *file1 = createNode("file1.txt", 1);
struct Node *subDir1 = createNode("SubDir1", 0);
struct Node *subFile1 = createNode("subfile1.txt", 1);
addSubNode(user1, file1);
addSubNode(user1, subDir1);
addSubNode(subDir1, subFile1);
display(root, 0);
return 0;
}
Output:

Conclusion:
The single-level directory is simple to implement and understand but can cause name conflicts when
managing a large number of files. The two-level directory improves organization by separating files
based on users, but it introduces additional complexity when accessing or managing files. The
hierarchical directory is the most flexible and scalable, allowing for efficient file organization with
folders and subfolders, though it requires more overhead to maintain the folder structure.
Experiment No.19
Write a C program to simulate all file allocation strategies. a) Sequential b) Indexed c) Linked
Source code:

a)Sequential
#include <stdio.h>
#define MAX_BLOCKS 30
#define MAX_FILES 10
typedef struct{
int start, length;
} File;
int main(){
printf("Megh Raj Rasailee\nSEQUENTIAL FILE ALLOCATION\n");
int disk[MAX_BLOCKS] = {0}, file_count = 0;
File files[MAX_FILES];
char choice;
do{
int start, length, can_alloc = 1;
printf("\nEnter the start block: ");
scanf("%d", &start);
printf("Enter the file length: ");
scanf("%d", &length);
for (int i = start; i < start + length; i++){
if (disk[i]){
printf("Block %d occupied!\n", i);
can_alloc = 0;
break;
}
}
if (can_alloc){
for (int i = start; i < start + length; i++)
disk[i] = 1;
files[file_count++] = (File){start, length};
printf("File allocated.\n");
}
printf("Allocate another file? (y/n): ");
scanf(" %c", &choice);
} while (choice == 'y');
printf("\nFile Allocation Table:\n");
for (int i = 0; i < file_count; i++){
printf("File %d: Start = %d, Length = %d\n", i + 1, files[i].start, files[i].length);
}
printf("\nDisk Status:\n");
for (int i = 0; i < MAX_BLOCKS; i++){
printf("%d ", disk[i]);
if ((i + 1) % 10 == 0)
printf("\n");
}
return 0;
}
b)Indexed
#include <stdio.h>
#define MAX_BLOCKS 50
#define MAX_FILES 10
typedef struct{
int index_block, data_blocks[MAX_BLOCKS], block_count;
} File;
int main(){
printf("Megh Raj Rasailee\nINDEXED FILE ALLOCATION\n");
int disk[MAX_BLOCKS] = {0}, i, file_count = 0;
File files[MAX_FILES];
char choice;
do {
int index, n;
printf("\nEnter the index block: ");
scanf("%d", &index);
if (disk[index]) {
printf("Block occupied!\n");
continue;
}
printf("Enter the number of data blocks: ");
scanf("%d", &n);
int blocks[MAX_BLOCKS];
printf("Enter the data blocks: ");
for (i = 0; i < n; i++){
scanf("%d", &blocks[i]);
if (disk[blocks[i]]){
printf("Block %d occupied!\n");
break;
}
}
files[file_count].index_block = index;
files[file_count].block_count = n;
disk[index] = 1;
for (i = 0; i < n; i++){
disk[blocks[i]] = 1;
files[file_count].data_blocks[i] = blocks[i];
}
file_count++;
printf("File allocated.\n");
printf("Allocate another file? (y/n): ");
scanf(" %c", &choice);
} while (choice == 'y');
printf("\nFile Allocation Table:\n");
for (i = 0; i < file_count; i++){
printf("%d -> Index: %d, Blocks: ", i + 1, files[i].index_block);
for (int j = 0; j < files[i].block_count; j++) {
printf("%d ", files[i].data_blocks[j]);
}
printf("\n");
}
return 0;
}
c)Linked
#include <stdio.h>
#define MAX_BLOCKS 50
#define END -1
int start[MAX_BLOCKS], next[MAX_BLOCKS], disk[MAX_BLOCKS] = {0};
int main(){
printf("Megh Raj Rasailee \nLINKED FILE ALLOCATION\n");
int n, s, blocks[MAX_BLOCKS];
char choice;
do{
printf("\nEnter the start block: ");
scanf("%d", &s);
if (disk[s]){
printf("Start block occupied!\n");
continue;
}
printf("Enter the number of blocks: ");
scanf("%d", &n);
printf("Enter the blocks: ");
for (int i = 0; i < n; i++){
scanf("%d", &blocks[i]);
if (disk[blocks[i]]){
printf("Block %d occupied!\n", blocks[i]);
continue;
}
}
start[s] = s;
int curr = s;
disk[s] = 1;
for (int i = 0; i < n; i++){
disk[blocks[i]] = 1;
next[curr] = blocks[i];
curr = blocks[i];
}
next[curr] = END;
printf("Allocate another file? (y/n): ");
scanf(" %c", &choice);
} while (choice == 'y' || choice == 'Y');
printf("\nFile allocations:\n");
for (int i = 0; i < MAX_BLOCKS; i++){
if (start[i]){
int curr = i;
printf("%d -> ", curr);
while (next[curr] != END) {
printf("%d -> ", next[curr]);
curr = next[curr];
} printf("NULL\n");
}
} return 0;
}
Output:

Conclusion:
Each method has trade-offs based on file system needs. The sequential allocation is simple but causes
fragmentation, linked allocation avoids fragmentation but is slower, and indexed allocation balances
both by using an index block, though it adds some overhead.
Experiment No.20
Write a C program to simulate disk scheduling algorithms. a) FCFS b) SCAN c) LOOK
Source code:
a)FCFS
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Megh Raj Rasailee\nFCFS DISK SCHEDULING\n");
int queue[20], head, qsize, i;
printf("\nEnter the size of queue: ");
scanf("%d", &qsize);
printf("Enter the queue elements: ");
for (i = 0; i < qsize; i++)
{
scanf("%d", &queue[i]);
}
printf("Enter initial head position: ");
scanf("%d", &head);
printf("\nHead Movement Sequence: ");
for (i = 0; i < qsize - 1; i++)
{
printf("%d->", queue[i]);
}
printf("%d\n", queue[qsize - 1]);
int total_movement = 0;
for (i = 0; i < qsize; i++)
{
total_movement += abs(head - queue[i]);
head = queue[i];
}
printf("Total Head Movement: %d\n", total_movement);
return 0;
}

b)SCAN
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Megh Raj Rasailee\nSCAN DISK SCHEDULING\n\n");
int q[20], h, qs, ds, dir, i, j, tm = 0, idx = 0;
printf("Enter the queue size: ");
scanf("%d", &qs);
printf("Enter the queue elements: ");
for (i = 0; i < qs; i++)
scanf("%d", &q[i]);
printf("Enter the initial head position: ");
scanf("%d", &h);
printf("Enter the disk size: ");
scanf("%d", &ds);
printf("Enter the direction (0 for left, 1 for right): ");
scanf("%d", &dir);
for (i = 0; i < qs - 1; i++)
{
for (j = i + 1; j < qs; j++)
{
if (q[i] > q[j])
{
int temp = q[i];
q[i] = q[j];
q[j] = temp;
}
}
}
while (q[idx] < h && idx < qs)
idx++;
printf("\nHead Movement Sequence: %d", h);
if (dir == 1)
{
for (i = idx; i < qs; i++)
{
printf("->%d", q[i]);
tm += abs(h - q[i]);
h = q[i];
}
printf("->%d", ds - 1);
tm += abs(h - (ds - 1));
h = ds - 1;
for (i = idx - 1; i >= 0; i--)
{
printf("->%d", q[i]);
tm += abs(h - q[i]);
h = q[i];
}
}
else
{
for (i = idx - 1; i >= 0; i--)
{
printf("->%d", q[i]);
tm += abs(h - q[i]);
h = q[i];
}
printf("->0");
tm += abs(h - 0);
h = 0;
for (i = idx; i < qs; i++)
{
printf("->%d", q[i]);
tm += abs(h - q[i]);
h = q[i];
}
}
printf("\nTotal Head Movement: %d\n", tm);
return 0;
}
c)LOOK
#include <stdio.h>
#include <stdlib.h>
int main(){
printf("Megh Raj Rasailee\nLOOK DISK SCHEDULING\n\n");
int q[20], h, qs, dir, i, j, tm = 0, idx = 0;
printf("Enter the queue size: ");
scanf("%d", &qs);
printf("Enter the queue elements: ");
for (i = 0; i < qs; i++)
scanf("%d", &q[i]);
printf("Enter the initial head position: ");
scanf("%d", &h);
printf("Enter the direction (0 for left, 1 for right): ");
scanf("%d", &dir);
for (i = 0; i < qs - 1; i++){
for (j = i + 1; j < qs; j++){
if (q[i] > q[j]){
int temp = q[i];
q[i] = q[j];
q[j] = temp;
}
}
}
while (idx < qs && q[idx] < h)
idx++;
printf("\nHead Movement Sequence: %d", h);
if (dir == 1){
for (i = idx; i < qs; i++){
printf("->%d", q[i]);
tm += abs(h - q[i]);
h = q[i];
}
for (i = idx - 1; i >= 0; i--){
printf("->%d", q[i]);
tm += abs(h - q[i]);
h = q[i];
}
}
else{
for (i = idx - 1; i >= 0; i--){
printf("->%d", q[i]);
tm += abs(h - q[i]);
h = q[i];
}
for (i = idx; i < qs; i++) {
printf("->%d", q[i]);
tm += abs(h - q[i]);
h = q[i];
}
}
printf("\nTotal Head Movement: %d\n", tm);
return 0;
}
Output:

Conclusion:
Each algorithm has its trade-offs in terms of simplicity and efficiency. FCFS is straightforward but
inefficient for disk seek times, SCAN improves efficiency by moving the disk head systematically in
one direction, and LOOK further optimizes performance by only moving to the last request in each
direction, reducing unnecessary head movement

You might also like