0% found this document useful (0 votes)
2 views100 pages

Cs 604 LAB

This document provides a comprehensive guide on installing VirtualBox and Ubuntu, along with basic Ubuntu commands, inter-process communication using pipes, thread creation in C, and the FCFS CPU scheduling algorithm. It includes step-by-step instructions for installation, command usage, and programming examples. The document serves as a practical resource for learning and implementing fundamental concepts in virtualization, Linux commands, and C programming.

Uploaded by

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

Cs 604 LAB

This document provides a comprehensive guide on installing VirtualBox and Ubuntu, along with basic Ubuntu commands, inter-process communication using pipes, thread creation in C, and the FCFS CPU scheduling algorithm. It includes step-by-step instructions for installation, command usage, and programming examples. The document serves as a practical resource for learning and implementing fundamental concepts in virtualization, Linux commands, and C programming.

Uploaded by

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

LAB 1: Install VirtualBox and Ubuntu

Basic Concepts

What is VirtualBox?

VirtualBox is software that allows you to run another operating system (like Ubuntu)
inside your computer without removing your current OS.

What is a Virtual Machine (VM)?

A VM is a virtual computer created inside your real computer. It uses your computer's
resources (RAM, CPU, storage) to run another operating system separately.

What is Ubuntu?

Ubuntu is a free, open-source Linux operating system used for programming, learning,
and server work.

Part 1: Install VirtualBox

Step 1: Download VirtualBox

1. Go to:
[Link]

2. Click Downloads.

3. Select your operating system (e.g., Windows Hosts).

Step 2: Install VirtualBox

1. Open the downloaded setup file.

2. Follow the installation steps.

3. Keep default settings.

4. Click Install → Finish.

Part 2: Install Ubuntu on VirtualBox

Step 1: Download Ubuntu ISO

1. Go to:
[Link]

2. Download Ubuntu Desktop ISO.


3. Check your system type:

o Right-click This PC → Properties

o Check if your system is 32-bit or 64-bit.

Step 2: Create Ubuntu Virtual Machine

1. Open VirtualBox.

2. Click New.

3. Enter:

o Name: Ubuntu

o Type: Linux

o Version: Ubuntu (64-bit)

4. Click Next.

Step 3: Assign RAM

• Give half of your computer's RAM.

• Example:

o 8GB RAM → Give 4GB (4096 MB)

o 4GB RAM → Give 2GB (2048 MB)

Step 4: Create Virtual Hard Disk

Select:

• Create a virtual hard disk now

• Type: VDI

• Storage: Dynamically allocated

• Size: 25 GB or more

Step 5: Add Ubuntu ISO File

1. Select your Ubuntu VM.


2. Go to Settings → Storage.

3. Click the empty disk icon.

4. Choose your Ubuntu ISO file.

Step 6: Install Ubuntu

1. Click Start.

2. Ubuntu will open.

3. Select Install Ubuntu.

4. Complete setup:

o Language

o Time zone

o Username

o Password

Step 7: Finish Installation

1. Restart the Virtual Machine.

2. Ubuntu is now ready to use inside VirtualBox.

Result:

VirtualBox and Ubuntu have been successfully installed, and Ubuntu can run as a
virtual machine on your computer.

LAB 2: Basic Ubuntu & Linux Commands + C Program Compilation

1. Check GCC Version

GCC is a compiler used to run C programs.


Check GCC:

gcc --version

Install GCC (if not installed):

sudo apt install build-essential

2. Basic Terminal Commands

Clear Terminal

clear

Check Current Location

pwd

Shows your current directory.

Change Directory

Go to a folder:

cd foldername

Go back:

cd ..

Go to Home:

cd ~

3. Create Directory (Folder)

Create a folder:

mkdir cs604p

Enter folder:

cd cs604p

Create multiple folders:

mkdir -p CS604/Files/CFiles

Structure:

CS604
└── Files

└── CFiles

4. Create Files

Create empty file:

touch [Link]

Create file using >:

> [Link]

Difference:

Command Purpose

touch Creates file safely

> Creates file and removes old content

5. View Files

Show files in current folder:

ls

View file content:

cat filename

Example:

cat [Link]

6. Write, Compile & Run C Program

Step 1: Create C file

Example:

touch myprogram.c

(C programs always use .c extension)


Step 2: Write Code

Open the file and write your C program.

Example:

#include<stdio.h>

int main()

printf("Hello World");

return 0;

Save the file.

Step 3: Compile Program

Syntax:

gcc filename.c -o outputname

Example:

gcc myprogram.c -o myprogram

Step 4: Run Program

Syntax:

./filename

Example:

./myprogram

7. Remove Files (rm)

Delete a file:

rm filename

Example:
rm [Link]

Ask before deleting:

rm -i filename

Delete multiple files:

rm [Link] [Link] [Link]

Delete all txt files:

rm *.txt

rm permanently deletes files (does not move them to Trash).

8. Move & Rename Files (mv)

Rename file

Syntax:

mv oldname newname

Example:

mv [Link] [Link]

Move file

Syntax:

mv filename destination

Example:

mv [Link] ~/Documents/

Move multiple files

mv [Link] [Link] ~/Documents/

9. System Information (uname)

Check system information:


Command Shows

uname Kernel name

uname -a Complete information

uname -r Kernel version

uname -m Machine type

uname -o Operating system

Quick Command List (Must Remember)

Task Command

Clear screen clear

Current directory pwd

Change directory cd

Go back cd ..

Create folder mkdir

Create file touch

List files ls

View file cat

Delete file rm

Move/Rename mv

Compile C gcc file.c -o name

Run C program ./name

System info uname


LAB 3: Two-Way Inter-Process Communication Using Pipes in C

Objective

Learn how parent and child processes communicate with each other using pipes in
C.

In this lab:

1. Parent sends a message → Child receives it.

2. Child sends a reply → Parent receives it.

1. What is IPC?

IPC (Inter-Process Communication) is a method that allows two processes to


exchange data.

Example:

• Parent process communicates with child process.

2. What is a Pipe?

A pipe is a communication channel between processes.

A pipe has two ends:

Pipe End Purpose

pipe[0] Read data

pipe[1] Write/send data

Example:

Write End → Pipe → Read End

3. Parent and Child Process

When we use:

fork();

It creates two processes:

1. Parent Process
2. Child Process

Checking process:

pid > 0 → Parent

pid == 0 → Child

4. Important System Calls

Command Purpose

pipe() Creates communication pipe

fork() Creates child process

write() Sends data

read() Receives data

close() Closes unused pipe end

Program Logic

We use two pipes:

Pipe 1:

Parent → Child

Parent

| Hello Child

Child

Pipe 2:

Child → Parent

Child

| Hello Parent

Parent

Important Code Explanation

Include Libraries

#include <stdio.h>

Used for printf().

#include <unistd.h>

Used for pipe(), fork(), read(), write().

#include <string.h>

Used for strlen().

Create Pipes

int pipe1[2], pipe2[2];

