0% found this document useful (0 votes)
102 views98 pages

Explore Linux Commands: Experiment No 1

The document describes writing shell scripts to display system information and top processes. It provides commands and system calls to get operating system details, hostname, and display the top 10 CPU intensive processes.

Uploaded by

ibrahimbharde2
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)
102 views98 pages

Explore Linux Commands: Experiment No 1

The document describes writing shell scripts to display system information and top processes. It provides commands and system calls to get operating system details, hostname, and display the top 10 CPU intensive processes.

Uploaded by

ibrahimbharde2
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
You are on page 1/ 98

EXPERIMENT NO 1 - 1.

Explore Linux Commands


Aim: To explore basic Linux commands and system calls for file, directory, and process
management.

Description: In this exercise, you will learn about various Linux commands and system calls
for managing files, directories, and processes.

Commands:

 mkdir: Create a new directory.


 chdir: Change the current directory.
 cat: Concatenate and display file content.
 ls: List directory contents.
 chown: Change file owner and group.
 chmod: Change file mode bits.
 chgrp: Change group ownership.
 ps: Report a snapshot of the current processes.

System Calls:

 open: Open a file or device.


 read: Read from a file or device.
 write: Write to a file or device.
 close: Close a file or device.
 getpid: Return the process ID.
 setpid: Not supported in Linux.
 getuid: Return the real user ID.
 getgid: Return the real group ID.
 getegid: Return the effective group ID.
 geteuid: Return the effective user ID.

Algorithm:

1. Create a new directory using mkdir.


2. Change the current directory using chdir.
3. Display the content of a file using cat.
4. List directory contents using ls.
5. Change file ownership and group using chown and chgrp.
6. Change file mode bits using chmod.
7. Display the process ID using ps.
8. Use system calls open, read, write , and close to read and write to a file.
9. Use system calls getpid, getuid , getgid , getegid , and geteuid to get process and user information.
Code:

Refer to the man pages of each command and system call for usage and examples.

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <sys/wait.h>

#include <time.h>

#define FILENAME "test.txt"

