0% found this document useful (0 votes)
18 views23 pages

OS - LAB Manual

The document contains C programming examples demonstrating various UNIX system calls, process management, thread concepts, CPU scheduling algorithms, IPC techniques, and solutions to classical synchronization problems. It includes code snippets for file management, process forking, threading, and different scheduling algorithms like FCFS, SJF, and Round Robin. Additionally, it covers IPC methods such as pipes, message queues, and shared memory, along with synchronization problems like the Dining Philosophers and Producer-Consumer problems.

Uploaded by

Deepak Chauhan
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)
18 views23 pages

OS - LAB Manual

The document contains C programming examples demonstrating various UNIX system calls, process management, thread concepts, CPU scheduling algorithms, IPC techniques, and solutions to classical synchronization problems. It includes code snippets for file management, process forking, threading, and different scheduling algorithms like FCFS, SJF, and Round Robin. Additionally, it covers IPC methods such as pipes, message queues, and shared memory, along with synchronization problems like the Dining Philosophers and Producer-Consumer problems.

Uploaded by

Deepak Chauhan
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/ 23

Unit Contents

I Write C programs to implement UNIX system calls and file


management.
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>

int main()
{
int n, fd;
char buff[50]; // declaring buffer

// Message printing on the display


printf("Enter text to write in the file:\n");
// Read from keyboard, specifying 0 as fd for std input device
// Here, n stores the number of characters
n = read(0, buff, 50);

// creating a new file using open.


fd = open("file", O_CREAT | O_RDWR, 0777);

// Writting input data to file (fd)


write(fd, buff, n);
// Write to display (1 is standard fd for output device)
write(1, buff, n);

// closing the file


int close(int fd);

return 0;
}

II Write C programs to demonstrate various process related concepts.


Fork system call in C

#include <stdio.h>
#include <unistd.h>
int main()
{
pid_t b; // note that the actual return type of fork is
// pid_t, though it's probably just an int typedef'd or macro'd

b = fork();
if (b <0)
{
perror("Fork failed");
}
else if (b == 0) {
printf("Hello from Child \n"); // child process
else
printf("Hello from Parent \n"); // parent process

printf("The value of b is %d\n", b);


return 0;
}

Pipe system call in C

#include <stdio.h>
#include <unistd.h>
#define MSGSIZE 16
char* msg1 = "hello, world #1";
char* msg2 = "hello, world #2";
char* msg3 = "hello, world #3";

int main()
{
char inbuf[MSGSIZE];
int p[2], i;

if (pipe(p) < 0)
exit(1);

/* continued */
/* write pipe */

write(p[1], msg1, MSGSIZE);


write(p[1], msg2, MSGSIZE);
write(p[1], msg3, MSGSIZE);

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


/* read pipe */
read(p[0], inbuf, MSGSIZE);
printf("% s\n", inbuf);
}
return 0;
}

III Write C programs to demonstrate various thread related concepts.


#include <stdio.h>
#include <pthread.h>
# define NC "\e[0m"
# define YELLOW "\e[1;33m"

// thread_routine is the function the thread invokes right after its creation. The
thread ends at the end of this function.

void *thread_routine(void *data)


