KEMBAR78
Advanced Operating System | PDF | Computing | Operating System Technology
0% found this document useful (0 votes)
35 views30 pages

Advanced Operating System

The document is a lab manual for advanced operating systems, detailing experiments that involve writing C programs to demonstrate UNIX system calls, I/O operations, and CPU scheduling algorithms. It includes specific aims, descriptions, and sample code for experiments on process control, file handling, simulating UNIX commands, and implementing scheduling algorithms like FCFS, SJF, Priority, and Round Robin. Each experiment concludes with expected and actual outputs, along with results confirming successful execution.

Uploaded by

2020csm.r10
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)
35 views30 pages

Advanced Operating System

The document is a lab manual for advanced operating systems, detailing experiments that involve writing C programs to demonstrate UNIX system calls, I/O operations, and CPU scheduling algorithms. It includes specific aims, descriptions, and sample code for experiments on process control, file handling, simulating UNIX commands, and implementing scheduling algorithms like FCFS, SJF, Priority, and Round Robin. Each experiment concludes with expected and actual outputs, along with results confirming successful execution.

Uploaded by

2020csm.r10
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/ 30

Advanced Operating Systems Lab Manual

Experiment No.: 1

Aim:
To write C programs demonstrating the use of UNIX system calls:

fork(), exec(), getpid(), exit(), wait(), close(), stat(), opendir(), readdir().

Description:
In UNIX-like operating systems, system calls provide the interface between a user program
and the kernel. These calls allow user-space applications to request services from the
operating system such as process creation, process management, and file system
manipulation.

Process Control System Calls:

1. fork() - Creates a new process (child process).

2. exec() - Replaces the current process with a new process.

3. getpid() - Returns the process ID of the calling process.

4. exit() - Terminates the calling process.

5. wait() - Suspends execution of the calling process until one of its children terminates.

File System System Calls:

1. close() - Closes a file descriptor.

2. stat() - Retrieves information about a file.

3. opendir() - Opens a directory stream.

4. readdir() - Reads a directory entry from the directory stream.

Program 1: Process Creation and Execution

#include <stdio.h>

#include <unistd.h>
#include <sys/types.h>

#include <sys/wait.h>