Creates two pipes.

Each pipe has:

pipe[0] = Read

pipe[1] = Write

Messages

char parent_msg[]="Hello Child";

char child_msg[]="Hello Parent";

Messages exchanged between processes.

Create Pipes

pipe(pipe1);

pipe(pipe2);

Creates communication channels.


Create Child Process

int pid=fork();

Creates child process.

After fork:

Parent

Child

Parent Process

Condition:

if(pid > 0)

Means parent process.

Close unused ends

close(pipe1[0]);

Parent does not read from pipe1.

close(pipe2[1]);

Parent does not write to pipe2.

Send Message

write(pipe1[1], parent_msg, strlen(parent_msg)+1);

Parent sends:

Hello Child

to child.

Receive Reply

read(pipe2[0], buffer, sizeof(buffer));


Parent receives:

Hello Parent

Display Message

printf("Parent received: %s\n", buffer);

Child Process

Condition:

else

Means child process.

Close unused ends

close(pipe1[1]);

Child does not write to pipe1.

close(pipe2[0]);

Child does not read from pipe2.

Receive Parent Message

read(pipe1[0], buffer, sizeof(buffer));

Child receives:

Hello Child

Display Message

printf("Child received: %s\n", buffer);

Send Reply

write(pipe2[1], child_msg, strlen(child_msg)+1);

Child sends:
Hello Parent

Expected Output

Child received: Hello Child

Parent received: Hello Parent

Steps to Run Program

1. Open Ubuntu Virtual Machine

Start Ubuntu from VirtualBox.

2. Open Terminal

Shortcut:

Ctrl + Alt + T

3. Go to Desktop

cd Desktop

4. Create C File

touch pipe.c

5. Open File and Write Code

Save the program.

6. Compile Program

Syntax:

gcc filename.c -o outputname

Example:
gcc pipe.c -o pipe

7. Run Program

./pipe

Output:

Child received: Hello Child

Parent received: Hello Parent

Quick Revision

Remember:

pipe() → Create communication channel

fork() → Create child process

write() → Send message

read() → Receive message

close() → Close unused side

Main Idea:
Parent sends data using pipe1, child replies using pipe2.

LAB 4: Thread Creation and Termination in C

Objective

Learn how to:


• Create threads in C

• Run multiple threads together

• Terminate threads properly using pthread functions

1. What is a Thread?

A thread is the smallest unit of execution inside a process.

• A process can have multiple threads.

• Threads share the same memory and resources.

• Threads make programs faster by running multiple tasks at the same time.

Example:

• In MS Word:

o One thread handles typing.

o Another thread handles spell checking.

2. Difference Between Process and Thread

Process Thread

Running program Small execution unit inside a process

Has its own memory Shares process memory

Slower to create Faster to create

Uses more resources Uses fewer resources

Communication needs IPC Uses shared memory

Easy Remember:

Program = Code stored on disk

Process = Running program

Thread = Task inside a process

3. Types of Threads
1. User-Level Threads

• Managed by user programs.

• Faster but limited.

2. Kernel-Level Threads

• Managed by Operating System.

• Supports real parallel execution.

4. Relationship Between Process and Threads

One process can contain multiple threads.

Example:

Process

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

| | |

Thread1 Thread2 Thread3

Threads share:

• Memory

• Code

• Resources

5. Thread Creation in C

Linux uses pthread library.

Create thread:

pthread_create(&thread_id, NULL, function_name, NULL);

6. Important pthread Functions


Function Purpose

pthread_create() Creates a new thread

pthread_join() Waits for thread completion

pthread_exit() Terminates a thread

pthread_self() Gets thread ID

pthread_detach() Separates thread

7. Thread Termination

A thread ends by:

1. Returning from its function

Example:

return NULL;

2. Using:

pthread_exit();

8. Important Terms for Thread Program

Term Purpose

pthread_t Stores thread ID

pthread_create Creates thread

pthread_join Waits for thread

void *function(void *) Thread function format

usleep() Creates delay

printf() Displays output

gcc -pthread Compiles thread program

Program Aim
Create two threads:

• Thread 1

• Thread 2

Tasks:

1. Create both threads.

2. Display their IDs.

3. Run them simultaneously.

4. Terminate them after completion.

Program Explanation (Simple)

Libraries

#include <stdio.h>

Used for printf().

#include <stdlib.h>

Used for exit().

#include <pthread.h>

Used for thread functions.

#include <unistd.h>

Used for usleep().

Thread Function

void *thread_function(void *arg)

Function that each thread runs.

usleep(50000);

Pauses thread for a short time.

return NULL;
Ends thread.

Main Function

pthread_t t1,t2;

Creates two thread variables.

• t1 = Thread 1 ID

• t2 = Thread 2 ID

Create Thread 1

pthread_create(&t1,NULL,thread_function,NULL);

Creates Thread 1.

Create Thread 2

pthread_create(&t2,NULL,thread_function,NULL);

Creates Thread 2.

Display Thread IDs

printf("Thread ID: %lu", t1);

Shows thread ID.

Wait for Threads

pthread_join(t1,NULL);

pthread_join(t2,NULL);

Main program waits until both threads finish.

Compile and Run Program

Step 1: Create file

touch thread.c
Step 2: Compile

Important:
Use -pthread

gcc thread.c -o thread -pthread

Step 3: Run

./thread

Expected Output

Example:

Thread with ID: 140234 created

Thread with ID: 140235 created

Threads are going to be terminated one by one

(Thread IDs may be different every time.)

Quick Revision

Remember:

pthread_create() → Create thread

pthread_join() → Wait for thread

pthread_exit() → End thread

pthread_t → Store thread ID


-pthread → Compile thread program

Main Idea:
A thread is a small task inside a process. Multiple threads allow a program to perform
multiple tasks at the same time.

LAB 5: FCFS CPU Scheduling Algorithm in C

Objective

Implement the First Come First Serve (FCFS) CPU scheduling algorithm in C.

The program calculates:

• Waiting Time

• Turnaround Time

• Average Waiting Time

• Average Turnaround Time

1. What is FCFS?

FCFS (First Come First Served) is a CPU scheduling algorithm where processes
execute in the order they arrive.

Example:

P0 → P1 → P2 → P3

The first process runs first, then the next process.

Features:

• Non-preemptive algorithm

• Simple and easy to implement

• Process runs until completion

2. Assumptions
• All processes arrive at time 0.

• Processes execute in order:

P0, P1, P2, P3

• No process interruption.

• First process waiting time is always 0.

3. Important Terms

Burst Time

The total CPU time required by a process.

Example:

P0 = 10 seconds

Waiting Time

Time a process waits before execution starts.

Formula:

Waiting Time = Previous Burst Time + Previous Waiting Time

Turnaround Time

Total time from process arrival to completion.

Formula:

Turnaround Time = Waiting Time + Burst Time

4. Given Data

Process Burst Time

P0 10

P1 4

P2 6
Process Burst Time