{
pthread_t tid;

// The pthread_self() function provides this thread's own ID.


tid = pthread_self();

printf("%sThread [%ld]: The heaviest burden is to exist without


living.%s\n",YELLOW, tid, NC);
return (NULL); // The thread ends here.
}

int main(void)
{
pthread_t tid1; // First thread's ID
pthread_t tid2; // Second thread's ID

// creating the first thread that will go execute its thread routine function.

pthread_create(&tid1, NULL, thread_routine, NULL);


printf("Main: Created first thread [%ld]\n", tid1);

// creating the second thread that will also execute thread routine.

pthread_create(&tid2, NULL, thread_routine, NULL);


printf("Main: Created second thread [%ld]\n", tid2);

// the main thread waits for the new threads to end with pthread_join.

pthread_join(tid1, NULL);
printf("Main: Joining first thread [%ld]\n", tid1);
pthread_join(tid2, NULL);
printf("Main: Joining second thread [%ld]\n", tid2);
return (0);
}

IV Write C programs to simulate CPU scheduling algorithms: FCFS,


SJF, and Round Robin.
FCFS

#include <stdio.h>
int main()
{
int pid[15];
int bt[15];
int n;
printf("Enter the number of processes: ");
scanf("%d",&n);

printf("Enter process id of all the processes: ");


for(int i=0;i<n;i++)
{
scanf("%d",&pid[i]);
}

printf("Enter burst time of all the processes: ");


for(int i=0;i<n;i++)
{
scanf("%d",&bt[i]);
}

int i, wt[n];
wt[0]=0;

//for calculating waiting time of each process


for(i=1; i<n; i++)
{
wt[i]= bt[i-1]+ wt[i-1];
}

printf("Process ID Burst Time Waiting Time TurnAround Time\n");


float twt=0.0;
float tat= 0.0;
for(i=0; i<n; i++)
{
printf("%d\t\t", pid[i]);
printf("%d\t\t", bt[i]);
printf("%d\t\t", wt[i]);

//calculating and printing turnaround time of each process


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

//for calculating total waiting time


twt += wt[i];

//for calculating total turnaround time


tat += (wt[i]+bt[i]);
}
float att,awt;
//for calculating average waiting time
awt = twt/n;
//for calculating average turnaround time
att = tat/n;
printf("Avg. waiting time= %f\n",awt);
printf("Avg. turnaround time= %f",att);
}

SJF

#include <stdio.h>
int main()
{
// Matrix for storing Process Id, Burst
// Time, Average Waiting Time & Average
// Turn Around Time.
int A[100][4];
int i, j, n, total = 0, index, temp;
float avg_wt, avg_tat;
printf("Enter number of process: ");
scanf("%d", &n);
printf("Enter Burst Time:\n");
// User Input Burst Time and alloting Process Id.
for (i = 0; i < n; i++) {
printf("P%d: ", i + 1);
scanf("%d", &A[i][1]);
A[i][0] = i + 1;
}
// Sorting process according to their Burst Time.
for (i = 0; i < n; i++) {
index = i;
for (j = i + 1; j < n; j++)
if (A[j][1] < A[index][1])
index = j;
temp = A[i][1];
A[i][1] = A[index][1];
A[index][1] = temp;

temp = A[i][0];
A[i][0] = A[index][0];
A[index][0] = temp;
}
A[0][2] = 0;
// Calculation of Waiting Times
for (i = 1; i < n; i++) {
A[i][2] = 0;
for (j = 0; j < i; j++)
A[i][2] += A[j][1];
total += A[i][2];
}
avg_wt = (float)total / n;
total = 0;
printf("P BT WT TAT\n");
// Calculation of Turn Around Time and printing the
// data.
for (i = 0; i < n; i++) {
A[i][3] = A[i][1] + A[i][2];
total += A[i][3];
printf("P%d %d %d %d\n", A[i][0],A[i][1], A[i][2], A[i][3]);
}
avg_tat = (float)total / n;
printf("Average Waiting Time= %f", avg_wt);
printf("\nAverage Turnaround Time= %f", avg_tat);
}

Round Robin
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>

struct P
{
int AT, BT, ST[20], WT, FT, TAT, pos;
};

int quant;
int main()
{
int n, i, j;
// Taking Input
printf("Enter the no. of processes :");
scanf("%d", &n);
struct P p[n];

printf("Enter the quantum \n");


scanf("%d", &quant);

printf("Enter the process numbers \n");


for (i = 0; i < n; i++)
scanf("%d", &(p[i].pos));

printf("Enter the Arrival time of processes \n");


for (i = 0; i < n; i++)
scanf("%d", &(p[i].AT));

printf("Enter the Burst time of processes \n");


for (i = 0; i < n; i++)
scanf("%d", &(p[i].BT));

// Declaring variables
int c = n, s[n][20];
float time = 0, mini = INT_MAX, b[n], a[n];

// Initializing burst and arrival time arrays


int index = -1;
for (i = 0; i < n; i++)
{
b[i] = p[i].BT;
a[i] = p[i].AT;
for (j = 0; j < 20; j++)
{
s[i][j] = -1;
}
}

int tot_wt, tot_tat;


tot_wt = 0;
tot_tat = 0;
bool flag = false;

while (c != 0)
{

mini = INT_MAX;
flag = false;

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


{
float p = time + 0.1;
if (a[i] <= p && mini > a[i] && b[i] > 0)
{
index = i;
mini = a[i];
flag = true;
}
}
// if at =1 then loop gets out hence set flag to false
if (!flag)
{
time++;
continue;
}

// calculating start time


j = 0;

while (s[index][j] != -1)


{
j++;
}

if (s[index][j] == -1)
{
s[index][j] = time;
p[index].ST[j] = time;
}

if (b[index] <= quant)


{
time += b[index];
b[index] = 0;
}
else
{
time += quant;
b[index] -= quant;
}

if (b[index] > 0)
{
a[index] = time + 0.1;
}

// calculating arrival,burst,final times


if (b[index] == 0)
{
c--;
p[index].FT = time;
p[index].WT = p[index].FT - p[index].AT - p[index].BT;
tot_wt += p[index].WT;
p[index].TAT = p[index].BT + p[index].WT;
tot_tat += p[index].TAT;
}

} // end of while loop

// Printing output
printf("Process number ");
printf("Arrival time ");
printf("Burst time ");
printf("\tStart time");
j = 0;
while (j != 10)
{
j += 1;
printf(" ");
}
printf("\t\tFinal time");
printf("\tWait Time ");
printf("\tTurnAround Time \n");

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


{
printf("%d \t\t", p[i].pos);
printf("%d \t\t", p[i].AT);
printf("%d \t", p[i].BT);
j = 0;
int v = 0;
while (s[i][j] != -1)
{
printf("%d ", p[i].ST[j]);
j++;
v += 3;
}
while (v != 40)
{
printf(" ");
v += 1;
}
printf("%d \t\t", p[i].FT);
printf("%d \t\t", p[i].WT);
printf("%d \n", p[i].TAT);
}

// Calculating average wait time and turnaround time


double avg_wt, avg_tat;
avg_wt = tot_wt / (float)n;
avg_tat = tot_tat / (float)n;

// Printing average wait time and turnaround time


printf("The average wait time is : %lf\n", avg_wt);
printf("The average TurnAround time is : %lf\n", avg_tat);

return 0;
}

V Write C programs to simulate Intra & Inter – Process


Communication (IPC) techniques: Pipes, Messages Queues, and
Shared Memory.

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

int main() {
intpipefds[2];
intreturnstatus;
charwritemessages[2][20]={"Hi", "Hello"};
charreadmessage[20];
returnstatus = pipe(pipefds);

if (returnstatus == -1) {
printf("Unable to create pipe\n");
return 1;
}

printf("Writing to pipe - Message 1 is %s\n", writemessages[0]);


write(pipefds[1], writemessages[0], sizeof(writemessages[0]));
read(pipefds[0], readmessage, sizeof(readmessage));
printf("Reading from pipe – Message 1 is %s\n", readmessage);
printf("Writing to pipe - Message 2 is %s\n", writemessages[0]);
write(pipefds[1], writemessages[1], sizeof(writemessages[0]));
read(pipefds[0], readmessage, sizeof(readmessage));
printf("Reading from pipe – Message 2 is %s\n", readmessage);
return 0;
}

Messages Queues
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
// structure for message queue
structmsg_buffer {
longmsg_type;
charmsg[100];
} message;
main() {
key_tmy_key;
intmsg_id;
my_key = ftok("progfile", 65); //create unique key
msg_id = msgget(my_key, 0666 | IPC_CREAT); //create message queue and
return id
message.msg_type = 1;
printf("Write Message : ");
fgets(message.msg, 100, stdin);
msgsnd(msg_id, &message, sizeof(message), 0); //send message
printf("Sent message is : %s \n", message.msg);
}

Shared Memory
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/shm.h>
#include<string.h>
int main()
{
int i;
void *shared_memory;
char buff[100];
intshmid;
shmid=shmget((key_t)2345, 1024, 0666|IPC_CREAT);
//creates shared memory segment with key 2345, having size 1024 bytes.
IPC_CREAT is used to create the shared segment if it does not exist. 0666 are
the permissions on the shared segment
printf("Key of shared memory is %d\n",shmid);
shared_memory=shmat(shmid,NULL,0);
//process attached to shared memory segment
printf("Process attached at %p\n",shared_memory);
//this prints the address where the segment is attached with this process
printf("Enter some data to write to shared memory\n");
read(0,buff,100); //get some input from user
strcpy(shared_memory,buff); //data written to shared memory
printf("You wrote : %s\n",(char *)shared_memory);
}

VI Write C programs to simulate solutions to Classical Process


Synchronization Problems. Dining Philosophers, Producer –
Consumer, Readers – Writers.
Dining Philosophers

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

#define NUM_PHILOSOPHERS 5

sem_t forks[NUM_PHILOSOPHERS];
sem_t mutex; // For mutual exclusion while printing

void think(int philosopher) {


printf("Philosopher %d is thinking\n", philosopher);
sleep(1);
}

void eat(int philosopher) {


printf("Philosopher %d is eating\n", philosopher);
sleep(2);
}

void* philosopher(void* arg) {


int philosopher = *(int*)arg;
int left_fork = philosopher;
int right_fork = (philosopher + 1) % NUM_PHILOSOPHERS;

while (1) {
think(philosopher);

sem_wait(&forks[left_fork]); // Pick up left fork


sem_wait(&forks[right_fork]); // Pick up right fork
sem_wait(&mutex); // Enter critical section
eat(philosopher);
sem_post(&mutex); // Exit critical section

sem_post(&forks[left_fork]); // Put down left fork


sem_post(&forks[right_fork]); // Put down right fork

sleep(1); // Think again


}
return NULL;
}

int main() {
pthread_t philosophers[NUM_PHILOSOPHERS];
int philosopher_numbers[NUM_PHILOSOPHERS];

// Initialize semaphores
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
sem_init(&forks[i], 0, 1); // Each fork is initially available
}
sem_init(&mutex, 0, 1); // Mutex for critical section

// Create philosopher threads


for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
philosopher_numbers[i] = i;
pthread_create(&philosophers[i], NULL, philosopher,
&philosopher_numbers[i]);
}