int main() {

pid_t pid = fork(); // Creating a child process

if(pid < 0) {

perror("Fork failed");

return 1;

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

printf("Child Process:\n");

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

execlp("/bin/ls", "ls", NULL); // Execute 'ls' command

perror("exec failed");

else { // Parent process

wait(NULL); // Waiting for child to finish

printf("Parent Process:\n");

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

return 0;

Program 2: File Information using stat()

#include <stdio.h>

#include <sys/stat.h>
int main() {

struct stat fileStat;

if(stat("testfile.txt", &fileStat) < 0) {

perror("stat error");

return 1;

printf("File Size: %ld bytes\n", fileStat.st_size);

printf("Number of Links: %ld\n", fileStat.st_nlink);

printf("File Inode: %ld\n", fileStat.st_ino);

return 0;

Program 3: Reading Directory Contents using opendir(), readdir(), and closedir()

#include <stdio.h>

#include <dirent.h>

int main() {

DIR *dir;

struct dirent *entry;

dir = opendir("."); // Current Directory

if (dir == NULL) {

perror("opendir error");
return 1;

printf("Directory contents:\n");

while ((entry = readdir(dir)) != NULL) {

printf("%s\n", entry->d_name);

closedir(dir);

return 0;

Expected Output:

Program 1:

Child Process:

Child PID: 12345

(a list of files in the current directory)

Parent Process:

Parent PID: 12344

Program 2:

File Size: 1024 bytes

Number of Links: 1
File Inode: 9837193

Program 3:

Directory contents:

..

file1.txt

file2.c

a.out

Actual Output:

(To be filled after execution in the lab.)

Result:

The program was executed successfully. The process-related system calls (fork(), exec(),
getpid(), exit(), wait()) and file system calls (close(), stat(), opendir(), readdir()) were
implemented and the expected results were obtained.

Experiment 2: I/O System Calls in UNIX Operating System

Aim:
To write C programs using the I/O system calls of the UNIX operating system (open(),
read(), write(), close()) to perform basic file operations.

Description:
This experiment introduces file handling in UNIX through system calls. The objective is to
open or create a file, write content into it, read the content from the file, and then close it
using appropriate system calls.

Program:
#include <stdio.h>

#include <fcntl.h>

#include <unistd.h>

#include <string.h>

int main() {

int fd;

char buffer[100];

char writeData[] = "Welcome to Advanced Operating Systems Lab!";

// Open or create the file

fd = open("sample.txt", O_CREAT | O_RDWR, 0666);

if(fd < 0) {

perror("Error opening file");

return 1;

// Write data to the file

write(fd, writeData, strlen(writeData));

// Reset file offset to the beginning

lseek(fd, 0, SEEK_SET);

// Read data from the file

read(fd, buffer, sizeof(writeData));


buffer[strlen(writeData)] = '\0'; // Null-terminate the string

printf("Data read from file: %s\n", buffer);

// Close the file

close(fd);

return 0;

Expected Output:
Data read from file: Welcome to Advanced Operating Systems Lab!

Actual Output:

(To be filled after performing the experiment in the lab)

Result:
The program was successfully executed. The file was created, written to, and read from
using UNIX I/O system calls (open(), write(), read(), close()). The output matched the
expected result.

Experiment 3: Simulating UNIX Commands (like ls, grep)

Aim:
To write C programs to simulate basic UNIX commands such as ls (listing directory
contents) and grep (searching for a string in a file).

Description:
This experiment familiarizes students with directory handling and file content searching in
UNIX.

The first part simulates the functionality of ls by listing the contents of a directory.
The second part simulates the grep command by searching for a string in a file and printing
the matching lines.

Program 1: Simulate ls Command

#include <stdio.h>

#include <dirent.h>

int main() {

struct dirent *de;

DIR *dr = opendir(".");

if (dr == NULL) {

printf("Could not open current directory.\n");

return 0;

printf("Contents of current directory:\n");

while ((de = readdir(dr)) != NULL)

printf("%s\n", de->d_name);

closedir(dr);

return 0;

Program 2: Simulate grep Command

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

int main() {

FILE *fp;

char filename[100], search[100], line[200];

printf("Enter filename: ");

scanf("%s", filename);

printf("Enter the word to search: ");

scanf("%s", search);

fp = fopen(filename, "r");

if (fp == NULL) {

printf("File not found.\n");

return 0;

printf("Lines containing '%s':\n", search);

while (fgets(line, sizeof(line), fp)) {

if (strstr(line, search))

printf("%s", line);

fclose(fp);

return 0;
}

Expected Output:

For Program 1 (ls):

Contents of current directory:

..

sample.txt

a.out

program1.c

program2.c

(Contents may vary depending on the directory)

For Program 2 (grep):

Enter filename: sample.txt

Enter the word to search: Welcome

Lines containing 'Welcome':

Welcome to Advanced Operating Systems Lab!

Actual Output:

(To be filled after performing the experiment in the lab)

Result:
The program was executed successfully.

The ls simulation listed all the files and directories in the current folder.

The grep simulation successfully searched for the specified word in the given file and
displayed the matching lines.

Experiment 4: CPU Scheduling – FCFS and SJF Algorithms

Aim:
To write a C program to implement the First Come First Serve (FCFS) and Shortest Job First
(SJF) CPU scheduling algorithms and compute:

Average Waiting Time (AWT)

Average Turnaround Time (ATAT)

Also, display/print the Gantt chart.

Description:
This experiment helps students understand how different CPU scheduling algorithms affect
process execution order and CPU performance metrics like waiting time and turnaround
time.

FCFS (First Come First Serve): Processes are executed in the order they arrive.

SJF (Shortest Job First): Processes are executed based on the shortest burst time.

Program: CPU Scheduling for FCFS and SJF

#include <stdio.h>

void findWaitingTime(int n, int bt[], int wt[]) {

wt[0] = 0;

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


wt[i] = bt[i-1] + wt[i-1];

void findTurnAroundTime(int n, int bt[], int wt[], int tat[]) {

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

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

void findAverageTimeFCFS(int n, int bt[]) {

int wt[n], tat[n];

int total_wt = 0, total_tat = 0;

findWaitingTime(n, bt, wt);

findTurnAroundTime(n, bt, wt, tat);

printf("\nFCFS Scheduling:\n");

printf("Process\tBurst Time\tWaiting Time\tTurnaround Time\n");

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

total_wt += wt[i];

total_tat += tat[i];

printf("P%d\t%d\t\t%d\t\t%d\n", i+1, bt[i], wt[i], tat[i]);

printf("Average Waiting Time = %.2f\n", (float)total_wt/n);

printf("Average Turnaround Time = %.2f\n", (float)total_tat/n);

printf("Gantt Chart: ");


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

printf("P%d ", i+1);

printf("\n");

void findAverageTimeSJF(int n, int bt[]) {

int wt[n], tat[n], temp, proc[n];

int total_wt = 0, total_tat = 0;

// process IDs

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

proc[i] = i;

// Sort processes by burst time

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

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

if(bt[i] > bt[j]) {

temp = bt[i];

bt[i] = bt[j];

bt[j] = temp;

temp = proc[i];

proc[i] = proc[j];

proc[j] = temp;

}
}

findWaitingTime(n, bt, wt);

findTurnAroundTime(n, bt, wt, tat);

printf("\nSJF Scheduling:\n");

printf("Process\tBurst Time\tWaiting Time\tTurnaround Time\n");

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

total_wt += wt[i];

total_tat += tat[i];

printf("P%d\t%d\t\t%d\t\t%d\n", proc[i]+1, bt[i], wt[i], tat[i]);

printf("Average Waiting Time = %.2f\n", (float)total_wt/n);

printf("Average Turnaround Time = %.2f\n", (float)total_tat/n);

printf("Gantt Chart: ");

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

printf("P%d ", proc[i]+1);

printf("\n");

int main() {

int n, bt[20];

printf("Enter number of processes: ");

scanf("%d", &n);
printf("Enter burst time for each process:\n");

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

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

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

// Make a copy for SJF as FCFS modifies original bt

int bt_sjf[20];

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

bt_sjf[i] = bt[i];

findAverageTimeFCFS(n, bt);

findAverageTimeSJF(n, bt_sjf);

return 0;

Expected Output:

For example, if input is:

Enter number of processes: 3

Enter burst time for each process:

P1: 5

P2: 3

P3: 8
Output:

FCFS Scheduling:

Process Burst Time Waiting Time Turnaround Time

P1 5 0 5

P2 3 5 8

P3 8 8 16

Average Waiting Time = 4.33

Average Turnaround Time = 9.67

Gantt Chart: P1 P2 P3

SJF Scheduling:

Process Burst Time Waiting Time Turnaround Time

P2 3 0 3

P1 5 3 8

P3 8 8 16

Average Waiting Time = 3.67

Average Turnaround Time = 9.00

Gantt Chart: P2 P1 P3

Actual Output:

(To be filled after running the program in lab)

Result:
The C program for CPU Scheduling using FCFS and SJF policies was successfully executed.
The average waiting and turnaround times were calculated, and the Gantt charts displayed
the execution order of processes.

Experiment 5: CPU Scheduling – Priority and Round Robin


Algorithms

Aim:
To write a C program to implement Priority Scheduling and Round Robin Scheduling
algorithms.

Compute and display:

Average Waiting Time (AWT)

Average Turnaround Time (ATAT)

Display the Gantt chart for each scheduling policy.

Description:
This experiment covers:

1. Priority Scheduling: Each process is assigned a priority. Processes are executed in the
order of their priority (lower number = higher priority).

2. Round Robin Scheduling: Each process is assigned a fixed time slice (quantum). Processes
are executed in cyclic order until completion.

Program: CPU Scheduling for Priority and Round Robin

Part 1: Priority Scheduling

#include <stdio.h>

int main() {

int n, bt[20], p[20], wt[20], tat[20], pr[20], i, j, pos, temp;

int total_wt = 0, total_tat = 0;


printf("Enter number of processes: ");

scanf("%d", &n);

printf("Enter Burst Time and Priority (Lower number = higher priority):\n");

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

printf("P%d:\n", i+1);

printf("Burst Time: ");

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

printf("Priority: ");

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

p[i] = i+1; // process number

// Sorting based on priority

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

pos = i;

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

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

pos = j;

temp = pr[i];

pr[i] = pr[pos];

pr[pos] = temp;
temp = bt[i];

bt[i] = bt[pos];

bt[pos] = temp;

temp = p[i];

p[i] = p[pos];

p[pos] = temp;

wt[0] = 0; // first process waiting time is 0

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

wt[i] = 0;

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

wt[i] += bt[j];

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

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

printf("\nPriority Scheduling:\n");

printf("Process\tBurst Time\tPriority\tWaiting Time\tTurnaround Time\n");

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

total_wt += wt[i];

total_tat += tat[i];
printf("P%d\t%d\t\t%d\t\t%d\t\t%d\n", p[i], bt[i], pr[i], wt[i], tat[i]);

printf("Average Waiting Time = %.2f\n", (float)total_wt / n);

printf("Average Turnaround Time = %.2f\n", (float)total_tat / n);

printf("Gantt Chart: ");

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

printf("P%d ", p[i]);

printf("\n");

return 0;

Part 2: Round Robin Scheduling

#include <stdio.h>

int main() {

int n, i, bt[20], rem_bt[20], wt[20], tat[20], tq, time = 0;

float total_wt = 0, total_tat = 0;

printf("Enter number of processes: ");

scanf("%d", &n);

printf("Enter Burst Time for each process:\n");

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


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

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

rem_bt[i] = bt[i]; // copy burst time

printf("Enter Time Quantum: ");

scanf("%d", &tq);

while(1) {

int done = 1;

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

if(rem_bt[i] > 0) {

done = 0;

if(rem_bt[i] > tq) {

time += tq;

rem_bt[i] -= tq;

} else {

time += rem_bt[i];

wt[i] = time - bt[i];

rem_bt[i] = 0;

if(done == 1)

break;

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

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

total_wt += wt[i];

total_tat += tat[i];

printf("\nRound Robin Scheduling:\n");

printf("Process\tBurst Time\tWaiting Time\tTurnaround Time\n");

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

printf("P%d\t%d\t\t%d\t\t%d\n", i+1, bt[i], wt[i], tat[i]);

printf("Average Waiting Time = %.2f\n", total_wt/n);

printf("Average Turnaround Time = %.2f\n", total_tat/n);

return 0;

Expected Output:

Sample Input:

Enter number of processes: 3

Enter Burst Time and Priority:

P1: 10 3
P2: 1 1

P3: 2 2

Enter Time Quantum: 2

Priority Scheduling Output:

Priority Scheduling:

Process Burst Time Priority Waiting Time Turnaround Time

P2 1 1 0 1

P3 2 2 1 3

P1 10 3 3 13

Average Waiting Time = 1.33

Average Turnaround Time = 5.67

Gantt Chart: P2 P3 P1

Round Robin Scheduling Output:

Round Robin Scheduling:

Process Burst Time Waiting Time Turnaround Time

P1 10 12 22

P2 1 0 1

P3 2 1 3

Average Waiting Time = 4.33

Average Turnaround Time = 8.67

Actual Output:
(To be filled after running the program in lab)

Result:
The programs for Priority Scheduling and Round Robin Scheduling were successfully
executed. The calculated waiting times, turnaround times, and Gantt charts were displayed
as expected.

Experiment 6: Inter-Process Communication (IPC) Using Shared


Memory, Pipes, or Message Queues

Aim:
To develop an application demonstrating Inter-Process Communication (IPC) using any one
of the following methods in UNIX:

Shared Memory

Pipes

Message Queues

(This example will use Pipes for IPC.)

Description:
Inter-Process Communication (IPC) is a mechanism that allows processes to communicate
and synchronize with each other.

Pipes are used for unidirectional communication between two related processes (parent
and child). A pipe is created using the pipe() system call, and the child process can
read/write data through it.

Program: IPC using Pipes

#include <stdio.h>
#include <unistd.h>

#include <string.h>

int main() {

int fd[2]; // file descriptors: fd[0] - read, fd[1] - write

pid_t pid;

char write_msg[] = "Hello from parent to child!";

char read_msg[100];

// Create a pipe

if (pipe(fd) == -1) {

printf("Pipe failed.\n");

return 1;

pid = fork(); // create child process

if (pid < 0) {

printf("Fork failed.\n");

return 1;

if (pid > 0) { // Parent process

close(fd[0]); // Close reading end

write(fd[1], write_msg, strlen(write_msg) + 1); // Write to pipe

close(fd[1]); // Close writing end after writing


} else { // Child process

close(fd[1]); // Close writing end

read(fd[0], read_msg, sizeof(read_msg)); // Read from pipe

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

close(fd[0]); // Close reading end after reading

return 0;

Expected Output:

Child received message: Hello from parent to child!

Actual Output:

(To be filled after running the program in lab)

Result:
The program demonstrating Inter-Process Communication using Pipes was successfully
executed. The child process received the message sent by the parent process via the pipe.

Experiment 7: Producer-Consumer Problem Using Semaphores

Aim:
To write a C program to implement the Producer-Consumer problem using semaphores for
process synchronization.

Description:
The Producer-Consumer problem is a classic example of a multi-process synchronization
problem.
The Producer produces items and puts them into a buffer.

The Consumer consumes items from the buffer.

A semaphore is used to control access to the buffer to avoid race conditions and ensure
synchronization.

This implementation uses simple counting semaphores and mutex locks to solve the
problem.

Program: Producer-Consumer Problem using Semaphores

#include <stdio.h>

#include <stdlib.h>

#include <pthread.h>

#include <semaphore.h>

#include <unistd.h>

#define SIZE 5

int buffer[SIZE]; // Shared buffer

int in = 0, out = 0; // Buffer pointers

sem_t full, empty; // Semaphores

pthread_mutex_t mutex; // Mutex lock

void *producer(void *arg) {

int item;

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

item = rand() % 100; // Random item

sem_wait(&empty); // Decrease empty count


pthread_mutex_lock(&mutex); // Lock

buffer[in] = item;

printf("Producer produced: %d at buffer[%d]\n", item, in);

in = (in + 1) % SIZE;

pthread_mutex_unlock(&mutex); // Unlock

sem_post(&full); // Increase full count

sleep(1); // Simulate time delay

void *consumer(void *arg) {

int item;

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

sem_wait(&full); // Decrease full count

pthread_mutex_lock(&mutex); // Lock

item = buffer[out];

printf("Consumer consumed: %d from buffer[%d]\n", item, out);

out = (out + 1) % SIZE;

pthread_mutex_unlock(&mutex); // Unlock

sem_post(&empty); // Increase empty count


sleep(1); // Simulate time delay

int main() {

pthread_t prod, cons;

// Initialize semaphores

sem_init(&empty, 0, SIZE);

sem_init(&full, 0, 0);

pthread_mutex_init(&mutex, NULL);

// Create producer and consumer threads

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

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

// Wait for threads to finish

pthread_join(prod, NULL);

pthread_join(cons, NULL);

// Destroy semaphores and mutex

sem_destroy(&empty);

sem_destroy(&full);

pthread_mutex_destroy(&mutex);

return 0;
}

Expected Output:

Producer produced: 57 at buffer[0]

Consumer consumed: 57 from buffer[0]

Producer produced: 23 at buffer[1]

Consumer consumed: 23 from buffer[1]

Producer produced: 89 at buffer[2]

Consumer consumed: 89 from buffer[2]

Producer produced: 15 at buffer[3]

Consumer consumed: 15 from buffer[3]

Producer produced: 62 at buffer[4]

Consumer consumed: 62 from buffer[4]

(Note: Random values will change for every execution)

Actual Output:

(To be filled after running the program in lab)

Result:
The program for solving the Producer-Consumer problem using Semaphores was
successfully implemented. The synchronization ensured no race conditions occurred
between the producer and consumer threads.

You might also like