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;
}