P3 8

5. FCFS Algorithm Steps

Step 1:

Set first process waiting time:

P0 Waiting Time = 0

Step 2:

Calculate remaining waiting times:

Waiting[i] = Waiting[i-1] + Burst[i-1]

Step 3:

Calculate turnaround:

Turnaround = Waiting + Burst

Step 4:

Find average values:

Average = Total / Number of Processes

6. Code Explanation

Include Library

#include <stdio.h>

Used for:

• printf()

• scanf()

Number of Processes

const int n = 4;

There are 4 processes:

P0 P1 P2 P3
Arrays

int burst[n];

int waiting[n];

int turnaround[n];

Stores:

• Burst times

• Waiting times

• Turnaround times

Burst Time Values

burst[0]=10;

burst[1]=4;

burst[2]=6;

burst[3]=8;

Assigns CPU time to each process.

First Waiting Time

waiting[0]=0;

First process does not wait.

Calculate Waiting Time

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

waiting[i]=waiting[i-1]+burst[i-1];

Calculates waiting time of each process.

Example:
P0 = 0

P1 = 0 + 10 = 10

P2 = 10 + 4 = 14

P3 = 14 + 6 = 20

Calculate Turnaround Time

turnaround[i]=waiting[i]+burst[i];

Example:

P1:

Waiting = 10

Burst = 4

Turnaround = 10 + 4 = 14

Calculate Average

avgWaiting = totalWaiting/n;

Calculates average waiting time.

avgTurnaround = totalTurnaround/n;

Calculates average turnaround time.

7. Compile and Run Program

Create C file

touch fcfs.c
Compile

gcc fcfs.c -o fcfs

Run

./fcfs

8. Expected Output

Process Burst Waiting Turnaround

P0 10 0 10

P1 4 10 14

P2 6 14 20

P3 8 20 28

Average Waiting Time = 11.00

Average Turnaround Time = 18.00

Quick Revision

Remember:

FCFS = First process comes, first executes

Waiting Time:

Previous Waiting + Previous Burst

Turnaround Time:

Waiting + Burst
Important Formula:

WT = Waiting Time

TAT = WT + Burst Time

Main Idea:
FCFS executes processes in order and calculates how long each process waits and
completes.

LAB 6: Round Robin CPU Scheduling Algorithm in C

Objective

Implement Round Robin (RR) CPU Scheduling in C and calculate:

• Waiting Time

• Turnaround Time

• Average Waiting Time

• Average Turnaround Time

1. What is Round Robin Scheduling?

Round Robin (RR) is a pre-emptive CPU scheduling algorithm.

Each process gets a fixed amount of CPU time called Time Quantum.

If a process is not completed within its time quantum:

• CPU stops it.

• It goes back to the end of the queue.

• The next process gets CPU time.

Example:

P0 → P1 → P2 → P3 → P0 → P1 ...
2. Process States

A process can have these states:

State Meaning

New Process is being created

Ready Waiting for CPU

Running Executing on CPU

Waiting Waiting for I/O or event

Terminated Execution completed

3. Important Concepts

Time Quantum

A fixed time given to each process.

Example:

Time Quantum = 4

A process can run for maximum 4 units at one turn.

Pre-emption

If a process is not completed:

Example:

Burst Time = 10

Quantum = 4

Execution:

Run 4 → Remaining 6

Run 4 → Remaining 2

Run 2 → Complete

Context Switching
When CPU changes from one process to another.

Example:

P0 stops → P1 starts

The system saves the old process state and loads the new one.

4. Working of Round Robin

Steps:

1. Put all processes in ready queue.

2. Give each process CPU time equal to quantum.

3. If process finishes:

o Remove it.

4. If not:

o Put it back in queue.

5. Repeat until all processes complete.

5. Advantages and Disadvantages

Advantages

Fair scheduling
Every process gets CPU time
Easy to implement

Disadvantages

Too small quantum causes many context switches.


Too large quantum behaves like FCFS.

6. Example Data

Time Quantum:

Processes:
Process Burst Time

P0 10

P1 4

P2 2

P3 8

7. Important Formulas

Turnaround Time

TAT = Finish Time - Arrival Time

Since arrival time is 0:

TAT = Finish Time

Waiting Time

WT = Turnaround Time - Burst Time

8. Program Logic

Store burst times:

P0 = 10

P1 = 4

P2 = 2

P3 = 8

Copy burst time into remaining array:

Example:

Remaining:

10 4 2 8

Every time a process executes:

Remaining Time = Remaining Time - Quantum


9. Code Explanation

Header File

#include <stdio.h>

Used for:

• printf()

Number of Processes

const int n = 4;

There are 4 processes.

Arrays

int burst[4];

Stores CPU burst time.

int remaining[4];

Stores remaining execution time.

int waiting[4];

Stores waiting time.

int turnaround[4];

Stores turnaround time.

int finish[4];

Stores completion time.

Time Quantum

int timeQuantum = 4;

Each process gets 4 CPU units.

Global Clock
int time = 0;

Tracks total CPU time.

Completed Counter

int completed = 0;

Counts finished processes.

10. Initialize Arrays

remaining[i] = burst[i];

Initially:

Remaining Time = Burst Time

Example:

P0 = 10

P1 = 4

P2 = 2

P3 = 8

11. Round Robin Execution

Loop continues until all processes finish:

while(completed < n)

Check every process:

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

If process still has work:

if(remaining[i] > 0)

Case 1: Remaining Time > Quantum


Example:

Remaining = 10

Quantum = 4

Execute:

10 - 4 = 6

Code:

time += timeQuantum;

remaining[i] -= timeQuantum;

Case 2: Process Finishes

If:

Remaining <= Quantum

Process completes.

Code:

time += remaining[i];

Updates CPU time.

Set remaining time:

remaining[i]=0;

Process completed.

Calculate:

turnaround[i]=finish[i];

and:

waiting[i]=turnaround[i]-burst[i];

12. Compile and Run

Create file
touch round_robin.c

Compile

gcc round_robin.c -o lab

Run

./lab

13. Expected Output

Process Burst Waiting Turnaround

P0 10 14 24

P1 4 4 8

P2 2 8 10

P3 8 14 22

Average Waiting Time = 10.00

Average Turnaround Time = 16.00

Quick Revision

Remember:

Round Robin = Each process gets fixed time

Time Quantum = CPU time given to each process

Remaining Time = Burst - Executed Time


TAT = Finish Time

WT = TAT - Burst Time

Main Idea:

Round Robin gives every process a fair chance by executing them one by one for a fixed
time quantum until all processes finish.

LAB 7: Producer–Consumer Problem Using Circular Buffer in C

Objective

Implement the Producer–Consumer problem in C using a circular buffer.

The program will:

• Produce integer values.

• Consume integer values.

• Prevent buffer overflow and underflow.

• Display produced and consumed items.

1. What is Producer–Consumer Problem?

Producer–Consumer is a synchronization problem where:

Producer