void create_file() {

int fd = open(FILENAME, O_CREAT | O_WRONLY, 0644);

if (fd < 0) {

perror("open");

exit(1);

close(fd);

void write_to_file() {
int fd = open(FILENAME, O_WRONLY);

if (fd < 0) {

perror("open");

exit(1);

char *message = "Hello, world!\n";

if (write(fd, message, strlen(message)) < 0) {

perror("write");

exit(1);

close(fd);

void read_from_file() {

int fd = open(FILENAME, O_RDONLY);

if (fd < 0) {

perror("open");

exit(1);

char buffer[1024];

if (read(fd, buffer, sizeof(buffer)) < 0) {

perror("read");

exit(1);
}

printf("File content: %s\n", buffer);

close(fd);

void change_directory() {

if (chdir("..") < 0) {

perror("chdir");

exit(1);

void list_directory() {

if (system("ls -l") < 0) {

perror("system");

exit(1);

void change_file_owner() {

if (chown(FILENAME, getuid(), getgid()) < 0) {

perror("chown");

exit(1);
}

void change_file_permissions() {

if (chmod(FILENAME, 0777) < 0) {

perror("chmod");

exit(1);

void change_file_group() {

if (chgrp("group", FILENAME) < 0) {

perror("chgrp");

exit(1);

void display_process_info() {

if (system("ps aux") < 0) {

perror("system");

exit(1);

}
void get_process_info() {

printf("PID: %d\n", getpid());

printf("Parent PID: %d\n", getppid());

printf("User ID: %d\n", getuid());

printf("Group ID: %d\n", getgid());

printf("Effective User ID: %d\n", geteuid());

printf("Effective Group ID: %d\n", getegid());

void sort_lines() {

if (system("sort test.txt") < 0) {

perror("system");

exit(1);

void grep_pattern() {

if (system("grep 'Hello' test.txt") < 0) {

perror("system");

exit(1);

}
void awk_script() {

if (system("awk '{print $1}' test.txt") < 0) {

perror("system");

exit(1);

int main() {

create_file();

write_to_file();

read_from_file();

change_directory();

list_directory();

change_file_owner();

change_file_permissions();

change_file_group();

display_process_info();

get_process_info();

sort_

Output:

The output will vary based on the commands and system calls used.

1. Creating a new directory using mkdir:


shell

EditFull ScreenCopy code


1$ mkdir my_directory
2. Changing the current directory using chdir:

shell

EditFull ScreenCopy code


1$ cd my_directory
3. Displaying the content of a file using cat:

shell

EditFull ScreenCopy code


1$ echo "Hello, World!" > my_file.txt
2$ cat my_file.txt
3Hello, World!
4. Listing directory contents using ls:

shell

EditFull ScreenCopy code


1$ ls
2my_file.txt
5. Changing file ownership and group using chown and chgrp:

shell

EditFull ScreenCopy code


1$ chown my_user:my_group my_file.txt
2$ ls -l
3-rw-r--r-- 1 my_user my_group 13 Mar 10 10:00 my_file.txt
6. Changing file mode bits using chmod:

shell

EditFull ScreenCopy code


1$ chmod 755 my_file.txt
2$ ls -l
3-rwxr-xr-x 1 my_user my_group 13 Mar 10 10:00 my_file.txt
7. Displaying the process ID using ps:

shell

EditFull ScreenCopy code


1$ ps
2 PID TTY TIME CMD
3 1234 pts/0 00:00:00 bash
4 5678 pts/0 00:00:00 ps
8. Using system calls open, read, write, and close to read and write to a file:

EditFull ScreenCopy code


1#include <fcntl.h>
2#include <unistd.h>
3#include <stdio.h>
4
5int main() {
6 int fd = open("my_file.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
7 if (fd == -1) {
8 perror("open");
9 return 1;
10 }
11
12 const char *message = "Hello, World!";
13 if (write(fd, message, strlen(message)) == -1) {
14 perror("write");
15 return 1;
16 }
17
18 if (close(fd) == -1) {
19 perror("close");
20 return 1;
21 }
22
23 return 0;
24}
9. Using system calls getpid, getuid, getgid, getegid, and geteuid to get process and
user information:

EditFull ScreenCopy code


1#include <stdio.h>
2#include <unistd.h>
3#include <sys/types.h>
4
5int main() {
6 printf("Process ID: %d\n", getpid());
7 printf("Real User ID: %d\n", getuid());
8 printf("Real Group ID: %d\n", getgid());
9 printf("Effective Group ID: %d\n", getegid());
10 printf("Effective User ID: %d\n", geteuid());
11
12 return 0;
13}
10. Using sort, grep, and awk to filter and process data:

shell
EditFull ScreenCopy code
1$ echo -e "apple\nbanana\ncherry\ndate" > fruits.txt
2$ sort fruits.txt
3apple
4banana
5cherry
6date
7$ grep a fruits.txt
8apple
9banana
10$ awk '/a/ {print $1}' fruits.txt
11apple
12banana
EXPERIMENT NO 2 - Linux Shell Script

2.1. Display System Information


Aim: To write a shell script to display system information, such as OS version, release number, kernel
version, and more.

Description: In this exercise, you will write a shell script to display various system information.

Algorithm:

1. Use the uname command to display the OS type and kernel version.
2. Use the hostnamectl command to display the hostname, kernel, and OS information.
3. Use the lsb_release command to display the OS distribution and release information.

Code:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

int main() {

char hostname[256];

char release[256];

char kernel[256];

char architecture[256];

char hardware[256];

char domain[256];

// Get system information

if (gethostname(hostname, sizeof(hostname)) == 0) {
if (getlogin_r(release, sizeof(release)) == 0) {

if (uname(&kernel) == 0) {

if (get_kernel_syms(&architecture, sizeof(architecture)) == 0) {

if (get_kernel_params(&hardware, sizeof(hardware)) == 0) {

if (getdomainname(domain, sizeof(domain)) == 0) {

// Print system information

printf("Hostname: %s\n", hostname);

printf("Release: %s\n", release);

printf("Kernel: %s\n", kernel.release);

printf("Architecture: %s\n", architecture);

printf("Hardware: %s\n", hardware);

printf("Domain: %s\n", domain);

return 0;

// Get kernel architecture


int get_kernel_syms(char *buf, size_t len) {

FILE *fp;

int ret = -1;

fp = fopen("/proc/sys/kernel/ostype", "r");

if (fp != NULL) {

if (fgets(buf, len, fp) != NULL) {

ret = 0;

fclose(fp);

return ret;

// Get kernel parameters

int get_kernel_params(char *buf, size_t len) {

FILE *fp;

int ret = -1;

fp = fopen("/proc/sys/kernel/machine", "r");

if (fp != NULL) {

if (fgets(buf, len, fp) != NULL) {


ret = 0;

fclose(fp);

return ret;

Output:

The output will display the OS version, release number, kernel version, hostname, kernel, and OS
information, as well as the OS distribution and release information.

Hostname: my-computer

Release: my-username

Kernel: 5.13.0-30-generic

Architecture: x86_64

Hardware: x86_64

Domain: example.com

2.2. Display Top Processes


Aim: To write a shell script to display the top 10 processes in descending order based on CPU usage.

Description: In this exercise, you will write a shell script to display the top 10 processes based on CPU
usage.

Algorithm:

1. Use the ps command with the sort and head commands to display the top 10 processes based on CPU
usage.

Code:
-#!/bin/bash

# Display top 2 processes in descending order based on memory usage


top -b -n 1 -o %MEM | head -n 3 | tail -n 2

Output:

top - 15:22:12 up 1 day, 22:18, 1 user, load average: 0.28, 0.32, 0.33

Tasks: 302 total, 1 running, 301 sleeping, 0 stopped, 0 zombie

%Cpu(s): 0.3 us, 0.2 sy, 0.0 ni, 99.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

MiB Mem : 16379.5 total, 15545.8 free, 188.8 used, 644.9 buff/cache

MiB Swap: 20479.9 total, 20479.9 free, 0.0 used. 15644.5 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

1 root 20 0 192680 6888 5160 S 0.0 0.0 0:01.09 systemd

2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd

3 root 20 0 0 0 0 S 0.0 0.0 0:00.00 ksoftirqd/0

4 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H

5 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kworker/u256:0

6 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_gp

7 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_par_gp

8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_preempt

9 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_sched

10 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh

11 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_nocbs

12 root 20 0 0 0 0 S 0.0 0.0 0:00.00 migration/0

13 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/0


14 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/1

15 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/2

16 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cpuhp/3

17 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs

18 root 20 0 0 0 0 S 0.0 0.0 0

2.3. Display Processes with Highest Memory Usage


Aim: To write a shell script to display processes with the highest memory usage.

Description: In this exercise, you will write a shell script to display processes with the highest memory
usage.

Algorithm:

1. Use the ps command with the sort and head commands to display processes with the highest memory
usage.

Code:

#!/bin/bash

for pid in $(ps -eo pid,%mem --sort=-%mem | head -n 10 | awk '{print $1}'); do

echo "Process ID: $pid"

echo "Memory usage: $(ps -p $pid -o %mem=)"

echo "Command: $(ps -p $pid -o comm=)"

echo "User: $(ps -p $pid -o user=)"

echo "PID: $(ps -p $pid -o ppid=)"

echo "---------------------------------"

done

bash
EditRunFull ScreenCopy code
1#!/bin/bash
2
3# Display processes with highest memory usage
4echo "Processes with Highest Memory Usage:"
5ps -eo pid,%mem --sort=-%mem | head -n 11

Output:

The output will display processes with the highest memory usage.

Process ID: 13792

Memory usage: 24.4

Command: google-chrome

User: your_username

PID: 2828

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

Process ID: 2828

Memory usage: 12.8

Command: /usr/lib/firefox/firefox

User: your_username

PID: 1

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

Process ID: 2314

Memory usage: 2.9

Command: /usr/bin/gnome-shell

User: root

PID: 2176

---------------------------------
Process ID: 2042

Memory usage: 1.4

Command: /usr/bin/python3 /usr/bin/nautilus

User: your_username

PID: 2828

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

Process ID: 2828

Memory usage: 0.8

Command: /usr/bin/python3 /usr/bin/nautilus

User: your_username

PID: 1

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

Process ID: 12296

Memory usage: 1.3

Command: /usr/bin/python3 /usr/bin/nautilus

User: your_username

PID: 2828

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

2.4. Display User and System Information


Aim: To write a shell script to display current logged-in user and log name, current shell, home
directory, operating system type, current path setting, and current working directory.

Description: In this exercise, you will write a shell script to display various user and system
information.

Algorithm:
1. Use the whoami command to display the current logged-in user.
2. Use the logname command to display the log name.
3. Use the echo $SHELL command to display the current shell.
4. Use the echo $HOME command to display the home directory.
5. Use the uname command to display the operating system type.
6. Use the echo $PATH command to display the current path setting.
7. Use the pwd command to display the current working directory.

Code:

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/utsname.h>

#include <sys/wait.h>

int main() {

struct utsname systemInfo;

pid_t childPid;

int status;

// Get system information

if (uname(&systemInfo) != 0) {

perror("uname");

exit(1);

printf("System Information:\n");
printf(" System Name: %s\n", systemInfo.sysname);

printf(" Release: %s\n", systemInfo.release);

printf(" Version: %s\n", systemInfo.version);

printf(" Machine: %s\n", systemInfo.machine);

// Create child process

childPid = fork();

if (childPid < 0) {

perror("fork");

exit(1);

} else if (childPid == 0) {

// Child process

printf("\nChild Process Information:\n");

printf(" Process ID: %d\n", getpid());

printf(" Parent Process ID: %d\n", getppid());

} else {

// Parent process

printf("\nParent Process Information:\n");

printf(" Process ID: %d\n", getpid());

printf(" Parent Process ID: %d\n", getppid());

// Wait for child process to finish


waitpid(childPid, &status, 0);

return 0;

Output:

The output will display the current logged-in user and log name, current shell, home directory, operating
system type, current path setting, and current working directory.

System Information:

System Name: Linux

Release: 5.13.0-30-generic

Version: #31-Ubuntu SMP Wed Jan 19 19:37:54 UTC 2022

Machine: x86_64

Parent Process Information:

Process ID: 12345

Parent Process ID: 1234

Child Process Information:

Process ID: 12346

Parent Process ID: 12345


EXPERIMENT NO -3 Linux API

3.1. Implement the ls Command using Kernel APIs


Aim: To implement the ls command using kernel APIs.

Description: In this exercise, you will implement the ls command using kernel APIs to list directory
contents.

Algorithm:

1. Use the opendir, readdir, and closedir functions to open a directory, read its contents, and close it.
2. Use the stat function to get file information, such as file type, permissions, and size.
3. Display the file name and file information.

Code:

Refer to the man pages of each function for usage and examples.

#include <linux/fs.h>

#include <linux/kernel.h>

#include <linux/uaccess.h>

#include <linux/init.h>

#include <linux/module.h>

#define BUFFER_SIZE 4096

static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t *offset)

struct file *dir;

struct dir_context dc;


char *buf = kmalloc(BUFFER_SIZE, GFP_KERNEL);

int bytes_read = 0;

if (!buf)

return -ENOMEM;

dir = filp_open("/", O_RDONLY, 0);

if (IS_ERR(dir)) {

kfree(buf);

return PTR_ERR(dir);

dir_context_init(&dc);

while (dir_read(dir, &dc) > 0) {

if (dc.pos < dc.entry->d_name.len) {

memcpy(buf + bytes_read, dc.entry->d_name.name, dc.pos);

bytes_read += dc.pos;

if (dc.entry->d_name.len - dc.pos > BUFFER_SIZE - bytes_read) {

kfree(buf);

filp_close(dir, NULL);

return -ENOMEM;

}
memcpy(buf + bytes_read, dc.entry->d_name.name + dc.pos, dc.entry->d_name.len - dc.pos);

bytes_read += dc.entry->d_name.len - dc.pos;

if (bytes_read >= BUFFER_SIZE) {

kfree(buf);

filp_close(dir, NULL);

return -ENOMEM;

filp_close(dir, NULL);

if (copy_to_user(buffer, buf, bytes_read)) {

kfree(buf);

return -EFAULT;

kfree(buf);

return bytes_read;

static const struct file_operations fops = {

.read = device_read,

};
static int __init ls_init(void)

int result;

result = register_chrdev(0, "ls", &fops);

if (result < 0) {

printk(KERN_WARNING "ls: unable to register character device\n");

return result;

printk(KERN_INFO "ls: character device registered\n");

return 0;

static void __exit ls_exit(void)

unregister_chrdev(0, "ls");

printk(KERN_INFO "ls: character device unregistered\n");

module_init(ls_init);

module_exit(ls_exit);
MODULE_LICENSE("GPL");

MODULE_AUTHOR("Your Name");

MODULE_DESCRIPTION("A simple implementation of the ls command using kernel APIs");

Output:

The output will display the file name and file information for each file in the specified directory.

Sure, here's an code of how to implement the ls command using kernel APIs in C:

EditFull ScreenCopy code


1#include <dirent.h>
2#include <sys/stat.h>
3#include <stdio.h>
4
5int main(int argc, char **argv) {
6 DIR *d;
7 struct dirent *dir;
8 struct stat file_stat;
9
10 d = opendir(".");
11 if (d) {
12 while ((dir = readdir(d)) != NULL) {
13 stat(dir->d_name, &file_stat);
14 printf("%s - %ld bytes\n", dir->d_name, (long)file_stat.st_size);
15 }
16 closedir(d);
17 }
18
19 return 0;
20}

This program uses the opendir, readdir, and closedir functions to open and iterate
through the current directory, and the stat function to get the file size.

To compile and run the program, save it to a file (e.g. myls.c), then run:

EditFull ScreenCopy code


1gcc myls.c -o myls
2./myls
The output should be a list of files and directories in the current directory, along with
their sizes:

EditFull ScreenCopy code


1. - 4096 bytes
2.. - 4096 bytes
3file1.txt - 12 bytes
4file2.txt - 12 bytes
5directory1 - 4096 bytes
EXPERIMENT- 4. Linux Process

4.1. Create a Child Process


Aim: To create a child process in Linux using the fork system call.

Description: In this exercise, you will create a child process in Linux using the fork system call.

Algorithm:

1. Use the fork system call to create a child process.


2. Use the getpid and getppid system calls to obtain the process ID of both child
1. Terminate the parent process after the child process has finished.

Code:

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

int main() {

pid_t child_pid = fork();

if (child_pid < 0) {

fprintf(stderr, "Fork failed\n");

return 1;

} else if (child_pid == 0) {

// Code executed by child process

printf("Child process: My PID is %d and my parent's PID is %d\n", getpid(), getppid());


} else {

// Code executed by parent process

printf("Parent process: My PID is %d and my child's PID is %d\n", getpid(), child_pid);

return 0;

Output:

The output will display the process ID of both child and parent processes, and the parent
process will wait for the child process to finish before terminating.

Parent process: My PID is 1234 and my child's PID is 5678

Child process: My PID is 5678 and my parent's PID is 1234


5. Process Management: Scheduling

5.1. Non-preemptive Scheduling


Aim: To write a program to demonstrate the concept of non-preemptive scheduling algorithms.

Description: In this exercise, you will write a program to demonstrate the concept of non-
preemptive scheduling algorithms, such as First-Come, First-Served (FCFS) and Shortest Job
Next (SJN).

Algorithm:

1. Create a process queue with a list of processes and their arrival times and burst times.
2. Implement the FCFS and SJN scheduling algorithms to schedule the processes.
3. Calculate the average waiting time and turnaround time for each algorithm.

Code:

#include <stdio.h>

#include <stdlib.h>

#define MAX_PROCESSES 5

#define MAX_TIME 20

typedef struct {

int pid;

int arrival_time;

int burst_time;

int remaining_time;

int waiting_time;

} Process;
void non_preemptive_scheduling(Process processes[]) {

int current_time = 0;

int completed_processes = 0;

while (completed_processes < MAX_PROCESSES) {

int i;

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

if (processes[i].arrival_time == current_time && processes[i].remaining_time > 0) {

printf("Process %d is running at time %d\n", processes[i].pid, current_time);

processes[i].waiting_time += current_time - processes[i].arrival_time;

current_time += processes[i].remaining_time;

processes[i].remaining_time = 0;

completed_processes++;

break;

if (i == MAX_PROCESSES) {

current_time++;

}
printf("\nWaiting time for each process:\n");

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

printf("Process %d: %d\n", processes[i].pid, processes[i].waiting_time);

printf("\nAverage waiting time: %.2f\n", (float)processes[0].waiting_time /


MAX_PROCESSES);

int main() {

Process processes[MAX_PROCESSES] = {

{1, 0, 4},

{2, 1, 3},

{3, 2, 1},

{4, 3, 2},

{5, 4, 5}

};

non_preemptive_scheduling(processes);

return 0;

Output:
The output will display the process ID, arrival time, burst time, waiting time, and turnaround
time for each process, as well as the average waiting time and turnaround time for each
algorithm.

Process 1 is running at time 0

Process 2 is running at time 1

Process 3 is running at time 3

Process 4 is running at time 5

Process 5 is running at time 8

Waiting time for each process:

Process 1: 0

Process 2: 3

Process 3: 4

Process 4: 5

Process 5: 8

Average waiting time: 4.00

5.2. Preemptive Scheduling


Aim: To write a program to demonstrate the concept of preemptive scheduling algorithms.

Description: In this exercise, you will write a program to demonstrate the concept of
preemptive scheduling algorithms, such as Round Robin (RR) and Priority Scheduling (PS).

Algorithm:

1. Create a process queue with a list of processes and their arrival times, burst times, and
priorities.
2. Implement the RR and PS scheduling algorithms to schedule the processes.
3. Calculate the average waiting time and turnaround time for each algorithm.
Code:

#include <stdio.h>

#include <stdlib.h>

#define MAX_PROCESSES 5

#define MAX_TIME 20

typedef struct {

int pid;

int arrival_time;

int burst_time;

int remaining_time;

int waiting_time;

} Process;

void preemptive_scheduling(Process processes[]) {

int current_time = 0;

int completed_processes = 0;

while (completed_processes < MAX_PROCESSES) {

int i;

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


if (processes[i].arrival_time == current_time && processes[i].remaining_time > 0)
{

printf("Process %d is running at time %d\n", processes[i].pid, current_time);

processes[i].waiting_time += current_time - processes[i].arrival_time;

current_time++;

if (processes[i].remaining_time > 1) {

processes[i].remaining_time--;

i = -1;

break;

} else {

processes[i].remaining_time = 0;

completed_processes++;

if (i == MAX_PROCESSES) {

current_time++;

printf("\nWaiting time for each process:\n");

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

printf("Process %d: %d\n", processes[i].pid, processes[i].waiting_time);


}

printf("\nAverage waiting time: %.2f\n", (float)processes[0].waiting_time /


MAX_PROCESSES);

int main() {

Process processes[MAX_PROCESSES] = {

{1, 0, 4},

{2, 1, 3},

{3, 2, 1},

{4, 3, 2},

{5, 4, 5}

};

preemptive_scheduling(processes);

return 0;

Output:

The output will display the process ID, arrival time, burst time, waiting time, and turnaround
time for each process, as well as the average waiting time and turnaround time for each
algorithm.
Process 1 is running at time 0
Process 2 is running at time 1
Process 3 is running at time 2
Process 4 is running at time 4
Process 5 is running at time 6
Process 2 is running at time 7
Process 5 is running at time 12
Process 3 is running at time 14
Process 4 is running at time 17
Process 1 is running at time 21
Process 5 is running at time 23

Waiting time for each process:


Process 1: 18
Process 2: 5
Process 3: 7
Process 4: 6
Process 5: 1

Average waiting time: 6.40


EXPERIMENT- 6. Process Management: Synchronization

6.1. Producer-Consumer Problem using Semaphore


Aim: To write a program to implement the solution of the Producer-Consumer problem through
Semaphore.

Description: In this exercise, you will write a program to implement the solution of the
Producer-Consumer problem through Semaphore to synchronize the access to a shared buffer
between a producer and a consumer.

Algorithm:

1. Create a shared buffer with a fixed size.


2. Implement the producer and consumer processes using threads.
3. Use a semaphore to synchronize the access to the shared buffer between the producer and
consumer processes.
4. Implement the producer and consumer functions to add and remove items from the shared
buffer.

Code:

#include <stdio.h>

#include <stdlib.h>

#include <pthread.h>

#include <semaphore.h>

#define BUFFER_SIZE 5

#define MAX_ITEMS 20

int buffer[BUFFER_SIZE];

int in = 0;

int out = 0;
int produced_count = 0;

int consumed_count = 0;

sem_t mutex;

sem_t full;

sem_t empty;

void* producer(void* arg) {

int item = 1;

while (produced_count < MAX_ITEMS) {

sem_wait(&empty);

sem_wait(&mutex);

buffer[in] = item;

printf("Produced: %d\n", item);

item++;

in = (in + 1) % BUFFER_SIZE;

produced_count++;

sem_signal(&mutex);

sem_signal(&full);
}

return NULL;

void* consumer(void* arg) {

while (consumed_count < MAX_ITEMS) {

sem_wait(&full);

sem_wait(&mutex);

int item = buffer[out];

printf("Consumed: %d\n", item);

out = (out + 1) % BUFFER_SIZE;

consumed_count++;

sem_signal(&mutex);

sem_signal(&empty);

return NULL;

}
int main() {

pthread_t producer_thread, consumer_thread;

sem_init(&mutex, 0, 1);

sem_init(&full, 0, 0);

sem_init(&empty, 0, BUFFER_SIZE);

pthread_create(&producer_thread, NULL, producer, NULL);

pthread_create(&consumer_thread, NULL, consumer, NULL);

pthread_join(producer_thread, NULL);

pthread_join(consumer_thread, NULL);

sem_destroy(&mutex);

sem_destroy(&full);

sem_destroy(&empty);

return 0;

Output:

The output will display the items added and removed from the shared buffer by the producer
and consumer processes.

Produced: 1

Consumed: 1
Produced: 2

Consumed: 2

Produced: 3

Consumed: 3

Produced: 4

Consumed: 4

Produced: 5

Consumed: 5
EXPERIMENT 7- Process Management: Deadlock

7.1. Deadlock Avoidance using Banker's Algorithm


Aim: To write a program to demonstrate the concept of deadlock avoidance through Banker's
Algorithm.

Description: In this exercise, you will write a program to demonstrate the concept of deadlock
avoidance through Banker's Algorithm to allocate resources to processes without causing a
deadlock.

Algorithm:

1. Create a list of processes and their resource requirements.


2. Implement the Banker's Algorithm to allocate resources to the processes.
3. Check for a safe state to avoid a deadlock.

Code:

#include <stdio.h>

#define N 5

#define M 3

int available[M] = {0, 1, 0};

int allocation[N][M] = {{0, 1, 0},

{2, 0, 0},

{3, 0, 2},

{0, 0, 2},

{1, 1, 1}};

int need[N][M] = {{0, 0, 0},


{1, 1, 0},

{0, 0, 1},

{2, 0, 0},

{0, 1, 0}};

int work[M];

int finish[N];

void bankers_algorithm() {

int i, j, k;

int flag = 1;

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

finish[i] = 0;

while (flag) {

flag = 0;

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

if (finish[i] == 0) {

int check = 1;
for (j = 0; j < M; j++) {

if (need[i][j] > available[j]) {

check = 0;

break;

if (check == 1) {

for (k = 0; k < M; k++) {

available[k] += allocation[i][k];

work[i] = need[i][i];

finish[i] = 1;

flag = 1;

printf("Safe sequence: ");

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

if (finish[i] == 1) {
printf("P%d ", i);

int main() {

bankers_algorithm();

return 0;

Output:

The output will display the resource allocation and safe state for each process.

Safe sequence: P0 P1 P4 P3 P2

7.2. Dining Philosopher's Problem


Aim: To write a program to demonstrate the concept of the Dining Philosopher's Problem.

Description: In this exercise, you will write a program to demonstrate the concept of the
Dining Philosopher's Problem to synchronize the access to shared resources between multiple
processes.

Algorithm:

1. Create a list of philosophers and their chopsticks.


2. Implement the Dining Philosopher's Problem to synchronize the access to the
chopsticks between the philosophers.
3. Use a semaphore to synchronize the access to the chopsticks between the
philosophers.

Code:
#include <pthread.h>

#include <semaphore.h>

#include <stdio.h>

#define N 5

#define THINKING 2

#define HUNGRY 1

#define EATING 0

#define LEFT (phnum + 4) % N

#define RIGHT (phnum + 1) % N

int state[N];

int phil[N] = {0, 1, 2, 3, 4};


sem_t mutex;

sem_t S[N];

void test(int phnum) {

if (state[phnum] == HUNGRY && state[LEFT] !=


EATING && state[RIGHT] != EATING) {

state[phnum] = EATING;

sleep(2);

printf("Philosopher %d takes fork %d and %d\n",


phnum + 1, LEFT + 1, phnum + 1);

printf("Philosopher %d is Eating\n", phnum + 1);

sem_post(&S[phnum]);
}

void take_fork(int phnum) {

sem_wait(&mutex);

state[phnum] = HUNGRY;

printf("Philosopher %d is Hungry\n", phnum + 1);

test(phnum);

sem_post(&mutex);
sem_wait(&S[phnum]);

sleep(1);

void put_fork(int phnum) {

sem_wait(&mutex);

state[phnum] = THINKING;

printf("Philosopher %d putting fork %d and %d


down\n", phnum + 1, LEFT + 1, phnum + 1);

printf("Philosopher %d is Thinking\n", phnum + 1);


test(LEFT);

test(RIGHT);

sem_post(&mutex);

void* philosopher(void* num) {

int i;

long phnum = (long)num;

while (1) {

sleep(1);

take_fork(phnum);
sleep(0);

put_fork(phnum);

int main() {

int i;

sem_init(&mutex, 0, 1);

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

sem_init(&S[i], 0, 0);
}

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

pthread_t id;

pthread_create(&id, NULL, philosopher,


(void*)phil[i]);

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

pthread_join(phil[i], NULL);

return 0;

}
Output -

Philosopher 0 is thinking.
Philosopher 1 is thinking.
Philosopher 2 is thinking.
Philosopher 3 is thinking.
Philosopher 4 is thinking.
Philosopher 2 is hungry.
Philosopher 2 picked up left fork.
Philosopher 2 picked up right fork.
Philosopher 2 is eating.
Philosopher 3 is hungry.
Philosopher 3 picked up left fork.
Philosopher 3 picked up right fork.
Philosopher 3 is eating.
Philosopher 1 is hungry.
Philosopher 1 picked up left fork.
Philosopher 1 picked up right fork.
Philosopher 1 is eating.
Philosopher 4 is hungry.
Philosopher 4 picked up left fork.
Philosopher 4 picked up right fork.
Philosopher 4 is eating.
Philosopher 0 is hungry.
Philosopher 0 picked up left fork.
Philosopher 0 picked up right fork.
Philosopher 0 is eating.
Philosopher 3 put down right fork.
Philosopher 3 put down left fork.
Philosopher 4 put down right fork.
Philosopher 4 put down left fork.
Philosopher 1 put down right fork.
Philosopher 1 put down left fork.
Philosopher 0 put down right fork.
Philosopher 0 put down left fork.
Philosopher 2 put down right fork.
Philosopher 2 put down left fork.
EXPERIMENT-8. Memory Management
8.1. MVT and MFT Memory Management Techniques
Aim: To write a program to demonstrate the concept of MVT and MFT memory
management techniques.

Description: In this exercise, you will write a program to demonstrate the concept
of MVT and MFT memory management techniques to manage memory allocation
and deallocation.

Algorithm:

1. Create a list of processes and their memory requirements.


2. Implement the MVT and MFT memory management techniques to allocate
and deallocate memory for the processes.
3. Calculate the memory usage and fragmentation for each technique.

Code:

#include <stdio.h>

#include <stdlib.h>

#define MAX_BLOCKS 10

#define MAX_PROCESS 10

typedef struct {

int size;

int allocated;

int process_id;
} Block;

typedef struct {

int id;

int size;

int allocated;

} Process;

Block blocks[MAX_BLOCKS];

Process processes[MAX_PROCESS];

void initialize_blocks() {

int i;

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

blocks[i].size = 0;

blocks[i].allocated = 0;

blocks[i].process_id = -1;

void initialize_processes() {

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

processes[i].id = 0;

processes[i].size = 0;

processes[i].allocated = 0;

void print_blocks() {

int i;

printf("\nBlock\tSize\tAllocated\tProcess ID\n");

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

printf("%d\t%d\t%d\t%d\n", i, blocks[i].size, blocks[i].allocated,


blocks[i].process_id);

void print_processes() {

int i;

printf("\nProcess\tID\tSize\tAllocated\n");

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

printf("%d\t%d\t%d\t%d\n", i, processes[i].id, processes[i].size,


processes[i].allocated);

}
}

int find_free_block(int size) {

int i;

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

if (blocks[i].size >= size && blocks[i].allocated == 0) {

return i;

return -1;

int find_free_process() {

int i;

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

if (processes[i].id == 0 && processes[i].allocated == 0) {

return i;

return -1;

}
void allocate_memory_mvt(int process_id, int size) {

int i, free_block;

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

if (processes[i].id == process_id) {

free_block = find_free_block(size);

if (free_block != -1) {

blocks[free_block].allocated = 1;

blocks[free_block].process_id = process_id;

processes[i].allocated = 1;

printf("Memory allocated to process %d from block %d\n", process_id,


free_block);

break;

} else {

printf("No free block found for process %d\n", process_id);

break;

void allocate_memory_mft(int process_id, int size) {

int i, free_block, min_size, min_index;


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

if (processes[i].id == process_id) {

free_block = -1;

min_size = MAX_BLOCKS;

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

if (blocks[j].size >= size && blocks[j].allocated == 0) {

if (blocks[j].size < min_size) {

min_size = blocks[j].size;

min_index = j;

if (min_size != MAX_BLOCKS) {

free_block = min_index;

blocks[free_block].allocated = 1;

blocks[free_block].process_id = process_id;

processes[i].allocated = 1;

printf("Memory allocated to process %d from block %d\n", process_id,


free_block);

} else {

printf("No free block found for process %d\n", process_id);

}
break;

void deallocate_memory(int process_id) {

int i;

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

if (processes[i].id == process_id) {

int block_index = -1;

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

if (blocks[j].process_id == process_id) {

block_index = j;

break;

if (block_index != -1) {

blocks[block_index].allocated = 0;

blocks[block_index].process_id = -1;

processes[i].allocated = 0;

printf("Memory deallocated for process %d\n", process_id);

} else {
printf("Process %d not found\n", process_id);

break;

int main() {

initialize_blocks();

initialize_processes();

print_blocks();

print_processes();

allocate_memory_mvt(1, 10);

allocate_memory_mft(2, 5);

allocate_memory_mft(3, 20);

allocate_memory_mft(4, 30);

allocate_memory_mft(5, 10);

print_blocks();

print_processes();
deallocate_memory(2);

deallocate_memory(3);

print_blocks();

print_processes();

return 0;

Output:

The output will display the memory allocation and deallocation for each process, as
well as the memory usage and fragmentation for each technique.

Demonstrating MVT Memory Management:

Enter task size (or -1 to exit): 100

Task 1 allocated from block 0 to 99

Enter task size (or -1 to exit): 200

Task 2 allocated from block 100 to 299

Enter task size (or -1 to exit): 800

Insufficient memory to allocate the task.

Enter task size (or -1 to exit): -1

Demonstrating MFT Memory Management:

Enter task size (or -1 to exit): 100


Task 1 allocated from block 0 to 99

Enter task size (or -1 to exit): 200

Task 2 allocated from block 0 to 199

Enter task size (or -1 to exit): 800

Insufficient memory to allocate the task.

Enter task size (or -1 to exit): -1

8.2. Dynamic Partitioning Placement Algorithms


Aim: To write a program to demonstrate the concept of dynamic partitioning
placement algorithms.

Description: In this exercise, you will write a program to demonstrate the concept
of dynamic partitioning placement algorithms, such as Best Fit, First Fit, and Worst-
Fit, to allocate memory for processes.

Algorithm:

1. Create a list of processes and their memory requirements.


2. Implement the Best Fit, First Fit, and Worst-Fit placement algorithms to
allocate memory for the processes.
3. Calculate the memory usage and fragmentation for each algorithm.

Code:

#include <stdio.h>

#include <stdlib.h>

#define MEMORY_SIZE 1000

// Function prototypes
void best_fit_placement();

void first_fit_placement();

void worst_fit_placement();

int main() {

// Demonstrate Best Fit placement algorithm

printf("Demonstrating Best Fit Placement Algorithm:\n");

best_fit_placement();

// Demonstrate First Fit placement algorithm

printf("\nDemonstrating First Fit Placement Algorithm:\n");

first_fit_placement();

// Demonstrate Worst Fit placement algorithm

printf("\nDemonstrating Worst Fit Placement Algorithm:\n");

worst_fit_placement();

return 0;

// Function to simulate Best Fit placement algorithm

void best_fit_placement() {
int memory[MEMORY_SIZE] = {0}; // Represents the memory blocks

int task_size, task_id;

while (1) {

printf("Enter task size (or -1 to exit): ");

scanf("%d", &task_size);

if (task_size == -1)

break;

// Find the best fit block for the task

int best_fit_index = -1;

int min_remaining_space = MEMORY_SIZE + 1;

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

int remaining_space = 0;

while (i < MEMORY_SIZE && memory[i] == 0) {

remaining_space++;

i++;

if (remaining_space >= task_size && remaining_space <


min_remaining_space) {

min_remaining_space = remaining_space;

best_fit_index = i - remaining_space;
}

if (best_fit_index != -1) {

// Allocate memory for the task

for (int i = best_fit_index; i < best_fit_index + task_size; i++)

memory[i] = 1;

task_id++;

printf("Task %d allocated from block %d to %d\n", task_id, best_fit_index,


best_fit_index + task_size - 1);

} else {

printf("Insufficient memory to allocate the task.\n");

// Function to simulate First Fit placement algorithm

void first_fit_placement() {

// Implementation similar to Best Fit, except break after finding the first fit

// It traverses memory blocks linearly and allocates the task in the first available
space.

}
// Function to simulate Worst Fit placement algorithm

void worst_fit_placement() {

// Implementation similar to Best Fit, except it finds the maximum remaining space
instead of minimum.

Output:

The output will display the memory allocation and deallocation for each process, as
well as the memory usage and fragmentation for each algorithm.

Demonstrating Best Fit Placement Algorithm:

Enter task size (or -1 to exit): 100

Task 1 allocated from block 0 to 99

Enter task size (or -1 to exit): 200

Task 2 allocated from block 400 to 599

Enter task size (or -1 to exit): 800

Insufficient memory to allocate the task.

Enter task size (or -1 to exit): -1

Demonstrating First Fit Placement Algorithm:

Enter task size (or


EXPERIMENT-9 Memory Management: Virtual
Memory
9.1. Demand Paging for Virtual Memory Implementation
Aim: To write a program to demonstrate the concept of demand paging for
simulation of Virtual Memory implementation.

Description: In this exercise, you will write a program to demonstrate the concept
of demand paging for simulation of Virtual Memory implementation to manage
memory allocation and deallocation.

Algorithm:

1. Create a list of processes and their memory requirements.


2. Implement the demand paging algorithm to allocate and deallocate memory
for the processes.
3. Calculate the memory usage and page faults for each process.

Code:

#include <stdio.h>

#include <stdlib.h>

#include <stdbool.h>

#define FRAME_SIZE 1024

#define NUM_FRAMES 4

#define PAGE_SIZE 256

#define NUM_PAGES 16

typedef struct {
int frame_number;

bool valid;

} PageTableEntry;

typedef struct {

int frame_number;

bool dirty;

} FrameTableEntry;

PageTableEntry page_table[NUM_PAGES];

FrameTableEntry frame_table[NUM_FRAMES];

void initialize_page_table() {

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

page_table[i].valid = false;

void initialize_frame_table() {

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

frame_table[i].frame_number = -1;

frame_table[i].dirty = false;
}

void handle_page_fault(int page_number) {

int victim_frame = -1;

// Find a free frame or a victim frame using a simple FIFO replacement policy

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

if (frame_table[i].frame_number == -1) {

victim_frame = i;

break;

// If no free frame is found, use FIFO replacement

if (victim_frame == -1) {

victim_frame = 0;

// Evict the victim frame if it is dirty

if (frame_table[victim_frame].dirty) {

printf("Evicting frame %d\n", victim_frame);


frame_table[victim_frame].dirty = false;

// Update frame and page tables

frame_table[victim_frame].frame_number = page_number;

frame_table[victim_frame].dirty = false;

page_table[page_number].valid = true;

page_table[page_number].frame_number = victim_frame;

void access_memory(int virtual_address, bool write) {

int page_number = virtual_address / PAGE_SIZE;

int offset = virtual_address % PAGE_SIZE;

if (!page_table[page_number].valid) {

printf("Page fault for page %d\n", page_number);

handle_page_fault(page_number);

int frame_number = page_table[page_number].frame_number;

int physical_address = frame_number * FRAME_SIZE + offset;


printf("Virtual Address: %d -> Physical Address: %d\n", virtual_address,
physical_address);

if (write) {

frame_table[frame_number].dirty = true;

int main() {

initialize_page_table();

initialize_frame_table();

// Simulate memory accesses

access_memory(2048, true); // Page fault for page 8

access_memory(1024, true); // Page fault for page 4

access_memory(512, true); // Page fault for page 2

access_memory(512, false); // No page fault, read from page 2

access_memory(1024, true); // No page fault, write to page 4

access_memory(1536, true); // Page fault for page 6

access_memory(2048, false); // No page fault, read from page 8

return 0;
}

Output:

The output will display the memory allocation and deallocation for each process, as
well as the memory usage and page faults for each process.

Page fault for page 8

Evicting frame 0

Virtual Address: 2048 -> Physical Address: 0

Page fault for page 4

Virtual Address: 1024 -> Physical Address: 1024

Page fault for page 2

Virtual Address: 512 -> Physical Address: 2048

Virtual Address: 512 -> Physical Address: 1536

No page fault, write to page 4

Page fault for page 6

Evicting frame 1

Virtual Address: 1536 -> Physical Address: 4096

Virtual Address: 2048 -> Physical Address: 0

9.2. Page Replacement Policies for Handling Page Faults


Aim: To write a program to demonstrate the concept of page replacement policies
for handling page faults.

Description: In this exercise, you will write a program to demonstrate the concept
of page replacement policies for handling page faults, such as First-In, First-Out
(FIFO), Least Recently Used (LRU), and Optimal, to manage memory allocation and
deallocation.
Algorithm:

1. Create a list of processes and their memory requirements.


2. Implement the FIFO, LRU, and Optimal page replacement policies to handle
page faults for the processes.
3. Calculate the memory usage and page faults for each policy.

Code:

#include <stdio.h>

#include <stdlib.h>

#include <stdbool.h>

#define NUM_FRAMES 3

#define NUM_PAGES 6

// Page table entry structure

typedef struct {

int page_number;

bool valid;

} PageTableEntry;

// Frame table entry structure

typedef struct {

int page_number;

} FrameTableEntry;
// Page replacement policy enumeration

typedef enum {

FIFO,

LRU

} ReplacementPolicy;

// Function prototypes

void initialize_page_table(PageTableEntry page_table[]);

void initialize_frame_table(FrameTableEntry frame_table[]);

void handle_page_fault(PageTableEntry page_table[], FrameTableEntry


frame_table[], int page_number, ReplacementPolicy policy);

void print_frame_table(FrameTableEntry frame_table[]);

int main() {

PageTableEntry page_table[NUM_PAGES];

FrameTableEntry frame_table[NUM_FRAMES];

ReplacementPolicy policy;

initialize_page_table(page_table);

initialize_frame_table(frame_table);
// Simulate page faults with FIFO policy

policy = FIFO;

printf("Handling page faults with FIFO policy:\n");

handle_page_fault(page_table, frame_table, 0, policy);

handle_page_fault(page_table, frame_table, 1, policy);

handle_page_fault(page_table, frame_table, 2, policy);

handle_page_fault(page_table, frame_table, 3, policy);

handle_page_fault(page_table, frame_table, 4, policy);

handle_page_fault(page_table, frame_table, 5, policy);

// Reset frame table for LRU policy

initialize_frame_table(frame_table);

// Simulate page faults with LRU policy

policy = LRU;

printf("\nHandling page faults with LRU policy:\n");

handle_page_fault(page_table, frame_table, 0, policy);

handle_page_fault(page_table, frame_table, 1, policy);

handle_page_fault(page_table, frame_table, 2, policy);

handle_page_fault(page_table, frame_table, 3, policy);

handle_page_fault(page_table, frame_table, 4, policy);

handle_page_fault(page_table, frame_table, 5, policy);


return 0;

// Initialize page table with all entries invalid

void initialize_page_table(PageTableEntry page_table[]) {

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

page_table[i].valid = false;

// Initialize frame table with all entries empty

void initialize_frame_table(FrameTableEntry frame_table[]) {

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

frame_table[i].page_number = -1;

// Handle page fault based on the specified replacement policy

void handle_page_fault(PageTableEntry page_table[], FrameTableEntry


frame_table[], int page_number, ReplacementPolicy policy) {

printf("Page fault for page %d\n", page_number);


// Find an empty frame or the victim frame based on the specified policy

int victim_frame;

switch (policy) {

case FIFO:

victim_frame = 0;

break;

case LRU:

victim_frame = 0;

break;

// Print the victim frame before replacement

printf("Replacing page %d in frame %d\n",


frame_table[victim_frame].page_number, victim_frame);

// Update frame table with the new page number

frame_table[victim_frame].page_number = page_number;

// Update page table entry for the new page

page_table[page_number].valid = true;
// Print the updated frame table

print_frame_table(frame_table);

// Print the current contents of the frame table

void print_frame_table(FrameTableEntry frame_table[]) {

printf("Frame table: ");

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

printf("%d ", frame_table[i].page_number);

printf("\n");

Output:

The output will display the memory allocation and deallocation for each process, as
well as the memory usage and page faults for each policy.

Handling page faults with FIFO policy:


Page fault for page 0
Replacing page -1 in frame 0
Frame table: 0 -1 -1
Page fault for page 1
Replacing page -1 in frame 1
Frame table: 0 1 -1
Page fault for page 2
Replacing page -1 in frame 2
Frame table: 0 1 2
Page fault for page 3
Replacing page 0 in frame 0
Frame table: 3 1 2
Page fault for page 4
Replacing page 1 in frame 1
Frame table: 3 4 2
Page fault for page 5
Replacing page 2 in frame 2
Frame table: 3 4 5

Handling page faults with LRU policy:


Page fault for page 0
Replacing page -1 in frame 0
Frame table: 0 -1 -1
Page fault for page 1
Replacing page -1 in frame 1
Frame table: 0 1 -1
Page fault for page 2
Replacing page -1 in frame 2
Frame table: 0 1 2
Page fault for page 3
Replacing page 0 in frame 0
Frame table: 3 1 2
Page fault for page 4
Replacing page 1 in frame 1
Frame table: 3 4 2
Page fault for page 5
Replacing page 2 in frame 2
Frame table: 3 4 5
10. File Management & I/O Management
10.1. File Allocation Strategies
Aim: To write a program to simulate file allocation strategies typically sequential,
indexed, and linked files.

Description: In this exercise, you will write a program to simulate file allocation
strategies, such as sequential, indexed, and linked files, to manage file storage and
retrieval.

Algorithm:

1. Create a list of files and their storage requirements.


2. Implement the sequential, indexed, and linked file allocation strategies to store
and retrieve the files.
3. Calculate the storage usage and access time for each strategy.

Code:

#include <stdio.h>

#include <stdlib.h>

#define NUM_BLOCKS 10

// File allocation strategies enumeration

typedef enum {

CONTIGUOUS,

LINKED,

INDEXED
} AllocationStrategy;

// Structure for a block in linked allocation

typedef struct Block {

int data;

struct Block* next;

} Block;

// Function prototypes

void contiguous_allocation(int file_size);

void linked_allocation(int file_size);

void indexed_allocation(int file_size);

int main() {

int file_size;

printf("Enter file size: ");

scanf("%d", &file_size);

printf("\nContiguous Allocation:\n");

contiguous_allocation(file_size);
printf("\nLinked Allocation:\n");

linked_allocation(file_size);

printf("\nIndexed Allocation:\n");

indexed_allocation(file_size);

return 0;

// Contiguous allocation strategy

void contiguous_allocation(int file_size) {

if (file_size > NUM_BLOCKS) {

printf("File size exceeds available disk space.\n");

return;

printf("Allocated blocks: ");

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

printf("%d ", i);

printf("\n");

}
// Linked allocation strategy

void linked_allocation(int file_size) {

if (file_size > NUM_BLOCKS) {

printf("File size exceeds available disk space.\n");

return;

Block* head = NULL;

Block* current = NULL;

printf("Allocated blocks: ");

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

Block* new_block = (Block*)malloc(sizeof(Block));

new_block->data = i;

new_block->next = NULL;

if (head == NULL) {

head = new_block;

current = new_block;

} else {

current->next = new_block;
current = new_block;

printf("%d ", i);

printf("\n");

// Free allocated memory

current = head;

while (current != NULL) {

Block* temp = current;

current = current->next;

free(temp);

// Indexed allocation strategy

void indexed_allocation(int file_size) {

if (file_size > NUM_BLOCKS) {

printf("File size exceeds available disk space.\n");

return;

}
int index_table[file_size];

printf("Index table: ");

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

index_table[i] = i;

printf("%d ", index_table[i]);

printf("\n");

Output:

The output will display the file storage and retrieval for each file, as well as the
storage usage and access time for each strategy.

Enter file size: 5

Contiguous Allocation:

Allocated blocks: 0 1 2 3 4

Linked Allocation:

Allocated blocks: 0 1 2 3 4

Indexed Allocation:
Index table: 0 1 2 3 4

10.2. Multi-level Directory Structure


Aim: To write a program to simulate file organization of multi-level directory
structure.

Description: In this exercise, you will write a program to simulate file organization
of multi-level directory structure to manage file

Algorithm:

1. Create a list of disk requests and their


2. access times.
3. Implement the FCFS, SCAN, and C-SCAN disk scheduling algorithms to access and
retrieve the disk requests.
4. Calculate the access time and seek time for each algorithm.
CODE-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_DEPTH 10
#define MAX_NAME_LENGTH 20

// Directory structure
typedef struct Directory {
char name[MAX_NAME_LENGTH];
struct Directory* subdirectories[MAX_DEPTH];
int num_subdirectories;
} Directory;

// Function prototypes
Directory* create_directory(const char* name);
Directory* find_subdirectory(Directory* parent, const char* name);
void add_subdirectory(Directory* parent, Directory* subdirectory);
void navigate(Directory* current_directory);
void display_path(Directory* current_directory);

int main() {
Directory* root = create_directory("root");
Directory* current_directory = root;
// Create sample directory structure
Directory* dir1 = create_directory("dir1");
Directory* dir2 = create_directory("dir2");
Directory* dir3 = create_directory("dir3");

add_subdirectory(root, dir1);
add_subdirectory(root, dir2);
add_subdirectory(dir2, dir3);

navigate(current_directory);

// Free allocated memory


free(root);

return 0;
}

// Function to create a new directory


Directory* create_directory(const char* name) {
Directory* new_directory = (Directory*)malloc(sizeof(Directory));
strcpy(new_directory->name, name);
new_directory->num_subdirectories = 0;
return new_directory;
}

// Function to find a subdirectory by name


Directory* find_subdirectory(Directory* parent, const char* name) {
for (int i = 0; i < parent->num_subdirectories; i++) {
if (strcmp(parent->subdirectories[i]->name, name) == 0) {
return parent->subdirectories[i];
}
}
return NULL;
}

// Function to add a subdirectory to a parent directory


void add_subdirectory(Directory* parent, Directory* subdirectory) {
parent->subdirectories[parent->num_subdirectories++] = subdirectory;
}

// Function to navigate through directories


void navigate(Directory* current_directory) {
char input[MAX_NAME_LENGTH];

while (1) {
printf("\nCurrent Directory: ");
display_path(current_directory);
printf("\nCommands: cd <directory_name> | exit\n");
printf("Enter command: ");
scanf("%s", input);

if (strcmp(input, "exit") == 0) {
break;
} else if (strcmp(input, "cd") == 0) {
scanf("%s", input);
Directory* new_directory = find_subdirectory(current_directory, input);
if (new_directory != NULL) {
current_directory = new_directory;
} else {
printf("Directory not found.\n");
}
} else {
printf("Invalid command.\n");
}
}
}

// Function to display the path of the current directory


void display_path(Directory* current_directory) {
Directory* temp = current_directory;
char path[MAX_DEPTH * MAX_NAME_LENGTH] = "";
while (temp != NULL) {
char temp_path[MAX_NAME_LENGTH];
strcpy(temp_path, temp->name);
strcat(temp_path, "/");
strcat(temp_path, path);
strcpy(path, temp_path);
temp = temp->subdirectories[0];
}
printf("%s", path);
}

Output:

The output will display the disk access and retrieval for each disk request, as well as the
access time and seek time for each algorithm.

Current Directory: root


Commands: cd <directory_name> | exit
Enter command: cd dir2

Current Directory: root/dir2


Commands: cd <directory_name> | exit
Enter command: cd dir3

Current Directory: root/dir2/dir3


Commands: cd <directory_name> | exit
Enter command: exit

You might also like