Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
19 views21 pages

Operating System Lab

The document outlines the objectives and theoretical foundations of an Operating System lab, focusing on the hardware and software requirements of various operating systems including UNIX, LINUX, and Windows versions. It details experiments involving UNIX system calls for process and file management, as well as CPU scheduling policies such as FCFS, SJF, and Priority. The document includes code examples for implementing these concepts in practice.
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)
19 views21 pages

Operating System Lab

The document outlines the objectives and theoretical foundations of an Operating System lab, focusing on the hardware and software requirements of various operating systems including UNIX, LINUX, and Windows versions. It details experiments involving UNIX system calls for process and file management, as well as CPU scheduling policies such as FCFS, SJF, and Priority. The document includes code examples for implementing these concepts in practice.
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/ 21

Operating System Lab

Experiment 1
Objective:- Study of hardware and software requirements of different Operating
systems(UNIX, LINUX, Windows XP, Windows7/8)
Theory:-
Operating System: An Operating System (OS) is system software that manages
computer hardware and software resources while providing a user interface. It handles
key tasks like process management, memory management, file systems, I/O control,
and device management. Types of OS include batch, time-sharing, distributed, real-
time, network, and mobile OS. Core OS components are the kernel, shell, system calls,
and device drivers. It uses scheduling algorithms (like FCFS, Round Robin, SJF) to
manage multiple processes efficiently. Concepts like threads, virtual memory, paging,
and segmentation help in multitasking and memory utilization. OS ensures security and
protection via authentication, authorization, and access control, and handles deadlocks
using prevention, avoidance (e.g., Banker's algorithm), or detection and recovery
strategies.

1. UNIX
• Hardware Requirements:
o CPU: Varies (mostly used on servers/mainframes)
o RAM: Minimum 64 MB (depends on distribution)
o HDD: Around 500 MB to several GBs
• Software Requirements:
o Shell (e.g., Bourne, C shell)
o Compilers (e.g., GCC)
o File system support (UFS, ext, etc.
2. LINUX
• Hardware Requirements:
o CPU: 500 MHz or higher
o RAM: Minimum 128 MB (512 MB recommended)
o HDD: 2 GB minimum (varies by distro)
• Software Requirements:
o Linux Kernel
o GNU utilities and libraries
o GUI (optional, e.g., GNOME, KDE)
o Package manager (e.g., APT, YUM)
3. Windows XP
• Hardware Requirements:
o CPU: 233 MHz (300 MHz recommended)
o RAM: 64 MB (128 MB recommended)
o HDD: 1.5 GB of free space
• Software Requirements:
o DirectX support
o Internet Explorer 6
o Device drivers (specific to hardware)
4. Windows 7
• Hardware Requirements:
o CPU: 1 GHz (32-bit or 64-bit)
o RAM: 1 GB (32-bit) / 2 GB (64-bit)
o HDD: 16 GB (32-bit) / 20 GB (64-bit)
• Software Requirements:
o .NET Framework
o DirectX 9 graphics device
o Windows Installer
5. Windows 8
• Hardware Requirements:
o CPU: 1 GHz with PAE, NX, SSE2
o RAM: 1 GB (32-bit) / 2 GB (64-bit)
o HDD: 16 GB (32-bit) / 20 GB (64-bit)
• Software Requirements:
o .NET Framework 3.5 and 4.5
o DirectX 9 or later
o Secure Boot (for some editions)
Experiment 2
Objective:- Execution of various UNIX system calls for:
1. Process management
2. File management
3. Input/Output System calls
Theory:-
Process Management:
Process Management is a fundamental function of an Operating System (OS) that deals with
the creation, scheduling, and termination of processes.

UNIX System
Function Description Windows API
Call

Process Creation Creates a new process fork() CreateProcess()

Ends a process and frees


Process Termination exit() ExitProcess()
resources

Process Wait Waits for a child process to finish wait() / waitpid() WaitForSingleObject()

Get Process ID Returns process ID getpid() GetCurrentProcessId()

Process Sleep Delays process execution sleep() Sleep()

Code:-
#include <stdio.h>
#include <stdlib.h>

int main() {
printf("Parent process running...\n");

// Create a new process to run 'ls'


int status = system("ls"); // executes shell command
if (status == -1) {
perror("system() failed");
}

printf("Back to parent process after child finished.\n");


return 0;
}
File Management:
File Management is a core function of the operating system that involves the creation,
organization, storage, retrieval, naming, sharing, and protection of files on storage devices.

Function Description UNIX System Call Windows API

File Creation Creates a new file creat(), open() CreateFile()

File Opening Opens an existing file for read/write open() CreateFile()

File Reading Reads data from a file read() ReadFile()

File Writing Writes data to a file write() WriteFile()

File Closing Closes an open file descriptor close() CloseHandle()

File Renaming Changes file name rename() MoveFile() / MoveFileEx()

Code:-
#include <stdio.h>
int main() {
FILE *fp;
char content[100];
// Writing to a file
fp = fopen("example.txt", "w");
if (fp == NULL) {
perror("File open for write failed");
return 1;
}
fprintf(fp, "This is a test file written using standard I/O.\n");
fclose(fp);
// Reading from the file
fp = fopen("example.txt", "r");
if (fp == NULL) {
perror("File open for read failed");
return 1;
}
printf("Reading file content:\n");
while (fgets(content, sizeof(content), fp) != NULL) {
printf("%s", content);
}
fclose(fp);
return 0;
}
Input/Output System calls:
I/O system calls are functions provided by the operating system that allow user-level
programs to perform input and output operations by interacting with hardware devices (like
keyboard, mouse, disk, or screen).

UNIX System
Function Description Windows API
Call

Device Open Opens a device for I/O open() CreateFile()

Read Input Reads input from device/file read() ReadFile()

Write Output Sends output to device/file write() WriteFile()

Close Device/File Closes an I/O stream close() CloseHandle()

Sends control commands to


I/O Control ioctl() DeviceIoControl()
device

Select/Monitor
Monitors multiple I/O streams select() / poll() WaitForMultipleObjects()
I/O

Code:-
#include <stdio.h>

int main() {
char name[50];

printf("Enter your name: ");


fgets(name, sizeof(name), stdin); // read string with spaces

printf("Hello, %s", name);


return 0;
}
Experiment – 3
Objective:- Implement CPU Scheduling Policies
i. FCFS
ii. SJF
iii. Priority
iv. Multilevel - Queue
i. FCFS
#include <stdio.h>

struct Process {
int pid; // Process ID
int arrivalTime; // Arrival time of process
int burstTime; // Burst time (execution time)
int startTime; // Time when process starts execution
int completionTime; // Time when process finishes
int waitingTime; // Waiting time
int turnaroundTime; // Turnaround time
};

int main() {
int n, i, j;
printf("Enter number of processes: ");
scanf("%d", &n);

struct Process p[n];


struct Process temp;

// Input process details


for(i = 0; i < n; i++) {
p[i].pid = i + 1;
printf("Enter Arrival Time and Burst Time for Process %d: ", p[i].pid);
scanf("%d %d", &p[i].arrivalTime, &p[i].burstTime);
}

// Sort processes based on arrival time (simple bubble sort)


for(i = 0; i < n - 1; i++) {
for(j = 0; j < n - i - 1; j++) {
if(p[j].arrivalTime > p[j + 1].arrivalTime) {
temp = p[j];
p[j] = p[j + 1];
p[j + 1] = temp;
}
}
}

int currentTime = 0;
float totalWaitingTime = 0, totalTurnaroundTime = 0;

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


// If CPU is idle, move current time to arrival time of process
if(currentTime < p[i].arrivalTime) {
currentTime = p[i].arrivalTime;
}

p[i].startTime = currentTime;
p[i].completionTime = p[i].startTime + p[i].burstTime;
p[i].turnaroundTime = p[i].completionTime - p[i].arrivalTime;
p[i].waitingTime = p[i].startTime - p[i].arrivalTime;

currentTime = p[i].completionTime;

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

// Print table headers


printf("\nPID\tAT\tBT\tST\tCT\tWT\tTAT\n");
for(i = 0; i < n; i++) {
printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
p[i].pid, p[i].arrivalTime, p[i].burstTime,
p[i].startTime, p[i].completionTime,
p[i].waitingTime, p[i].turnaroundTime);
}

printf("\nAverage Waiting Time: %.2f\n", totalWaitingTime / n);


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

return 0;
}
SAMPLE INPUT:
Enter number of processes: 4
Enter Arrival Time and Burst Time for Process 1: 0 5
Enter Arrival Time and Burst Time for Process 2: 1 3
Enter Arrival Time and Burst Time for Process 3: 2 8
Enter Arrival Time and Burst Time for Process 4: 3 6

SAMPLE OUTPUT:
PIDAT BT ST CT WT TAT
1 0 5 0 5 0 5
2 1 3 5 8 4 7
3 2 8 8 16 6 14
4 3 6 16 22 13 19

Average Waiting Time: 5.75


Average Turnaround Time: 11.25
ii. SJF
#include <stdio.h>

struct Process {
int pid; // Process ID
int arrivalTime; // Arrival time of process
int burstTime; // Burst time (execution time)
int startTime; // Time when process starts execution
int completionTime; // Time when process finishes
int waitingTime; // Waiting time
int turnaroundTime; // Turnaround time
int isCompleted; // Flag to check if process is completed
};

int main() {
int n, i;
printf("Enter number of processes: ");
scanf("%d", &n);

struct Process p[n];

// Input process details


for(i = 0; i < n; i++) {
p[i].pid = i + 1;
printf("Enter Arrival Time and Burst Time for Process %d: ", p[i].pid);
scanf("%d %d", &p[i].arrivalTime, &p[i].burstTime);
p[i].isCompleted = 0; // Initially all processes are incomplete
}

int completed = 0, currentTime = 0;


float totalWaitingTime = 0, totalTurnaroundTime = 0;

while(completed != n) {
int idx = -1;
int minBurst = 100000; // A large number to find minimum

// Find process with minimum burst time among arrived and not completed
processes
for(i = 0; i < n; i++) {
if(p[i].arrivalTime <= currentTime && !p[i].isCompleted) {
if(p[i].burstTime < minBurst) {
minBurst = p[i].burstTime;
idx = i;
}
// If burst times are equal, choose process with earlier arrival time
else if(p[i].burstTime == minBurst) {
if(p[i].arrivalTime < p[idx].arrivalTime) {
idx = i;
}
}
}
}

if(idx != -1) {
// Start executing this process
p[idx].startTime = currentTime;
p[idx].completionTime = p[idx].startTime + p[idx].burstTime;
p[idx].turnaroundTime = p[idx].completionTime - p[idx].arrivalTime;
p[idx].waitingTime = p[idx].startTime - p[idx].arrivalTime;
p[idx].isCompleted = 1;

currentTime = p[idx].completionTime;
completed++;

totalWaitingTime += p[idx].waitingTime;
totalTurnaroundTime += p[idx].turnaroundTime;
} else {
// No process has arrived yet, move time forward
currentTime++;
}
}

// Print the result table


printf("\nPID\tAT\tBT\tST\tCT\tWT\tTAT\n");
for(i = 0; i < n; i++) {
printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
p[i].pid, p[i].arrivalTime, p[i].burstTime,
p[i].startTime, p[i].completionTime,
p[i].waitingTime, p[i].turnaroundTime);
}

printf("\nAverage Waiting Time: %.2f\n", totalWaitingTime / n);


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

return 0;
}