Creates data and puts it into a shared buffer.

Consumer

Takes data from the buffer and uses it.

Example:

Producer → Buffer → Consumer


2. What is a Buffer?

A buffer is a temporary storage area where produced data is stored before


consumption.

Example:

Buffer:

[10] [20] [30]

3. Circular Buffer

A circular buffer works like a circle.

When the last position is reached, it starts again from the first position.

Formula:

(index + 1) % buffer_size

Example:

Buffer size = 3

0→1→2→0→1

4. Important Concepts

Buffer Full

When buffer has no empty space.

Example:

Buffer size = 3

[10][20][30]

Producer cannot add more items.

Buffer Empty

When there is no item to consume.

Example:
[]

Consumer cannot remove anything.

5. Important Variables

Variable Purpose

buffer Stores items

in Position where producer writes

out Position where consumer reads

counter Number of items currently in buffer

6. Algorithm

Producer:

1. Check if buffer is full.

2. If full → Display "Buffer Full".

3. Otherwise:

o Add item.

o Move index.

o Increase counter.

Consumer:

1. Check if buffer is empty.

2. If empty → Display "Buffer Empty".

3. Otherwise:

o Remove item.

o Move index.

o Decrease counter.
7. Required Functions

Function Purpose

printf() Display output

scanf() Take input

malloc() Allocate memory

free() Release memory

8. Program Explanation

Header Files

#include <stdio.h>

Used for input/output:

• printf()

• scanf()

#include <stdlib.h>

Used for:

• malloc()

• free()

9. Variables

int bufsize;

Stores buffer size.

Example:

Buffer size = 3

int in = 0;

Producer position.
int out = 0;

Consumer position.

int counter = 0;

Counts items inside buffer.

10. Taking Buffer Size

scanf("%d",&bufsize);

User enters buffer size.

Example:

Enter buffer size: 3

11. Creating Buffer

int *buffer = malloc(bufsize * sizeof(int));

Creates memory space for buffer.

Example:

[ ][ ][ ]

12. Producer Operation

Command:

Means produce item.

Check buffer:

if(counter == bufsize)

If true:

Buffer is Full
Store value:

buffer[in]=value;

Example:

buffer[0]=10

Move producer position:

in=(in+1)%bufsize;

Moves to next location.

Increase item count:

counter++;

13. Consumer Operation

Command:

Means consume item.

Check empty buffer:

if(counter==0)

Output:

Buffer is Empty

Read item:

consumed=buffer[out];

Move consumer position:

out=(out+1)%bufsize;
Decrease count:

counter--;

14. Quit Program

Command:

Ends program.

15. Compile and Run

Create File

touch producer_consumer.c

Compile

gcc producer_consumer.c -o producer_consumer

Run

./producer_consumer

16. Sample Output

Enter buffer size: 3

Commands:

p = Produce

c = Consume

q = Quit
Choice: p

Enter value: 10

Produced: 10

Choice: p

Enter value: 20

Produced: 20

Choice: p

Enter value: 30

Produced: 30

Choice: p

Buffer is Full

Choice: c
Consumed: 10

Choice: c

Consumed: 20

Choice: q

Exiting program.

Quick Revision

Remember:

Producer → Adds item

Consumer → Removes item

Buffer Full → Cannot Produce

Buffer Empty → Cannot Consume

in → Producer position

out → Consumer position

counter → Number of items

Main Idea:
The Producer puts data into the shared buffer, and the Consumer removes data from it
while preventing overflow and underflow problems.

Lab 8 — Dining Philosophers Problem in C

Lab Aim

To solve the Dining Philosophers Problem in C and understand how Operating


Systems avoid deadlock using synchronization.

1. What is Dining Philosophers Problem?

• There are 5 philosophers sitting around a circular table.

• Each philosopher can perform two tasks:

o Thinking

o Eating

• To eat, each philosopher needs two forks:

o Left fork

o Right fork

There are only 5 forks available for 5 philosophers.

2. Problem (Deadlock Situation)

If every philosopher follows the same order:

1. Take left fork

2. Take right fork

Then:

Philosopher 1 → Takes Fork 1

Philosopher 2 → Takes Fork 2

Philosopher 3 → Takes Fork 3

Philosopher 4 → Takes Fork 4


Philosopher 5 → Takes Fork 5

Now everyone waits for the second fork.

Example:

P1 waits for Fork 2

P2 waits for Fork 3

P3 waits for Fork 4

P4 waits for Fork 5

P5 waits for Fork 1

No one can continue.

This situation is called:

Deadlock

Deadlock: A condition where processes keep waiting for resources forever.

3. Deadlock Solution

To avoid deadlock, change the order for one philosopher.

Normal philosophers:

Take Left Fork

Then Take Right Fork

Last philosopher:

Take Right Fork

Then Take Left Fork

This breaks the circular waiting condition and prevents deadlock.

4. Short Theory

Dining Philosophers is a resource-sharing problem.

• Philosophers represent processes.

• Forks represent shared resources.

• Mutex locks are used to control access to forks.


• Only one philosopher can use a fork at one time.

The solution uses synchronization to avoid conflicts.

5. Assumptions

• Number of philosophers = 5

• Number of forks = 5

• Each philosopher is represented as a process/thread.

• Each fork is a shared resource.

• Last philosopher takes the right fork first.

• Each philosopher completes one eating cycle.

6. Algorithm (Easy Steps)

1. Create 5 forks.

2. Initialize all forks as free.

3. Create philosopher states.

4. Each philosopher tries to get forks.

5. If both forks are available:

o Eat food.

o Release forks.

6. Last philosopher changes fork order to avoid deadlock.

7. Continue until all philosophers finish eating.

7. Important Terms

Term Meaning

Process A running program

Resource Something required by a process

Fork Shared resource


Term Meaning

Mutex Lock used for synchronization

Deadlock Infinite waiting situation

Synchronization Managing multiple processes safely

8. Code Explanation (Important Parts)

Header Files

#include<stdio.h>

#include<stdlib.h>

Used for:

• printf()

• system()

Number of Philosophers

#define n 4

Defines the number of philosophers and forks.

(Note: In standard Dining Philosophers problem, it is usually 5.)

Fork Structure

struct fork {

int taken;

};

Stores fork status.

Values:

0 = Available

1 = Taken
Philosopher Structure

struct philosp {

int left;

int right;

};

Stores whether philosopher has:

• Left fork

• Right fork

9. Function: goForDinner()

void goForDinner(int philID)

This function controls philosopher activities.

It checks:

Case 1:

Philosopher already finished.

left = 10

right = 10

Case 2:

Philosopher has both forks.

left = 1

right = 1

Actions:

• Complete dinner

• Release forks

• Increase completed count

Case 3:
Philosopher has only left fork.

Now it tries to get the right fork.

If fork is available:

Take right fork

Otherwise:

Wait

Case 4:

Philosopher has no fork.

It tries to take the left fork.

10. Main Function

Initialize Forks

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