// Join threads (in real systems, this would be done with proper exit
conditions)
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
pthread_join(philosophers[i], NULL);
}

// Destroy semaphores
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
sem_destroy(&forks[i]);
}
sem_destroy(&mutex);
return 0;
}

Producer – Consumer

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

#define BUFFER_SIZE 5
int buffer[BUFFER_SIZE];
int in = 0, out = 0;

sem_t empty, full, mutex; // Semaphores for empty slots, full slots, and mutual
exclusion

void* producer(void* arg) {


int item;
while (1) {
item = rand() % 100; // Produce a random item
sem_wait(&empty); // Decrease empty slot count
sem_wait(&mutex); // Enter critical section

buffer[in] = item; // Add item to buffer


printf("Producer produced: %d\n", item);
in = (in + 1) % BUFFER_SIZE;

sem_post(&mutex); // Exit critical section


sem_post(&full); // Increase full slot count

sleep(1);
}
return NULL;
}

void* consumer(void* arg) {


int item;
while (1) {
sem_wait(&full); // Decrease full slot count
sem_wait(&mutex); // Enter critical section

item = buffer[out]; // Consume item from buffer


printf("Consumer consumed: %d\n", item);
out = (out + 1) % BUFFER_SIZE;

sem_post(&mutex); // Exit critical section


sem_post(&empty); // Increase empty slot count

sleep(1);
}
return NULL;
}