SAMPLE INPUT:
Enter number of processes: 4
Enter Arrival Time and Burst Time for Process 1: 0 7
Enter Arrival Time and Burst Time for Process 2: 2 4
Enter Arrival Time and Burst Time for Process 3: 4 1
Enter Arrival Time and Burst Time for Process 4: 5 4

SAMPLE OUTPUT:
PIDAT BT ST CT WT TAT
1 0 7 0 7 0 7
2 2 4 7 11 5 9
3 4 1 11 12 7 8
4 5 4 12 16 7 11
Average Waiting Time: 4.75
Average Turnaround Time: 8.75

iii. Priority:
#include <stdio.h>

struct Process {
int pid; // Process ID
int arrivalTime; // Time when process arrives
int burstTime; // CPU burst time
int priority; // Lower number = higher priority
int startTime; // Time when process starts
int completionTime; // Time when process ends
int waitingTime; // Waiting = Start - Arrival
int turnaroundTime; // Turnaround = Completion - Arrival
int isCompleted; // Flag to mark process as completed
};

int main() {
int n, i;
printf("Enter number of processes: ");
scanf("%d", &n);

struct Process p[n];

// Taking input
for(i = 0; i < n; i++) {
p[i].pid = i + 1;
printf("Enter Arrival Time, Burst Time, Priority (lower = higher priority) for Process
%d: ", p[i].pid);
scanf("%d %d %d", &p[i].arrivalTime, &p[i].burstTime, &p[i].priority);
p[i].isCompleted = 0;
}

int completed = 0, currentTime = 0;


float totalWT = 0, totalTAT = 0;

while(completed != n) {
int idx = -1;
int highestPriority = 100000;

// Find the highest priority process among arrived and incomplete ones
for(i = 0; i < n; i++) {
if(p[i].arrivalTime <= currentTime && !p[i].isCompleted) {
if(p[i].priority < highestPriority) {
highestPriority = p[i].priority;
idx = i;
}
// If same priority, choose process with earlier arrival
else if(p[i].priority == highestPriority) {
if(p[i].arrivalTime < p[idx].arrivalTime) {
idx = i;
}
}
}
}

if(idx != -1) {
p[idx].startTime = currentTime;
p[idx].completionTime = p[idx].startTime + p[idx].burstTime;
p[idx].turnaroundTime = p[idx].completionTime - p[idx].arrivalTime;
p[idx].waitingTime = p[idx].startTime - p[idx].arrivalTime;
p[idx].isCompleted = 1;

currentTime = p[idx].completionTime;
completed++;

totalWT += p[idx].waitingTime;
totalTAT += p[idx].turnaroundTime;
} else {
currentTime++; // If no process has arrived yet
}
}

// Output
printf("\nPID\tAT\tBT\tPR\tST\tCT\tWT\tTAT\n");
for(i = 0; i < n; i++) {
printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
p[i].pid, p[i].arrivalTime, p[i].burstTime, p[i].priority,
p[i].startTime, p[i].completionTime,
p[i].waitingTime, p[i].turnaroundTime);
}

printf("\nAverage Waiting Time: %.2f", totalWT / n);


printf("\nAverage Turnaround Time: %.2f\n", totalTAT / n);

return 0;
}

