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

OS lab manual 2025

The document outlines the hardware and software requirements for various operating systems including UNIX, Linux, Windows XP, and Windows 7/8. It also details the execution of UNIX system calls for process management, file management, and input/output operations, along with implementations of CPU scheduling policies such as FCFS, SJF, Priority, and Multi-level Queue. Each section includes code examples demonstrating the respective functionalities and algorithms.

Uploaded by

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

OS lab manual 2025

The document outlines the hardware and software requirements for various operating systems including UNIX, Linux, Windows XP, and Windows 7/8. It also details the execution of UNIX system calls for process management, file management, and input/output operations, along with implementations of CPU scheduling policies such as FCFS, SJF, Priority, and Multi-level Queue. Each section includes code examples demonstrating the respective functionalities and algorithms.

Uploaded by

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

Experiment No.

– 1
Study of hardware and software requirements of different operating systems
(UNIX,LINUX,WINDOWS XP, WINDOWS7/8

1. UNIX: Hardware Requirements

 Processor: Minimum of 1 GHz processor


 Memory (RAM): Minimum of 1 GB RAM
 Hard Disk Space: Minimum of 10 GB free disk space
Software Requirements

 UNIX-compatible operating system, such as Sun Solaris, IBM AIX, HP-UX, etc.
 Compiler and development tools (optional)
 X Window System for graphical user interface (optional)
 Networking tools for network communication (optional)

2. Linux: Hardware Requirements:


 Processor: Minimum of 1 GHz processor
 Memory (RAM): Minimum of 1 GB RAM (2 GB or more recommended for better
performance)
 Hard Disk Space: Minimum of 10 GB free disk space (20 GB or more recommended for
better performance)
Software Requirements

 Linux distribution, such as Ubuntu, Fedora, CentOS, Debian, etc.


 Graphical user interface (optional)
 Compiler and development tools (optional)
 Networking tools for network communication (optional)
3. Windows XP: Hardware Requirements:
 Processor: Minimum of Pentium 233 MHz processor (300 MHz or higher recommended)
 Memory (RAM): Minimum of 64 MB RAM (128 MB or higher recommended)
 Hard Disk Space: Minimum of 1.5 GB free disk space
Software Requirements:

 Windows XP operating system


 DirectX 9 graphics device with WDDM driver (optional for graphical user interface)
 Networking tools for network communication (optional)
4. Windows 7/8: Hardware Requirements:
 Processor: Minimum of 1 GHz processor (1 GHz or higher recommended)
 Memory (RAM): Minimum of 1 GB RAM (2 GB or higher recommended)
 Hard Disk Space: Minimum of 16 GB free disk space (20 GB or higher recommended)
Software Requirements:

 Windows 7 or Windows 8 operating system


 DirectX 9 graphics device with WDDM 1.0 or higher driver (optional for graphical user
interface)
 Networking tools for network communication (optional)

Experiment No. – 2
Execute various UNIX system calls for
i. Process management
ii. File management
iii. Input/output Systems calls

i. Process Management

1. fork(): Used to create a new process by duplicating the current process.


2. exec(): Replaces the current process image with a new process image.
3. wait(): Makes a parent process wait until all its child processes have terminated.
4. exit(): Terminates a process and returns an exit status to the parent process.
5. kill(): Sends a signal (e.g., terminate, interrupt) to a process.

#include <stdio.h>

#include <unistd.h> ----------- for fork() and sleep() function

#include <sys/types.h>

int main() {

pid_t pid;

// Create a new process

pid = fork();

if (pid < 0) {

// Error occurred during fork

perror("Fork failed");

return 1;

} else if (pid == 0) {
// Child process

printf("Hello! I am the child process. My PID is %d\n", getpid());

} else {

// Parent process

printf("Hello! I am the parent process. My PID is %d, and my child's PID is %d\n",
getpid(), pid);

return 0;

ii. File Management

1. open(): Opens a file and returns a file descriptor.


2. read(): Reads data from a file associated with a given file descriptor.
3. write(): Writes data to a file using a file descriptor.
4. close(): Closes an open file descriptor.
5. unlink(): Deletes a file.

#include <stdio.h>

#include <stdlib.h>

// Function to write data to a file

void writeToFile(const char *filename)

FILE *file = fopen(filename, "w"); // Open the file in write mode

if (file == NULL) {

printf("Could not open file for writing\n");

return;}

fprintf(file, "Hello, this is a test file!\n");

fprintf(file, "We are testing file management in C.\n");

fclose(file); // Close the file

printf("Data written to file successfully.\n");

}
// Function to read data from a file

void readFromFile(const char *filename) {

FILE *file = fopen(filename, "r"); // Open the file in read mode

if (file == NULL) {

printf("Could not open file for reading\n");

return;

char ch;

printf("Contents of the file:\n");

while ((ch = fgetc(file)) != EOF) {

putchar(ch); // Print the file contents to the console

fclose(file); // Close the file}

// Function to append data to a file

void appendToFile(const char *filename) {

FILE *file = fopen(filename, "a"); // Open the file in append mode

if (file == NULL) {

printf("Could not open file for appending\n");

return;

fprintf(file, "Appending this new line to the file.\n");

fclose(file); // Close the file

printf("Data appended to file successfully.\n");

}
int main() {

const char *filename = "testfile.txt";

// Writing to a file

writeToFile(filename);

// Reading from the file

readFromFile(filename);

// Appending to the file

appendToFile(filename);

// Reading from the file after appending

readFromFile(filename);

return 0;}

iii. Input/Output System Calls

1. read(): Reads data from a file or input device into a buffer.


2. write(): Writes data from a buffer to a file or output device.
3. lseek(): Moves the file offset pointer to a specified location (useful for random
access).
4. ioctl(): Performs device-specific input/output operations.
5. dup(): Duplicates an existing file descriptor
6. #include <fcntl.h> // For open() flags
7. #include <unistd.h> // For read(), write(), close()
8. #include <stdio.h> // For perror()
9. #include <stdlib.h> // For exit()
10.
11. #define BUFFER_SIZE 1024
12.
13. // Function to read from a file and write to another file using system calls
14. void fileCopyUsingSysCalls(const char *source, const char *destination) {
15. int sourceFile, destFile, bytesRead, bytesWritten;
16. char buffer[BUFFER_SIZE];
17.
18. // Open the source file in read-only mode
19. sourceFile = open(source, O_RDONLY);
20. if (sourceFile == -1) {
21. perror("Error opening source file");
22. exit(1);
23. }
24.
25. // Open the destination file in write-only mode. Create the file if it doesn't exist.
26. destFile = open(destination, O_WRONLY | O_CREAT | O_TRUNC, 0644);
27. if (destFile == -1) {
28. perror("Error opening destination file");
29. close(sourceFile);
30. exit(1);
31. }
32.
33. // Read from the source file and write to the destination file
34. while ((bytesRead = read(sourceFile, buffer, BUFFER_SIZE)) > 0) {
35. bytesWritten = write(destFile, buffer, bytesRead);
36. if (bytesWritten != bytesRead) {
37. perror("Error writing to destination file");
38. close(sourceFile);
39. close(destFile);
40. exit(1);
41. }
42. }
43.
44. if (bytesRead == -1) {
45. perror("Error reading from source file");
46. }
47.
48. // Close both files
49. close(sourceFile);
50. close(destFile);
51.
52. printf("File copied successfully using system calls.\n");
53. }
54.
55. int main() {
56. const char *sourceFile = "source.txt";
57. const char *destinationFile = "destination.txt";
58.
59. // Copy content from source file to destination file
60. fileCopyUsingSysCalls(sourceFile, destinationFile);
61.
62. return 0;

Experiment No. – 3

Implement CPU Scheduling Policies:

i. SJF
ii. Priority
iii. FCFS
iv. Multi-level Queue

1. First-Come-First-Serve (FCFS):

In FCFS, the process that arrives first gets executed first.

FCFS Algorithm:

c
Copy
#include <stdio.h>

typedef struct {
int pid; // Process ID
int arrivalTime;
int burstTime;
int waitingTime;
int turnaroundTime;
} Process;

void findWaitingTime(Process proc[], int n) {


proc[0].waitingTime = 0;
for (int i = 1; i < n; i++) {
proc[i].waitingTime = proc[i - 1].waitingTime + proc[i - 1].burstTime;
}
}

void findTurnaroundTime(Process proc[], int n) {


for (int i = 0; i < n; i++) {
proc[i].turnaroundTime = proc[i].burstTime + proc[i].waitingTime;
}
}

void findAvgTimes(Process proc[], int n) {


int totalWaitingTime = 0, totalTurnaroundTime = 0;

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


totalWaitingTime += proc[i].waitingTime;
totalTurnaroundTime += proc[i].turnaroundTime;
}

printf("Average waiting time: %.2f\n", (float)totalWaitingTime / n);


printf("Average turnaround time: %.2f\n", (float)totalTurnaroundTime / n);
}

void FCFS(Process proc[], int n) {


findWaitingTime(proc, n);
findTurnaroundTime(proc, n);
findAvgTimes(proc, n);
}

int main() {
Process proc[] = {
{1, 0, 5, 0, 0},
{2, 1, 3, 0, 0},
{3, 2, 8, 0, 0},
{4, 3, 6, 0, 0}
};
int n = sizeof(proc) / sizeof(proc[0]);

FCFS(proc, n);

return 0;
}

2. Shortest Job First (SJF):

In SJF, the process with the shortest burst time is executed first.

SJF Algorithm (Non-preemptive):

c
Copy
#include <stdio.h>
#include <stdlib.h>

typedef struct {
int pid; // Process ID
int burstTime;
int waitingTime;
int turnaroundTime;
} Process;

int compare(const void *a, const void *b) {


return ((Process*)a)->burstTime - ((Process*)b)->burstTime;
}

void findWaitingTime(Process proc[], int n) {


proc[0].waitingTime = 0;
for (int i = 1; i < n; i++) {
proc[i].waitingTime = proc[i - 1].waitingTime + proc[i - 1].burstTime;
}
}

void findTurnaroundTime(Process proc[], int n) {


for (int i = 0; i < n; i++) {
proc[i].turnaroundTime = proc[i].burstTime + proc[i].waitingTime;
}
}
void findAvgTimes(Process proc[], int n) {
int totalWaitingTime = 0, totalTurnaroundTime = 0;

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


totalWaitingTime += proc[i].waitingTime;
totalTurnaroundTime += proc[i].turnaroundTime;
}

printf("Average waiting time: %.2f\n", (float)totalWaitingTime / n);


printf("Average turnaround time: %.2f\n", (float)totalTurnaroundTime / n);
}

void SJF(Process proc[], int n) {


qsort(proc, n, sizeof(Process), compare); // Sort by burst time
findWaitingTime(proc, n);
findTurnaroundTime(proc, n);
findAvgTimes(proc, n);
}

int main() {
Process proc[] = {
{1, 6, 0, 0},
{2, 8, 0, 0},
{3, 7, 0, 0},
{4, 3, 0, 0}
};
int n = sizeof(proc) / sizeof(proc[0]);

SJF(proc, n);

return 0;
}

3. Priority Scheduling:

In Priority Scheduling, each process has a priority. The process with the highest priority
(lowest priority number) gets executed first.

Priority Scheduling Algorithm:

c
Copy
#include <stdio.h>

typedef struct {
int pid; // Process ID
int priority;
int burstTime;
int waitingTime;
int turnaroundTime;
} Process;

int compare(const void *a, const void *b) {


return ((Process*)a)->priority - ((Process*)b)->priority;
}

void findWaitingTime(Process proc[], int n) {


proc[0].waitingTime = 0;
for (int i = 1; i < n; i++) {
proc[i].waitingTime = proc[i - 1].waitingTime + proc[i - 1].burstTime;
}
}

void findTurnaroundTime(Process proc[], int n) {


for (int i = 0; i < n; i++) {
proc[i].turnaroundTime = proc[i].burstTime + proc[i].waitingTime;
}
}

void findAvgTimes(Process proc[], int n) {


int totalWaitingTime = 0, totalTurnaroundTime = 0;

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


totalWaitingTime += proc[i].waitingTime;
totalTurnaroundTime += proc[i].turnaroundTime;
}

printf("Average waiting time: %.2f\n", (float)totalWaitingTime / n);


printf("Average turnaround time: %.2f\n", (float)totalTurnaroundTime / n);
}

void PriorityScheduling(Process proc[], int n) {


qsort(proc, n, sizeof(Process), compare); // Sort by priority
findWaitingTime(proc, n);
findTurnaroundTime(proc, n);
findAvgTimes(proc, n);
}

int main() {
Process proc[] = {
{1, 2, 6, 0, 0},
{2, 1, 8, 0, 0},
{3, 4, 7, 0, 0},
{4, 3, 3, 0, 0}
};
int n = sizeof(proc) / sizeof(proc[0]);

PriorityScheduling(proc, n);

return 0;
}

4. Multi-level Queue (MLQ) Scheduling:

In Multi-Level Queue Scheduling, there are multiple queues, each with a different priority.
Processes are assigned to different queues based on their priority.

MLQ Algorithm:

c
Copy
#include <stdio.h>

#define HIGH_QUEUE 0
#define LOW_QUEUE 1

typedef struct {
int pid;
int burstTime;
int priority;
} Process;

void scheduleQueue(Process proc[], int n, int queueType) {


printf("Processing Queue %d\n", queueType);
for (int i = 0; i < n; i++) {
if ((queueType == HIGH_QUEUE && proc[i].priority == 1) || (queueType ==
LOW_QUEUE && proc[i].priority == 2)) {
printf("Process %d (Priority: %d, Burst Time: %d)\n", proc[i].pid, proc[i].priority,
proc[i].burstTime);
}
}
}

void MLQ(Process proc[], int n) {


printf("High Priority Queue:\n");
scheduleQueue(proc, n, HIGH_QUEUE);

printf("\nLow Priority Queue:\n");


scheduleQueue(proc, n, LOW_QUEUE);
}

int main() {
Process proc[] = {
{1, 6, 1}, // High priority
{2, 8, 2}, // Low priority
{3, 5, 1}, // High priority
{4, 3, 2} // Low priority
};
int n = sizeof(proc) / sizeof(proc[0]);
MLQ(proc, n);

return 0;
}

Experiment No. – 4

Implement file storage allocation technique:

i. Contiguous(using array)
ii. Linked –list(using linked-list)
iii. Indirect allocation (indexing)

1. Contiguous Allocation (using an array)

In contiguous allocation, files are stored in contiguous blocks on the disk. We can represent this
using an array where each index represents a block on the disk.

#include <stdio.h>
#include <string.h>

#define MAX_BLOCKS 100 // Maximum number of blocks

typedef struct {
int blockNumber; // Block number on the disk
char data[50]; // Data stored in the block
} Block;

typedef struct {
int size; // Size of the file in blocks
int startBlock; // Starting block of the file
int blocks[MAX_BLOCKS]; // Array of block numbers allocated to the file
} File;

// Initialize the disk with free blocks


Block disk[MAX_BLOCKS];

// Function to allocate blocks contiguously


int allocateContiguously(File *file, int size) {
int freeBlocks = 0;

// Find contiguous free blocks


for (int i = 0; i < MAX_BLOCKS; i++) {
if (disk[i].blockNumber == 0) { // Block is free
freeBlocks++;
} else {
freeBlocks = 0;
}

if (freeBlocks == size) { // Found enough free blocks


file->startBlock = i - size + 1;
for (int j = 0; j < size; j++) {
disk[file->startBlock + j].blockNumber = 1; // Mark as allocated
file->blocks[j] = file->startBlock + j;
}
file->size = size;
return 1; // Allocation successful
}
}
return 0; // Allocation failed
}

void displayFileDetails(File file) {


printf("File Size: %d blocks\n", file.size);
printf("Start Block: %d\n", file.startBlock);
printf("Allocated Blocks: ");
for (int i = 0; i < file.size; i++) {
printf("%d ", file.blocks[i]);
}
printf("\n");
}

int main() {
File file1;
memset(disk, 0, sizeof(disk)); // Initialize all disk blocks as free

if (allocateContiguously(&file1, 5)) {
printf("Contiguous Allocation Successful!\n");
displayFileDetails(file1);
} else {
printf("Contiguous Allocation Failed!\n");
}

return 0;
}

2. Linked List Allocation (using linked list)

In linked list allocation, each block contains a pointer to the next block, and the file is stored in non-
contiguous blocks. This is implemented using a linked list, where each node represents a disk block.

#include <stdio.h>
#include <stdlib.h>

#define MAX_BLOCKS 100 // Maximum number of blocks

typedef struct Block {


int blockNumber; // Block number on the disk
char data[50]; // Data stored in the block
struct Block* next; // Pointer to the next block in the file
} Block;

typedef struct {
int size; // Size of the file (in blocks)
Block* head; // Head pointer to the first block
} File;

// Initialize the disk with free blocks


Block disk[MAX_BLOCKS];

// Function to allocate blocks using linked list


int allocateLinkedList(File* file, int size) {
Block* prevBlock = NULL;
Block* newBlock = NULL;
file->head = NULL;
file->size = size;

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


newBlock = (Block*)malloc(sizeof(Block));
if (!newBlock) {
return 0; // Memory allocation failed
}

// Find a free block


for (int j = 0; j < MAX_BLOCKS; j++) {
if (disk[j].blockNumber == 0) {
disk[j].blockNumber = 1; // Mark as allocated
newBlock->blockNumber = j;
newBlock->next = NULL;

// Link the new block to the previous one


if (prevBlock == NULL) {
file->head = newBlock;
} else {
prevBlock->next = newBlock;
}
prevBlock = newBlock;
break;
}
}
}
return 1; // Allocation successful
}

void displayFileDetails(File file) {


printf("File Size: %d blocks\n", file.size);
printf("Allocated Blocks: ");
Block* current = file.head;
while (current != NULL) {
printf("%d ", current->blockNumber);
current = current->next;
}
printf("\n");
}

int main() {
File file1;
memset(disk, 0, sizeof(disk)); // Initialize all disk blocks as free

if (allocateLinkedList(&file1, 4)) {
printf("Linked List Allocation Successful!\n");
displayFileDetails(file1);
} else {
printf("Linked List Allocation Failed!\n");
}

return 0;
}
3. Indexed Allocation (using indexing)

In indexed allocation, each file has an index block that contains pointers to the data blocks. We
implement this using an array for the index block.

#include <stdio.h>

#define MAX_BLOCKS 100 // Maximum number of blocks

typedef struct {
int blockNumber; // Block number on the disk
char data[50]; // Data stored in the block
} Block;

typedef struct {
int size; // Size of the file in blocks
int index[MAX_BLOCKS]; // Index block that stores block numbers
} File;

// Initialize the disk with free blocks


Block disk[MAX_BLOCKS];

// Function to allocate blocks using indexed allocation


int allocateIndexed(File* file, int size) {
file->size = size;
for (int i = 0; i < size; i++) {
// Find a free block
for (int j = 0; j < MAX_BLOCKS; j++) {
if (disk[j].blockNumber == 0) {
disk[j].blockNumber = 1; // Mark as allocated
file->index[i] = j; // Store block number in index
break;
}
}
}
return 1; // Allocation successful
}

void displayFileDetails(File file) {


printf("File Size: %d blocks\n", file.size);
printf("Index Block Pointers: ");
for (int i = 0; i < file.size; i++) {
printf("%d ", file.index[i]);
}
printf("\n");
}

int main() {
File file1;
memset(disk, 0, sizeof(disk)); // Initialize all disk blocks as free

if (allocateIndexed(&file1, 6)) {
printf("Indexed Allocation Successful!\n");
displayFileDetails(file1);
} else {
printf("Indexed Allocation Failed!\n");
}

return 0;
}

Experiment No. – 5

Implementation of contiguous allocation techniques:

i. Worst-Fit
ii. Best- Fit
iii. First- Fit

(i) Best Fit Algorithm The best fit deals with allocating the smallest free partition
which meets the requirement of the requesting process. This algorithm first
searches the entire list of free partitions and considers the smallest hole that is
adequate. It then tries to find a hole which is close to actual process size needed.

Algorithm:

1. Input memory blocks and processes with sizes.

2. Initialize all memory blocks as free.

3. Start by picking each process and find the minimum block size that can be assigned to
current process i.e., find min(bockSize[1], blockSize[2],.....blockSize[n]) >
processSize[current], if found then assign it to the current process.

4. If not then leave that process and keep checking the further processes.
(ii) Worst Fit Algorithm Worst Fit allocates a process to the partition which is largest
sufficient among the freely available partitions available in the main memory. If a
large process comes at a later stage, then memory will not have space to
accommodate it.

Algorithm:

1. Input memory blocks and processes with sizes.

2. Initialize all memory blocks as free.

3. Start by picking each process and find the maximum block size that can be assigned to
current process i.e., find max(bockSize[1], blockSize[2],.....blockSize[n]) >
processSize[current], if found then assign it to the current process.

4. If not then leave that process and keep checking the further processes.

(iii) Next Fit algorithm Next fit is a modified version of first fit. It begins as first fit to
find a free partition. When called next time it starts searching from where it left
off, not from the beginning.
Algorithm:

1. Input the number of memory blocks and their sizes and initializes all the blocks as free.

2. Input the number of processes and their sizes.

3. Start by picking each process and check if it can be assigned to the current block, if yes,
allocate it the required memory and check for next process but from the block where we left
not from starting.

4. If the current block size is smaller then keep checking the further blocks. Assignment
Quest

Experiment No. – 6
Calculation of external and internal fragmentation
i. Free space list of blocks from system
ii. List process file from the system
 External Fragmentation refers to the situation where free blocks of memory or disk space
are scattered throughout the system, making it difficult to allocate large contiguous blocks
even though the total free space might be sufficient.
 Internal Fragmentation occurs when allocated memory or disk space is larger than the
required size, leading to unused space within the allocated blocks.
Below is a C program that calculates both internal and external fragmentation using a free
space list and a list of processes (files in this case). The program simulates a disk allocation
system, where free space blocks and allocated blocks are managed to calculate fragmentation.

1. Free Space List of Blocks

We will define a free space list that represents blocks on the disk, where each block can be
free or allocated.

2. List of Processes (Files)

Each process will represent a file, with the size (in blocks) and the blocks allocated to the file.

#include <stdio.h>
#include <stdlib.h>

#define MAX_BLOCKS 100 // Total number of blocks on the disk

// Structure to represent a block


typedef struct {
int blockNumber; // Block number on the disk
int allocated; // 1 if allocated, 0 if free
} Block;

// Structure to represent a file (process) allocated on the disk


typedef struct {
int pid; // Process ID (or File ID)
int size; // Size of the file in blocks
int *allocatedBlocks; // Array of block numbers allocated to this file
} File;

// Disk with blocks


Block disk[MAX_BLOCKS];

// Function to initialize the disk (set all blocks as free)


void initializeDisk() {
for (int i = 0; i < MAX_BLOCKS; i++) {
disk[i].blockNumber = i;
disk[i].allocated = 0; // Mark all blocks as free
}
}

// Function to calculate internal fragmentation for a file


int calculateInternalFragmentation(File *file) {
int internalFrag = 0;

// We assume each file occupies contiguous blocks


int lastBlock = file->allocatedBlocks[file->size - 1];

// If the file uses fewer blocks than required, internal fragmentation occurs
int unusedSpace = (lastBlock + 1) - file->size;

internalFrag = unusedSpace;
return internalFrag;
}

// Function to calculate external fragmentation


int calculateExternalFragmentation() {
int externalFrag = 0;

// External fragmentation is the number of free blocks scattered in the disk


for (int i = 0; i < MAX_BLOCKS; i++) {
if (disk[i].allocated == 0) {
externalFrag++; // Count free blocks
}
}

return externalFrag;
}

// Function to allocate blocks to a file (for simplicity, allocate contiguous blocks)


int allocateFile(File *file) {
int allocatedBlocksCount = 0;

// Try to allocate contiguous blocks on the disk


for (int i = 0; i < MAX_BLOCKS; i++) {
if (disk[i].allocated == 0) { // Block is free
disk[i].allocated = 1; // Mark as allocated
file->allocatedBlocks[allocatedBlocksCount] = i;
allocatedBlocksCount++;

// If all blocks are allocated, return success


if (allocatedBlocksCount == file->size) {
return 1;
}
}
}
return 0; // Failed to allocate enough contiguous blocks
}

// Function to display the free space list


void displayFreeSpaceList() {
printf("\nFree Space List (Block Number): ");
for (int i = 0; i < MAX_BLOCKS; i++) {
if (disk[i].allocated == 0) {
printf("%d ", disk[i].blockNumber);
}
}
printf("\n");
}

// Function to display file details


void displayFileDetails(File *file) {
printf("Process %d (File) Allocation Details:\n", file->pid);
printf("File Size: %d blocks\n", file->size);
printf("Allocated Blocks: ");
for (int i = 0; i < file->size; i++) {
printf("%d ", file->allocatedBlocks[i]);
}
printf("\nInternal Fragmentation: %d blocks\n", calculateInternalFragmentation(file));
}

int main() {
initializeDisk(); // Initialize the disk

// Creating sample files (processes) with sizes


File file1 = {1, 5, (int *)malloc(5 * sizeof(int))}; // File with 5 blocks
File file2 = {2, 3, (int *)malloc(3 * sizeof(int))}; // File with 3 blocks
File file3 = {3, 6, (int *)malloc(6 * sizeof(int))}; // File with 6 blocks

// Allocate space for the files


if (allocateFile(&file1)) {
displayFileDetails(&file1);
} else {
printf("File 1 Allocation Failed\n");
}

if (allocateFile(&file2)) {
displayFileDetails(&file2);
} else {
printf("File 2 Allocation Failed\n");
}

if (allocateFile(&file3)) {
displayFileDetails(&file3);
} else {
printf("File 3 Allocation Failed\n");
}

// Display the free space list


displayFreeSpaceList();

// Calculate and display external fragmentation


printf("\nExternal Fragmentation: %d blocks\n", calculateExternalFragmentation());

// Cleanup allocated memory


free(file1.allocatedBlocks);
free(file2.allocatedBlocks);
free(file3.allocatedBlocks);
return 0;
}
Experiment No. – 7

Implementation of compaction for the continually changing memory layout and


calculate total movement of data

You might also like