int main() {
pthread_t prod_thread, cons_thread;

// Initialize semaphores
sem_init(&empty, 0, BUFFER_SIZE); // Empty slots in buffer
sem_init(&full, 0, 0); // Full slots in buffer
sem_init(&mutex, 0, 1); // Mutex for critical section

// Create producer and consumer threads


pthread_create(&prod_thread, NULL, producer, NULL);
pthread_create(&cons_thread, NULL, consumer, NULL);

// Join threads (in real systems, this would be done with proper exit
conditions)
pthread_join(prod_thread, NULL);
pthread_join(cons_thread, NULL);

// Destroy semaphores
sem_destroy(&empty);
sem_destroy(&full);
sem_destroy(&mutex);

return 0;
}
Readers – Writers

#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>

/*
This program provides a possible solution for first readers writers problem
using mutex and semaphore.
I have used 10 readers and 5 producers to demonstrate the solution. You can
always play with these values.
*/

sem_t wrt;
pthread_mutex_t mutex;
int cnt = 1;
int numreader = 0;

void *writer(void *wno)


{
sem_wait(&wrt);
cnt = cnt*2;
printf("Writer %d modified cnt to %d\n",(*((int *)wno)),cnt);
sem_post(&wrt);

}
void *reader(void *rno)
{
// Reader acquire the lock before modifying numreader
pthread_mutex_lock(&mutex);
numreader++;
if(numreader == 1) {
sem_wait(&wrt); // If this id the first reader, then it will block the writer
}
pthread_mutex_unlock(&mutex);
// Reading Section
printf("Reader %d: read cnt as %d\n",*((int *)rno),cnt);
// Reader acquire the lock before modifying numreader
pthread_mutex_lock(&mutex);
numreader--;
if(numreader == 0) {
sem_post(&wrt); // If this is the last reader, it will wake up the writer.
}
pthread_mutex_unlock(&mutex);
}