Sample Input:
Enter number of processes: 4
Enter Arrival Time, Burst Time, Priority (lower = higher priority) for Process 1: 0 5 2
Enter Arrival Time, Burst Time, Priority (lower = higher priority) for Process 2: 1 3 1
Enter Arrival Time, Burst Time, Priority (lower = higher priority) for Process 3: 2 8 4
Enter Arrival Time, Burst Time, Priority (lower = higher priority) for Process 4: 3 6 2
Sample Output:
PID AT BT PR ST CT WT TAT
1 0 5 2 0 5 0 5
2 1 3 1 5 8 4 7
4 3 6 2 8 14 5 11
3 2 8 4 14 22 12 20

Average Waiting Time: 5.25


Average Turnaround Time: 10.75

iv. Multilevel – Oueue


#include <stdio.h>

struct Process {
int pid;
int burstTime;
int queueNumber; // 1: High, 2: Medium, 3: Low
int startTime;
int completionTime;
int arrivalTime;
int waitingTime;
int turnaroundTime;
int isCompleted;
};

int main() {
int n, i;
printf("Enter number of processes: ");
scanf("%d", &n);

struct Process p[n];


// Input: Arrival Time, Burst Time, Queue Number
for (i = 0; i < n; i++) {
p[i].pid = i + 1;
printf("Enter Arrival Time, Burst Time, and Queue Number (1-High, 2-Medium, 3-Low) for
Process %d: ", p[i].pid);
scanf("%d %d %d", &p[i].arrivalTime, &p[i].burstTime, &p[i].queueNumber);
p[i].isCompleted = 0;
}

int currentTime = 0, completed = 0;


float totalWT = 0, totalTAT = 0;

while (completed != n) {
int idx = -1;
int minQueue = 4; // 1 is highest priority

// Find process with earliest arrival and highest priority that has arrived
for (i = 0; i < n; i++) {
if (p[i].arrivalTime <= currentTime && !p[i].isCompleted) {
if (p[i].queueNumber < minQueue) {
minQueue = p[i].queueNumber;
idx = i;
} else if (p[i].queueNumber == minQueue) {
// If same queue, pick one that arrived earlier
if (p[i].arrivalTime < p[idx].arrivalTime) {
idx = i;
}
}
}
}

if (idx != -1) {
p[idx].startTime = currentTime;
p[idx].completionTime = p[idx].startTime + p[idx].burstTime;
p[idx].turnaroundTime = p[idx].completionTime - p[idx].arrivalTime;
p[idx].waitingTime = p[idx].startTime - p[idx].arrivalTime;
p[idx].isCompleted = 1;

currentTime = p[idx].completionTime;
completed++;

totalWT += p[idx].waitingTime;
totalTAT += p[idx].turnaroundTime;
} else {
currentTime++; // If no process has arrived yet
}
}

// Output the table


printf("\nPID\tAT\tBT\tQ\tST\tCT\tWT\tTAT\n");
for (i = 0; i < n; i++) {
printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
p[i].pid, p[i].arrivalTime, p[i].burstTime, p[i].queueNumber,
p[i].startTime, p[i].completionTime,
p[i].waitingTime, p[i].turnaroundTime);
}

printf("\nAverage Waiting Time: %.2f", totalWT / n);


printf("\nAverage Turnaround Time: %.2f\n", totalTAT / n);

return 0;
}
Experiment – 4
Objective: Implement the solution for the Bounded Buffer (producer-consumer) problem using inter-
process communication techniques - Semaphores.
Theory: The Bounded Buffer Problem, also known as the Producer-Consumer Problem, is a
classic example of a synchronization problem in operating systems. It involves two types
of processes:

• Producer: Generates data and puts it into a shared buffer.


• Consumer: Takes data from the buffer for processing.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

#define SIZE 5 // Size of buffer

int buffer[SIZE]; // Shared buffer


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

sem_t empty; // Semaphore for empty slots


sem_t full; // Semaphore for filled slots
sem_t mutex; // Mutex for critical section

// Function to simulate a producer


void* producer(void* arg) {
int item;
for (int i = 0; i < 10; i++) {
item = rand() % 100; // Produce item

sem_wait(&empty); // Decrement empty count


sem_wait(&mutex); // Enter critical section
// Add item to buffer
buffer[in] = item;
printf("Producer produced: %d\n", item);
in = (in + 1) % SIZE;

sem_post(&mutex); // Exit critical section


sem_post(&full); // Increment full count

sleep(1); // Simulate production time


}

pthread_exit(NULL);
}

// Function to simulate a consumer


void* consumer(void* arg) {
int item;
for (int i = 0; i < 10; i++) {
sem_wait(&full); // Decrement full count
sem_wait(&mutex); // Enter critical section

// Remove item from buffer


item = buffer[out];
printf("Consumer consumed: %d\n", item);
out = (out + 1) % SIZE;

sem_post(&mutex); // Exit critical section


sem_post(&empty); // Increment empty count

sleep(2); // Simulate consumption time


}
pthread_exit(NULL);
}