ForkAvil[i].taken=0;

All forks are initially free.

Execute Dinner Process

while(compltedPhilo<n)

Loop continues until all philosophers complete dinner.

Calling Philosopher Function

goForDinner(i);

Each philosopher tries to eat.

11. Program Flow

Start

Create philosophers and forks

Initialize forks as free

Philosopher tries to get forks

If both forks available

Eat

Release forks

All philosophers finished?


End

12. Compile and Run

Compile:

gcc dining.c -o dining

Run:

./dining

13. Expected Output Example

Fork 1 taken by Philosopher 1

Fork 2 taken by Philosopher 2

Philosopher 1 completed his dinner

Philosopher 1 released fork 1 and fork 5

Philosopher 2 completed his dinner

Till now num of philosophers completed dinner are 5

Quick Exam Revision

Dining Philosophers Problem:

• It is a synchronization problem.

• Philosophers need two forks to eat.

• Same fork order causes deadlock.


• Changing order for one philosopher prevents deadlock.

Memory Trick:

"Same order = Deadlock, Different order = Solution."

Lab 9 — Banker's Algorithm in C

Lab Aim

To implement Banker's Algorithm in C and check whether a system is in a safe state or


not by finding a safe sequence.

1. What is Banker's Algorithm?

Banker's Algorithm is a deadlock avoidance algorithm used in Operating Systems.

It checks whether allocating resources to processes will keep the system safe.

It works like a bank:

• Bank gives resources only if it can still complete all processes.

• Similarly, OS gives resources only if the system remains safe.

2. Important Concepts

Deadlock

A situation where processes wait forever because resources are not available.

Example:

P1 waiting for Resource A

P2 waiting for Resource B

Neither process can continue.

Safe State

A system is in a safe state when:

• All processes can complete their execution.


• Resources can be allocated without causing deadlock.

Safe Sequence

A sequence in which all processes can finish safely.

Example:

P1 → P0 → P2

Means:

1. Execute P1

2. Release its resources

3. Execute P0

4. Execute P2

3. Matrices Used in Banker's Algorithm

1. Allocation Matrix

Shows resources already given to processes.

Example:

Alloc

P0 0 1 0

P1 2 0 0

P2 3 0 2

2. Maximum Matrix

Shows maximum resources required by each process.

Example:

Max

P0 7 5 3
P1 3 2 2

P2 9 0 2

3. Need Matrix

Shows remaining required resources.

Formula:

Need = Max - Allocation

Example:

P0:

Max 753

Alloc 010

Need 743

4. Available Array

Shows currently available resources.

Example:

Available:

A=3

B=3

C=2

5. Example Data

Process Allocation Maximum Need

P0 010 753 743


Process Allocation Maximum Need

P1 200 322 122

P2 302 902 600

Available:

A=3

B=3

C=2

Safe Sequence:

P1 → P0 → P2

6. Algorithm (Easy Steps)

Step 1:

Calculate Need matrix.

Need = Max - Allocation

Step 2:

Set all processes as unfinished.

Finish[i] = 0

Step 3:

Find a process where:

Need <= Available

If found:

• Add process to safe sequence.

• Release its resources.

• Update Available.

Formula:
Available = Available + Allocation

Step 4:

Repeat until:

• All processes finish → Safe State

• No process found → Unsafe State

7. Program Statement

Write a C program that:

• Calculates Need matrix.

• Implements Banker's Algorithm.

• Finds safe sequence.

• Displays safe sequence.

8. Important Data Structures

Array Purpose

alloc[][] Resources already allocated

max[][] Maximum resource requirement

need[][] Remaining resources needed

avail[] Available resources

finish[] Checks completed processes

safeSeq[] Stores safe order

9. Code Explanation (Important Parts)

Header File

#include<stdio.h>

Used for:
• printf()

• scanf()

Number of Processes and Resources

int n = 3;

int m = 3;

n = number of processes

m = number of resources

Allocation Matrix

int alloc[3][3]

Stores currently assigned resources.

Maximum Matrix

int max[3][3]

Stores maximum requirement.

Available Resources

int avail[3]={3,3,2};

Stores free resources.

Calculate Need

need[i][j] = max[i][j] - alloc[i][j];

Calculates remaining requirement.

Finish Array

int finish[3]={0};

Initially:
0 = Process not completed

1 = Process completed

Finding Safe Sequence

The program checks:

Need <= Available

If true:

• Process can execute.

• Add it to safe sequence.

• Release resources.

10. Program Flow

Start

Input Allocation, Maximum and Available resources

Calculate Need Matrix

Find process whose Need <= Available


Execute process

Release resources

Add process to Safe Sequence

All processes completed?

Print Safe Sequence

End

11. Compile and Run in Ubuntu

Create file:

nano bankers.c

Compile:

gcc bankers.c -o bankers

Run:
./bankers

12. Expected Output

Following is the SAFE Sequence:

P1 -> P0 -> P2

Q1: What is Banker's Algorithm?

Answer:
A deadlock avoidance algorithm that checks whether resource allocation keeps the
system safe.

Q2: What is a safe state?

Answer:
A state where all processes can complete execution without deadlock.

Q3: What is Need Matrix?

Answer:

Need = Maximum - Allocation

It shows remaining resources required by a process.

Q4: How is Available updated?

Answer:

After completing a process:

Available = Available + Allocation

Q5: What happens if no safe sequence exists?

Answer:

The system is in an unsafe state and resource allocation may cause deadlock.
Banker's Algorithm = Check before giving resources.

Need = Max - Allocation

Safe Sequence = Order in which all processes can finish safely.

Lab 10 — Logical vs Physical Address Translation

Lab Objective

To understand the difference between logical address and physical address and learn
how a logical address is converted into a physical address using the Segment:Offset
mechanism.

1. Logical Address

A logical address is the address generated by the CPU during program execution.

• It belongs to the process.

• It is also called a virtual address.

• It is converted into a physical address before accessing memory.

Example:

Segment : Offset

1000H : 0020H

2. Physical Address

A physical address is the actual location in the computer's RAM where data is stored.

• Generated after address translation.

• Used by memory hardware.

3. Segment and Offset


In 16-bit systems like 8086, memory is divided into segments.

A logical address contains:

Segment + Offset

Segment

• Represents the starting location of a memory block.

• Stored in segment registers:

CS → Code Segment

DS → Data Segment

SS → Stack Segment

ES → Extra Segment

The segment value alone is not the complete address.

Offset

• Shows the distance from the beginning of the segment.

• Identifies the exact location inside the segment.

4. Why Shift Segment by 4 Bits?

In 8086 architecture:

• Segment address is shifted left by 4 bits.

• This converts it into a physical base address.

Formula:

Segment × 16

OR

Segment << 4
5. Physical Address Formula

Physical Address = (Segment × 16) + Offset

or

Physical Address = (Segment << 4) + Offset

6. Example

Given:

Segment = 1000H

Offset = 0020H

Step 1: Shift Segment

1000H × 16 = 10000H