int main()
{

pthread_t read[10],write[5];
pthread_mutex_init(&mutex, NULL);
sem_init(&wrt,0,1);

int a[10] = {1,2,3,4,5,6,7,8,9,10}; //Just used for numbering the producer and
consumer

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


pthread_create(&read[i], NULL, (void *)reader, (void *)&a[i]);
}
for(int i = 0; i < 5; i++) {
pthread_create(&write[i], NULL, (void *)writer, (void *)&a[i]);
}

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


pthread_join(read[i], NULL);
}
for(int i = 0; i < 5; i++) {
pthread_join(write[i], NULL);
}

pthread_mutex_destroy(&mutex);
sem_destroy(&wrt);

return 0;

}
VII Write a C program to simulate Bankers Algorithm for Deadlock
Avoidance.
#include <stdio.h>
#include <stdbool.h>

#define P 5 // Number of processes


#define R 3 // Number of resource types

// Function to check if a process can finish with current available resources


bool isSafeState(int processes[], int avail[], int max[][R], int allot[][R]) {
int work[R]; // Work vector to track available resources
bool finish[P] = {false}; // To track if a process can finish
int safeSequence[P]; // To store the safe sequence of processes
int count = 0; // To count the number of processes that can finish

// Copy available resources to work[] vector


for (int i = 0; i < R; i++) {
work[i] = avail[i];
}

// Find a safe sequence


while (count < P) {
bool found = false;
for (int p = 0; p < P; p++) {
if (!finish[p]) {
// Check if all remaining needs of process p can be satisfied
bool canFinish = true;
for (int i = 0; i < R; i++) {
if (max[p][i] - allot[p][i] > work[i]) {
canFinish = false;
break;
}
}

// If process p can finish, simulate the allocation and release resources


if (canFinish) {
for (int i = 0; i < R; i++) {
work[i] += allot[p][i];
}
safeSequence[count++] = p; // Add process p to safe sequence
finish[p] = true; // Mark process p as finished
found = true;
}
}
}

// If no process can finish, the system is not in a safe state


if (!found) {
printf("System is in an unsafe state.\n");
return false;
}
}

// Print the safe sequence


printf("System is in a safe state.\nSafe sequence: ");
for (int i = 0; i < P; i++) {
printf("%d ", safeSequence[i]);
}
printf("\n");
return true;
}

// Function to check if a request can be granted


bool requestResources(int processes[], int avail[], int max[][R], int allot[][R], int
pid, int request[]) {
// Check if request is less than or equal to Need
for (int i = 0; i < R; i++) {
if (request[i] > max[pid][i] - allot[pid][i]) {
printf("Error: Process has exceeded maximum claim.\n");
return false;
}
}

// Check if request is less than or equal to available resources


for (int i = 0; i < R; i++) {
if (request[i] > avail[i]) {
printf("Resources are not available.\n");
return false;
}
}

// Simulate allocation and check if the system is in a safe state


for (int i = 0; i < R; i++) {
avail[i] -= request[i];
allot[pid][i] += request[i];
}

if (isSafeState(processes, avail, max, allot)) {


return true;
} else {
// Rollback allocation if the system is not safe
for (int i = 0; i < R; i++) {
avail[i] += request[i];
allot[pid][i] -= request[i];
}
printf("Request cannot be granted as it leads to an unsafe state.\n");
return false;
}
}

int main() {
int processes[] = {0, 1, 2, 3, 4}; // Process IDs

// Available instances of resources


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

// Maximum demand of each process for each resource


int max[][R] = {
{7, 5, 3}, // Process 0
{3, 2, 2}, // Process 1
{9, 0, 2}, // Process 2
{2, 2, 2}, // Process 3
{4, 3, 3} // Process 4
};

// Resources allocated to each process


int allot[][R] = {
{0, 1, 0}, // Process 0
{2, 0, 0}, // Process 1
{3, 0, 2}, // Process 2
{2, 1, 1}, // Process 3
{0, 0, 2} // Process 4
};

// Request resources for a process (example: process 1 requests (1, 0, 2))


int request[] = {1, 0, 2};
int pid = 1; // Process ID requesting resources

if (requestResources(processes, avail, max, allot, pid, request)) {


printf("Resources granted to Process %d.\n", pid);
}
return 0;
}

You might also like