int main() {
pthread_t prod, cons;

// Initialize semaphores
sem_init(&empty, 0, SIZE); // All slots empty at start
sem_init(&full, 0, 0); // No items at start
sem_init(&mutex, 0, 1); // Binary semaphore (mutex)

// 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
sem_destroy(&empty);
sem_destroy(&full);
sem_destroy(&mutex);
return 0;
}
Sample Output:
Producer produced: 43
Consumer consumed: 43
Producer produced: 11
Producer produced: 67
Consumer consumed: 11
Producer produced: 34
Consumer consumed: 67
Experiment – 5
Objective: Implement the solutions for the reader–writer problem using the inter-process
communication technique Semaphore.
Theory: The Reader–Writer Problem is a classic synchronization problem in operating systems where
multiple readers can access a shared resource simultaneously, but writers must have exclusive access.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

sem_t mutex; // Controls access to read_count


sem_t write_sem; // Controls access to the shared resource

int read_count = 0; // Number of active readers

// Simulate shared data


int shared_data = 0;

void* reader(void* arg) {


int id = *((int*)arg);

// Entry section for reader


sem_wait(&mutex);
read_count++;
if (read_count == 1) {
sem_wait(&write_sem); // First reader locks the resource
}
sem_post(&mutex);

// Critical section (reading)


printf("Reader %d is reading data = %d\n", id, shared_data);
sleep(1); // simulate read time

// Exit section for reader


sem_wait(&mutex);
read_count--;
if (read_count == 0) {
sem_post(&write_sem); // Last reader releases the resource
}
sem_post(&mutex);

pthread_exit(NULL);
}

void* writer(void* arg) {


int id = *((int*)arg);

// Entry section for writer


sem_wait(&write_sem); // Writer locks the resource

// Critical section (writing)


shared_data += 10;
printf("Writer %d is writing data = %d\n", id, shared_data);
sleep(2); // simulate write time

// Exit section for writer


sem_post(&write_sem); // Writer releases the resource

pthread_exit(NULL);
}

int main() {
pthread_t r[5], w[3];
int i;
int reader_ids[5] = {1, 2, 3, 4, 5};
int writer_ids[3] = {1, 2, 3};

// Initialize semaphores
sem_init(&mutex, 0, 1);
sem_init(&write_sem, 0, 1);

// Create reader and writer threads


for (i = 0; i < 3; i++) {
pthread_create(&w[i], NULL, writer, &writer_ids[i]);
pthread_create(&r[i], NULL, reader, &reader_ids[i]);
}

// Create additional readers


for (i = 3; i < 5; i++) {
pthread_create(&r[i], NULL, reader, &reader_ids[i]);
}

// Wait for threads to complete


for (i = 0; i < 3; i++) {
pthread_join(w[i], NULL);
pthread_join(r[i], NULL);
}
for (i = 3; i < 5; i++) {
pthread_join(r[i], NULL);
}
// Destroy semaphores
sem_destroy(&mutex);
sem_destroy(&write_sem);
return 0;
}

You might also like