Step 2: Add Offset

10000H + 0020H = 10020H

Final:

Physical Address = 10020H

7. Algorithm (Easy Steps)

1. Take segment address from user.

2. Take offset address from user.

3. Shift segment address left by 4 bits.

4. Add offset value.

5. Display physical address.

8. C Program Explanation

Header File

#include<stdio.h>

Used for:

• printf()
• scanf()

Variables

unsigned int segment, offset, physicalAddress;

Stores:

• Segment address

• Offset address

• Final physical address

Taking Input

scanf("%x",&segment);

Reads hexadecimal value.

Example:

1000

Address Calculation

physicalAddress = (segment << 4) + offset;

Steps:

1. Shift segment by 4 bits.

2. Add offset.

3. Store result.

Display Result

printf("%X", physicalAddress);

Displays the physical address in hexadecimal.

9. Program Flow

Start

Enter Segment Address

Enter Offset Address

Shift Segment Left by 4 bits

Add Offset

Display Physical Address

End

10. Compile and Run in Ubuntu

Create file:

nano lab10.c
Compile:

gcc lab10.c -o lab10

Run:

./lab10

11. Sample Input

Enter Segment Address (hex): 1000

Enter Offset Address (hex): 0020

12. Sample Output

Physical Address: 10020

Q1: What is a logical address?

Answer:
An address generated by CPU during program execution. It is also called a virtual
address.

Q2: What is a physical address?

Answer:
The actual address location in RAM where data is stored.

Q3: What is the formula for physical address?

Answer:

Physical Address = (Segment × 16) + Offset

Q4: Why do we shift segment by 4 bits?


Answer:
Because 8086 converts a 16-bit segment value into a 20-bit physical address by
multiplying it by 16.

Q5: What is an offset?

Answer:
Offset is the distance from the beginning of a segment that identifies the exact memory
location.

Logical Address = Segment + Offset

Physical Address = Segment × 16 + Offset

Segment Shift Left 4 Bits → Add Offset → Physical Address

Lab 11: Calculating Paging Parameters in C

Objective

To understand paging in Operating Systems and calculate:

• Number of pages

• Page table size

using a C program.

Short Theory

Paging is a memory management technique where:

• Logical memory is divided into small fixed-size blocks called pages.

• Physical memory is divided into blocks called frames.

• Pages are stored in frames for faster memory management.

Formula:

Number of Pages = Logical Memory Size ÷ Page Size

Page Table Size = Number of Pages × 4 bytes


(Assuming each page table entry takes 4 bytes)

Algorithm (Steps)

1. Start the program.

2. Enter logical memory size.

3. Enter page size.

4. Calculate number of pages:

5. Number of Pages = Logical Memory / Page Size

6. Calculate page table size:

7. Page Table Size = Number of Pages × 4

8. Display the results.

9. End the program.

C Program

#include <stdio.h>

int main() {

int logicalMemory, pageSize;

int numberOfPages, pageTableSize;

printf("Enter Logical Memory Size (in KB): ");

scanf("%d", &logicalMemory);

printf("Enter Page Size (in KB): ");

scanf("%d", &pageSize);

numberOfPages = logicalMemory / pageSize;


pageTableSize = numberOfPages * 4;

printf("Number of Pages: %d\n", numberOfPages);

printf("Page Table Size: %d bytes\n", pageTableSize);

return 0;

Simple Code Explanation

Code Meaning

#include <stdio.h> Allows use of input/output functions

int logicalMemory Stores memory size

int pageSize Stores page size

scanf() Takes input from user

numberOfPages = logicalMemory / pageSize Calculates total pages

pageTableSize = numberOfPages * 4 Calculates page table size

printf() Displays output

return 0 Ends program

Example

Input:

Enter Logical Memory Size (in KB): 64

Enter Page Size (in KB): 4

Calculation:

Number of Pages = 64 / 4

= 16
Page Table Size = 16 × 4

= 64 bytes

Output:

Number of Pages: 16

Page Table Size: 64 bytes

Steps to Run in Ubuntu

1. Open Terminal.

2. Create a file:

nano lab11.c

3. Write/paste the program.

4. Save the file.

5. Compile:

gcc lab11.c -o lab11

6. Run:

./lab11

Paging = Divide Memory into Pages

• Memory ÷ Page Size = Number of Pages

• Pages × 4 = Page Table Size


Lab 12: Demand Paging Effective Access Time (EAT)

Objective

To understand Demand Paging and calculate Effective Access Time (EAT) using a C
program.

Short Theory

What is Virtual Memory?

Virtual memory is a technique that allows a computer to use secondary storage (hard
disk/SSD) as an extension of RAM.

What is Paging?

Paging is a memory management technique where:

• Logical memory is divided into pages.

• Physical memory is divided into frames.

• A page table maps pages to frames.

What is Demand Paging?

Demand Paging loads a page into RAM only when it is needed.

If a required page is not available in RAM, a page fault occurs.

Page Fault

A page fault happens when the CPU tries to access a page that is not currently in main
memory.

When a page fault occurs:

1. Operating system finds the page on disk.

2. Loads the page into RAM.

3. Restarts the instruction.

Effective Access Time (EAT)

Effective Access Time is the average time required to access memory considering:

• Normal memory access time.


• Page fault handling time.

Formula used:

EAT = 100(1-p) + (pfo + 2ro + dirty*pst + dirty*2*pst) × p

Where:

Term Meaning

p Page fault rate

pfo Page fault overhead

pst Page swap time

dirty Probability of dirty page

ro Restart overhead

eat Effective Access Time

Algorithm (Steps)

1. Start the program.

2. Enter page fault rate.

3. Enter page fault overhead.

4. Enter page swap time.

5. Enter dirty page percentage.

6. Enter restart overhead time.

7. Apply EAT formula.

8. Display Effective Access Time.

9. End program.

C Program

#include <stdio.h>

#include <stdlib.h>
int main()

double p, pfo, pst, dirty, ro, eat;

printf("Calculating Effective Access Time for Demand Paging\n");

printf("Enter Page Fault Rate (%): ");

scanf("%lf", &p);

p = p / 100;

printf("Enter Page Fault Overhead: ");

scanf("%lf", &pfo);

printf("Enter Page Swap Time: ");

scanf("%lf", &pst);

printf("Enter Dirty Page Percentage (%): ");

scanf("%lf", &dirty);

dirty = dirty / 100;

printf("Enter Restart Overhead Time: ");

scanf("%lf", &ro);

eat = 100*(1-p) +

(pfo + 2*ro + (dirty*pst) + (dirty*2*pst)) * p;


printf("\nEffective Access Time = %lf\n", eat);

return 0;

Simple Code Explanation

Code Purpose

#include<stdio.h> Allows input/output functions

double variables Stores decimal values

scanf() Takes input from user

p = p/100 Converts percentage into decimal

dirty = dirty/100 Converts dirty percentage

eat = formula Calculates Effective Access Time

printf() Displays result

return 0 Ends program

Example

Input:

Page Fault Rate: 10

Page Fault Overhead: 50

Page Swap Time: 1000

Dirty Page Percentage: 20

Restart Overhead Time: 5

Output:

Effective Access Time = calculated value

Steps to Run in Ubuntu


1. Create file

nano lab12.c

2. Compile program

gcc lab12.c -o lab12

3. Run program

./lab12

Demand Paging:

• Page needed → Load into RAM.

• Page missing → Page Fault.

• More page faults = slower system.

EAT = Normal Access Time + Page Fault Cost

Lab 13: LRU (Least Recently Used) Page Replacement Algorithm

Objective

To implement the LRU Page Replacement Algorithm in C and calculate the number of
page faults.

Short Theory

What is Page Replacement?

When a page fault occurs and memory is full, the operating system removes an existing
page and loads the required page.

What is LRU Algorithm?

LRU (Least Recently Used) replaces the page that has not been used for the longest
time.

Simple idea:

The page that was not used recently is most likely not needed soon.

Example:
• Page used recently → Keep it.

• Page not used for a long time → Replace it.

Why LRU is Used?

• Reduces page faults.

• Improves memory performance.

• Uses past usage information to predict future needs.

Algorithm (Steps)

1. Start the program.

2. Enter number of memory frames.

3. Enter number of pages in reference string.

4. Enter the page reference string.

5. Check each page:

o If page already exists → update its recent usage time.

o If empty frame exists → insert page.

o If memory is full → replace the least recently used page.

6. Count page faults.

7. Display total page faults.

8. End program.

C Program

#include <stdio.h>

int findLRU(int time[], int n)

int i, minimum = time[0], pos = 0;


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

if(time[i] < minimum)

minimum = time[i];

pos = i;

return pos;

int main()

int frames[10], pages[30];

int no_of_frames, no_of_pages;

int time[10], counter = 0;

int flag1, flag2;

int i, j, pos;

int faults = 0;

printf("Enter number of frames: ");

scanf("%d", &no_of_frames);

printf("Enter number of pages: ");


scanf("%d", &no_of_pages);

printf("Enter reference string: ");

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

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

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

frames[i] = -1;

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

flag1 = flag2 = 0;

for(j = 0; j < no_of_frames; j++)

if(frames[j] == pages[i])

counter++;

time[j] = counter;
flag1 = flag2 = 1;

break;

if(flag1 == 0)

for(j = 0; j < no_of_frames; j++)

if(frames[j] == -1)

counter++;

faults++;

frames[j] = pages[i];

time[j] = counter;

flag2 = 1;

break;

if(flag2 == 0)

pos = findLRU(time, no_of_frames);


counter++;

faults++;

frames[pos] = pages[i];

time[pos] = counter;

printf("\n");

for(j = 0; j < no_of_frames; j++)

printf("%d\t", frames[j]);

printf("\n\nTotal Page Faults = %d", faults);

return 0;

Simple Code Explanation

Code Meaning

frames[] Stores pages currently in memory


Code Meaning

pages[] Stores page reference string

time[] Stores last used time of pages

findLRU() Finds the page used least recently

counter Keeps track of page usage time

faults Counts page faults

frames[i] = -1 Shows empty memory frame

faults++ Increases page fault count

Example

Input:

Enter number of frames: 3

Enter number of pages: 5

Enter reference string:

12314

Output:

1 -1 -1

1 2 -1

1 2 3

1 2 3

1 4 3

Total Page Faults = 4

Steps to Run in Ubuntu


1. Create file:

nano lab13.c

2. Compile:

gcc lab13.c -o lab13

3. Run:

./lab13

LRU = Remove the page that was used Least Recently

Steps:

1. Check page.

2. If present → update time.

3. If absent → replace oldest page.

4. Count page faults.

LAB 14: Demand Paging and Program Structure in C

Objective

To understand how program structure affects Demand Paging performance by


comparing row-major and column-major access of 2D arrays in C.

1. Theory (Short)

Demand Paging

• Demand Paging loads a page into RAM only when it is needed.

• If a required page is not in memory, a page fault occurs.

• The operating system loads that page from disk into RAM.

Page Fault

• A page fault happens when a program accesses a page that is not currently in
memory.

• More page faults mean slower performance.


2. Program Structure and Paging

The way a program accesses memory affects page faults.

Row-Major Order

• C stores 2D arrays in row-major order.

• Elements of the same row are stored together in memory.

• Accessing rows sequentially causes fewer page faults.

• Faster execution.

Example:

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

for(j=0;j<columns;j++)

A[i][j]=0;

Column-Major Order

• Accessing columns first does not follow C memory layout.

• Memory access becomes scattered.

• Causes more page faults.

• Slower execution.

Example:

for(j=0;j<columns;j++)

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

A[i][j]=0;

3. Algorithm (Easy Steps)

1. Start program.
2. Create a 2D array.

3. Initialize array using column-major order.

4. Observe more page faults.

5. Create another 2D array.

6. Initialize array using row-major order.

7. Observe fewer page faults.

8. End program.

4. C Program

#include<stdio.h>

#include<stdlib.h>

int main()

printf("Demand Paging Performance Demo");

int A[1024][1024];

// Column-major order

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

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

A[i][j]=0;

printf("\nColumn-major order completed");


int B[1024][1024];

// Row-major order

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

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

B[i][j]=0;

printf("\nRow-major order completed");

return 0;

5. Code Explanation (Short)

Header Files

#include<stdio.h>

#include<stdlib.h>

Used for input/output functions.

Array Declaration

int A[1024][1024];

Creates a matrix of size 1024 × 1024.

Column-Major Access
for(j=0;j<1024;j++)

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

• Column is accessed first.

• Memory locations are not continuous.

• More page faults occur.

Row-Major Access

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

for(j=0;j<1024;j++)

• Row is accessed first.

• Matches C memory storage.

• Fewer page faults occur.

6. Compile and Run

Save file:

lab14.c

Compile:

gcc lab14.c -o lab14

Run:

./lab14

7. Output

Demand Paging Performance Demo

Column-major order completed


Row-major order completed

8. Conclusion

• Demand Paging loads pages when required.

• Program memory access pattern affects performance.

• Row-major order is faster because it causes fewer page faults.

• Column-major order causes more page faults and reduces performance.

Q1. What is Demand Paging?


Loading pages into memory only when required.

Q2. What is a page fault?


A page fault occurs when a required page is not present in RAM.

Q3. Which order is faster in C?


Row-major order.

Q4. Why is row-major faster?


Because C stores arrays row by row, so memory access is continuous.

Q5. What causes more page faults?


Column-major access.

LAB 15: Calculating Bit Map Overhead in Disk Free-Space Management (C)

Objective

To calculate the storage overhead required for a Bit Map (Bit Vector) method used in
disk free-space management.

1. Theory (Short)

Disk Free-Space Management

• The operating system keeps track of free and allocated disk blocks.

• It helps in efficient storage allocation.


Bit Map Method

• Each disk block is represented by 1 bit.

• 1 → Free block

• 0 → Allocated block

Example:

101001

Means some blocks are free and some are allocated.

2. Bit Map Overhead

The space required to store the bit map itself is called overhead.

Formula:

Number of Blocks:

Disk Size / Block Size

Bit Map Size:

(Number of Blocks × 1 bit)

Convert bits into KB:

Overhead = (Disk Size / Block Size) / (8 × 1024)

3. Algorithm (Easy Steps)

1. Start program.

2. Take block size from user.

3. Take disk size from user.

4. Convert disk size from GB to KB.

5. Calculate total number of blocks.

6. Calculate bit map overhead.

7. Display overhead in KB.

8. End program.
4. C Program

#include<stdio.h>

#include<stdlib.h>

int main()

double blockSize, diskSize, overhead;

printf("Calculating Bit Map Overhead\n");

printf("Enter block size (in KB): ");

scanf("%lf",&blockSize);

printf("Enter disk size (in GB): ");

scanf("%lf",&diskSize);

// Convert GB to KB

diskSize = diskSize * 1024 * 1024;

// Calculate overhead

overhead = (diskSize / blockSize) / (8 * 1024);

printf("Total Overhead (in KB): %lf", overhead);

return 0;

5. Code Explanation (Short)


Header Files

#include<stdio.h>

#include<stdlib.h>

• stdio.h → used for printf() and scanf().

• stdlib.h → used for system functions.

Variables

double blockSize, diskSize, overhead;

• blockSize → size of one disk block.

• diskSize → total disk capacity.

• overhead → bit map storage size.

Input

scanf("%lf",&blockSize);

scanf("%lf",&diskSize);

Takes block size and disk size from the user.

Unit Conversion

diskSize = diskSize * 1024 * 1024;

Converts:

GB → KB

Because:

1 GB = 1024 × 1024 KB

Overhead Calculation

overhead = (diskSize / blockSize) / (8*1024);

Steps:

1. Find total number of blocks:


Disk Size / Block Size

2. Each block requires 1 bit.

3. Convert bits → bytes:

Divide by 8

4. Convert bytes → KB:

Divide by 1024

6. Sample Input

Enter block size (in KB): 4

Enter disk size (in GB): 100

7. Sample Output

Total Overhead (in KB): 3.125000

8. Compile and Run

Save file:

lab15.c

Compile:

gcc lab15.c -o lab15

Run:

./lab15

9. Conclusion

• Bit Map is used to manage free disk space.

• Each disk block requires only 1 bit.

• The overhead is the memory required to store this bit map.

• Bit Map provides fast and efficient disk space management.


Q1. What is Bit Map?
A method to represent free and allocated disk blocks using bits.

Q2. What does bit 1 represent?


Free block.

Q3. What does bit 0 represent?


Allocated block.

Q4. Why is Bit Map efficient?


Because it quickly finds free blocks and requires less storage.

Q5. What is Bit Map overhead?


The space required to store the bit map itself.

LAB 16: Disk Space Management Simulation in C

Objective

To simulate disk space allocation and deallocation using a C program.

1. Theory (Short)

Disk Space Management

• The operating system manages free and used disk blocks.

• When a file is created, blocks are allocated.

• When a file is deleted, blocks are released.

Contiguous Allocation

• A file is stored in continuous disk blocks.

• It provides fast access.

• It requires finding consecutive free blocks.

Example:

Disk Blocks:
0001100

0 = Free Block

1 = Allocated Block

2. Program Working

The program uses an array to represent the disk.

• Array element = Disk block

• 0 = Free block

• 1 = Allocated block

Operations:

1. Allocate space for a file.

2. Find consecutive free blocks.

3. Mark blocks as allocated.

4. Delete a file.

5. Mark blocks as free.

3. Algorithm (Easy Steps)

Allocation:

1. Start scanning disk blocks.

2. Find continuous free blocks.

3. If required space is found:

o Mark blocks as 1.

o Display allocation message.

4. Otherwise display error.

Deallocation:

1. Take starting block and file size.


2. Change allocated blocks back to 0.

3. Display deallocation message.

4. C Program

#include <stdio.h>

#define TOTAL_BLOCKS 100

int disk[TOTAL_BLOCKS] = {0};

// Allocate disk space

void allocateSpaceForFile(int fileSize)

int startBlock = -1;

int count = 0;

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

if(disk[i] == 0)

if(startBlock == -1)

startBlock = i;

count++;

if(count == fileSize)

{
for(int j=startBlock; j<startBlock+fileSize; j++)

disk[j] = 1;

printf("File allocated from block %d\n", startBlock);

return;

else

startBlock = -1;

count = 0;

printf("Not enough space available\n");

// Deallocate disk space

void deallocateSpaceForFile(int startBlock, int fileSize)

for(int i=startBlock; i<startBlock+fileSize; i++)

disk[i] = 0;

printf("File deleted from block %d\n", startBlock);

}
int main()

allocateSpaceForFile(20);

allocateSpaceForFile(30);

deallocateSpaceForFile(0,20);

allocateSpaceForFile(10);

return 0;

5. Code Explanation (Short)

Header File

#include<stdio.h>

Used for printf().

Disk Creation

int disk[TOTAL_BLOCKS]={0};

Creates 100 disk blocks.

Initially all blocks are free.

Allocation Function

void allocateSpaceForFile(int fileSize)

Allocates continuous blocks for a file.

Variables:

startBlock
Stores the first free block.

count

Counts consecutive free blocks.

Searching Free Space

if(disk[i]==0)

Checks whether the block is free.

Allocating Blocks

disk[j]=1;

Marks blocks as occupied.

Deallocation Function

void deallocateSpaceForFile()

Releases file space.

disk[i]=0;

Marks blocks as free again.

Main Function

allocateSpaceForFile(20);

Creates a 20-block file.

allocateSpaceForFile(30);

Creates a 30-block file.

deallocateSpaceForFile(0,20);

Deletes the first file.

allocateSpaceForFile(10);

Uses freed space for a new file.


6. Sample Output

File allocated from block 0

File allocated from block 20

File deleted from block 0

File allocated from block 0

7. Compile and Run

Save file:

lab16.c

Compile:

gcc lab16.c -o lab16

Run:

./lab16

8. Conclusion

• Disk space management keeps track of free and allocated blocks.

• Contiguous allocation stores files in consecutive blocks.

• Allocation marks blocks as 1.

• Deallocation changes blocks back to 0.

• This simulation helps understand how operating systems manage storage.

Q1. What is disk space management?


It is the process of managing free and used disk blocks.

Q2. What is contiguous allocation?


A method where a file is stored in consecutive disk blocks.
Q3. What does 0 represent in the program?
Free block.

Q4. What does 1 represent in the program?


Allocated block.

Q5. What is the disadvantage of contiguous allocation?


It may cause external fragmentation because continuous free space is required.

You might also like