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

OS_Labs[1]

Uploaded by

anaschaudry0
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views21 pages

OS_Labs[1]

Uploaded by

anaschaudry0
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 21

Lab # 8

(a).write c language program to implement semaphores using function


semet(),semct(),semop()functions.

#include <stdio.h>

#include <stdlib.h>

#include <sys/ipc.h>

#include <sys/sem.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <unistd.h>

// Union required for semctl initialization

union semun {

int val; // Value for SETVAL

struct semid_ds *buf; // Buffer for IPC_STAT, IPC_SET

unsigned short *array; // Array for GETALL, SETALL

};

// Function to initialize a semaphore

void initialize_semaphore(int semid, int value) {

union semun sem_union;

sem_union.val = value;

if (semctl(semid, 0, SETVAL, sem_union) == -1) {

perror("semctl - initialization failed");

exit(EXIT_FAILURE);

// Function to perform semaphore wait (P operation)

void semaphore_wait(int semid) {


struct sembuf sem_op;

sem_op.sem_num = 0; // Semaphore number in the set

sem_op.sem_op = -1; // Decrement the semaphore value

sem_op.sem_flg = 0; // Blocking operation

if (semop(semid, &sem_op, 1) == -1) {

perror("semop - wait failed");

exit(EXIT_FAILURE);

// Function to perform semaphore signal (V operation)

void semaphore_signal(int semid) {

struct sembuf sem_op;

sem_op.sem_num = 0; // Semaphore number in the set

sem_op.sem_op = 1; // Increment the semaphore value

sem_op.sem_flg = 0; // No special flags

if (semop(semid, &sem_op, 1) == -1) {

perror("semop - signal failed");

exit(EXIT_FAILURE);

int main() {

key_t key;

int semid;

// Generate a unique key for the semaphore

if ((key = ftok(".", 'A')) == -1) { // Use current directory as the key source

perror("ftok failed");

exit(EXIT_FAILURE);
}

// Create a semaphore set with one semaphore

if ((semid = semget(key, 1, 0666 | IPC_CREAT)) == -1) {

perror("semget failed");

exit(EXIT_FAILURE);

// Initialize the semaphore to 1 (binary semaphore for mutual exclusion)

initialize_semaphore(semid, 1);

pid_t pid = fork();

if (pid < 0) {

perror("fork failed");

exit(EXIT_FAILURE);

if (pid == 0) {

// Child process

printf("Child: Waiting to access critical section...\n");

semaphore_wait(semid);

printf("Child: Entered critical section.\n");

sleep(2); // Simulate work in the critical section

printf("Child: Leaving critical section.\n");

semaphore_signal(semid);

exit(0); // Ensure child exits cleanly

} else {

// Parent process

printf("Parent: Waiting to access critical section...\n");

semaphore_wait(semid);

printf("Parent: Entered critical section.\n");


sleep(2); // Simulate work in the critical section

printf("Parent: Leaving critical section.\n");

semaphore_signal(semid);

// Wait for the child process to finish

wait(NULL);

// Remove the semaphore set after both processes complete

if (semctl(semid, 0, IPC_RMID) == -1) {

perror("semctl - removal failed");

exit(EXIT_FAILURE);

printf("Semaphore removed successfully.\n");

return 0;

Output:

(b).write a c program to simulate the concept of dining philosopher problem.

#include <pthread.h>

#include <semaphore.h>

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

#define NUM_PHILOSOPHERS 5

// Declare semaphores and a mutex

sem_t forks[NUM_PHILOSOPHERS];

pthread_mutex_t mutex;

// Function for philosophers to think

void think(int philosopher) {

printf("Philosopher %d is thinking.\n", philosopher);

sleep(1);

// Function for philosophers to eat

void eat(int philosopher) {

printf("Philosopher %d is eating.\n", philosopher);

sleep(2);

// Function for philosopher's lifecycle

void* philosopher(void* arg) {

int philosopher = (int)arg;

while (1) {

think(philosopher);

// Pick up forks (critical section)

pthread_mutex_lock(&mutex);

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

sem_wait(&forks[(philosopher + 1) % NUM_PHILOSOPHERS]); // Pick up right fork

pthread_mutex_unlock(&mutex);

eat(philosopher);

// Put down forks

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


sem_post(&forks[(philosopher + 1) % NUM_PHILOSOPHERS]); // Put down right fork

return NULL;

int main() {

pthread_t philosophers[NUM_PHILOSOPHERS];

int philosopher_ids[NUM_PHILOSOPHERS];

// Initialize semaphores and mutex

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

sem_init(&forks[i], 0, 1);

pthread_mutex_init(&mutex, NULL);

// Create threads for each philosopher

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

philosopher_ids[i] = i;

if (pthread_create(&philosophers[i], NULL, philosopher, &philosopher_ids[i]) != 0) {

perror("Failed to create philosopher thread");

return 1;

// Wait for all philosopher threads to finish

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

pthread_join(philosophers[i], NULL);

// Clean up resources

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

sem_destroy(&forks[i]);

}
pthread_mutex_destroy(&mutex);

return 0;;

Output:

(c).write a c program to simulate the concept of bounded buffer problem.

#include <stdio.h>

#include <stdlib.h>

#include <pthread.h>

#include <semaphore.h>

#include <unistd.h>

#define BUFFER_SIZE 5

#define NUM_PRODUCERS 2

#define NUM_CONSUMERS 2

#define NUM_ITEMS 10

// Shared buffer

int buffer[BUFFER_SIZE];

int in = 0, out = 0;

// Semaphores and mutex


sem_t empty; // Tracks empty slots

sem_t full; // Tracks filled slots

pthread_mutex_t mutex; // Ensures mutual exclusion

// Producer function

void* producer(void* arg) {

int id = (int)arg;

for (int I = 0; I < NUM_ITEMS; I++) {

int item = rand() % 100; // Generate a random item

sem_wait(&empty); // Wait for an empty slo

pthread_mutex_lock(&mutex); // Lock the buffer

// Produce an item

buffer[in] = item;

printf("Producer %d: Produced item %d at position %d\n", id, item, in);

in = (in + 1) % BUFFER_SIZE;

pthread_mutex_unlock(&mutex); // Unlock the buffer

sem_post(&full); // Signal a filled slot

sleep(rand() % 2); // Simulate production time

return NULL;

// Consumer function

void* consumer(void* arg) {

int id = (int)arg;

for (int I = 0; I < NUM_ITEMS; I++) {

sem_wait(&full); // Wait for a filled slot

pthread_mutex_lock(&mutex); // Lock the buffer

// Consume an item

int item = buffer[out];


printf("Consumer %d: Consumed item %d from position %d\n", id, item, out);

out = (out + 1) % BUFFER_SIZE;

pthread_mutex_unlock(&mutex); // Unlock the buffer

sem_post(&empty); // Signal an empty slot

sleep(rand() % 2); // Simulate consumption time

return NULL;

int main() {

pthread_t producers[NUM_PRODUCERS], consumers[NUM_CONSUMERS];

int producer_ids[NUM_PRODUCERS], consumer_ids[NUM_CONSUMERS];

// Initialize semaphores and mutex

sem_init(&empty, 0, BUFFER_SIZE); // Initially, all slots are empty

sem_init(&full, 0, 0); // Initially, no slots are filled

pthread_mutex_init(&mutex, NULL);

// Create producer threads

for (int I = 0; I < NUM_PRODUCERS; I++) {

producer_ids[I] = I + 1;

if (pthread_create(&producers[I], NULL, producer, &producer_ids[I]) != 0) {

perror("Failed to create producer thread");

exit(EXIT_FAILURE);

// Create consumer threads

for (int I = 0; I < NUM_CONSUMERS; I++) {

consumer_ids[I] = I + 1;

if (pthread_create(&consumers[I], NULL, consumer, &consumer_ids[I]) != 0) {

perror("Failed to create consumer thread");


exit(EXIT_FAILURE);

} // Wait for producer threads to finish

for (int I = 0; I < NUM_PRODUCERS; I++) {

pthread_join(producers[I], NULL); }

// Wait for consumer threads to finish

for (int I = 0; I < NUM_CONSUMERS; I++) {

pthread_join(consumers[I], NULL);

} // Destroy semaphores and mutex

sem_destroy(&empty);

sem_destroy(&full);

pthread_mutex_destroy(&mutex);

printf("All producers and consumers have finished.\n");

return 0;}

Output:
Lab # 10
(a). Deadlocks in C (Demonstration)

#include <pthread.h>
#include <stdio.h>
#include <unistd.h> // Include this for the sleep() function
pthread_mutex_t lock1, lock2;
void *thread1(void *arg) {
pthread_mutex_lock(&lock1);
printf("Thread 1: Locked lock1\n");
sleep(1); // Simulate work
pthread_mutex_lock(&lock2);
printf("Thread 1: Locked lock2\n");
pthread_mutex_unlock(&lock2);
pthread_mutex_unlock(&lock1);
return NULL;
}
void *thread2(void *arg) {
pthread_mutex_lock(&lock2);
printf("Thread 2: Locked lock2\n");
sleep(1); // Simulate work
pthread_mutex_lock(&lock1);
printf("Thread 2: Locked lock1\n");
pthread_mutex_unlock(&lock1);
pthread_mutex_unlock(&lock2);
return NULL;
}
int main() {
pthread_t t1, t2;
pthread_mutex_init(&lock1, NULL);
pthread_mutex_init(&lock2, NULL);
pthread_create(&t1, NULL, thread1, NULL);
pthread_create(&t2, NULL, thread2, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_mutex_destroy(&lock1);
pthread_mutex_destroy(&lock2);
return 0;
}

Output:
b. Deadlock Avoidance Using Dijkstra's Banker's Algorithm

#include <stdio.h>
#define MAX 10
int available[MAX], max[MAX][MAX], allocation[MAX][MAX], need[MAX][MAX];
int processes, resources;
void calculateNeed() {
for (int i = 0; i < processes; i++) {
for (int j = 0; j < resources; j++) {
need[i][j] = max[i][j] - allocation[i][j];
}
}
}
int isSafe() {
int work[MAX], finish[MAX] = {0};
int safeSequence[MAX], index = 0;
for (int i = 0; i < resources; i++)
work[i] = available[i];
for (int count = 0; count < processes; count++) {
int found = 0;
for (int i = 0; i < processes; i++) {
if (!finish[i]) {
int j;
for (j = 0; j < resources; j++) {
if (need[i][j] > work[j])
break;
}
if (j == resources) {
for (int k = 0; k < resources; k++)
work[k] += allocation[i][k];
safeSequence[index++] = i;
finish[i] = 1;
found = 1;
}
}
}
if (!found) {
printf("System is not in a safe state\n");
return 0;
}
}
printf("System is in a safe state. Safe sequence: ");
for (int i = 0; i < processes; i++)
printf("%d ", safeSequence[i]);
printf("\n");
return 1;
}
int main() {
printf("Enter number of processes and resources: ");
scanf("%d %d", &processes, &resources);
printf("Enter available resources: ");
for (int i = 0; i < resources; i++)
scanf("%d", &available[i]);
printf("Enter maximum resource matrix: \n");
for (int i = 0; i < processes; i++)
for (int j = 0; j < resources; j++)
scanf("%d", &max[i][j]);
printf("Enter allocated resource matrix: \n");
for (int i = 0; i < processes; i++)
for (int j = 0; j < resources; j++)
scanf("%d", &allocation[i][j]);
calculateNeed();
isSafe();
return 0;
}
Output:

Other case check


c. Simulating Deadlock with Two Threads and Two Resources

#include <pthread.h>

#include <stdio.h>

#include <unistd.h> // Include this for the sleep() function

pthread_mutex_t resource1, resource2;

void *threadFunc1(void *arg) {

pthread_mutex_lock(&resource1);

printf("Thread 1: Locked resource1\n");

sleep(1); // Simulate work

pthread_mutex_lock(&resource2);

printf("Thread 1: Locked resource2\n");

pthread_mutex_unlock(&resource2);

pthread_mutex_unlock(&resource1);

return NULL;

void *threadFunc2(void *arg) {

pthread_mutex_lock(&resource2);

printf("Thread 2: Locked resource2\n");

sleep(1); // Simulate work

pthread_mutex_lock(&resource1);

printf("Thread 2: Locked resource1\n");

pthread_mutex_unlock(&resource1);

pthread_mutex_unlock(&resource2);

return NULL;

int main() {

pthread_t thread1, thread2;

pthread_mutex_init(&resource1, NULL);
pthread_mutex_init(&resource2, NULL);

pthread_create(&thread1, NULL, threadFunc1, NULL);

pthread_create(&thread2, NULL, threadFunc2, NULL);

pthread_join(thread1, NULL);

pthread_join(thread2, NULL);

pthread_mutex_destroy(&resource1);

pthread_mutex_destroy(&resource2);

return 0;

Output:

Lab # 11
a. Memory Allocation Graph and Resources in C

#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = malloc(5 * sizeof(int)); // Allocating memory for 5 integers
if (!arr) {
printf("Memory allocation failed\n");
return 1;
}
printf("Memory allocation graph:\n");
for (int i = 0; i < 5; i++) {
arr[i] = i * 10;
printf("arr[%d] = %d (Address: %p)\n", i, arr[i], (void*)&arr[i]);
}
free(arr); // Freeing the memory
printf("Memory freed.\n");
return 0;
}

Output:

b. Simulating malloc() in C

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

void *my_malloc(size_t size) {


void *ptr = sbrk(size);
if (ptr == (void*)-1) {
printf("Memory allocation failed\n");
return NULL;
}
return ptr;
}
int main() {
int *arr = (int*)my_malloc(5 * sizeof(int));
if (!arr) {
return 1;
}

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


arr[i] = i + 1;
printf("arr[%d] = %d\n", i, arr[i]);
}
return 0;
}

Output:
c. Using free() in Linux

#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = malloc(5 * sizeof(int));
if (!arr) {
printf("Memory allocation failed\n");
return 1;
}
for (int i = 0; i < 5; i++) {
arr[i] = i * 10;
printf("arr[%d] = %d\n", i, arr[i]);
}

free(arr); // Free allocated memory


printf("Memory has been freed.\n");
return 0;
}

Output:

Lab # 12
a. Demonstrating calloc()

#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int*)calloc(5, sizeof(int)); // Allocates memory for 5 integers and initializes to 0
if (!arr) {
printf("Memory allocation failed\n");
return 1;
}
printf("Using calloc():\n");
for (int i = 0; i < 5; i++) {
printf("arr[%d] = %d\n", i, arr[i]);
}
free(arr);
return 0;
}

Output:

b. Demonstrating realloc()

#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int*)malloc(3 * sizeof(int));
if (!arr) {
printf("Memory allocation failed\n");
return 1;
}
for (int i = 0; i < 3; i++) {
arr[i] = i + 1;
printf("arr[%d] = %d\n", i, arr[i]);
}
printf("Reallocating memory...\n");
arr = realloc(arr, 5 * sizeof(int));
if (!arr) {
printf("Memory reallocation failed\n");
return 1;
}
for (int i = 3; i < 5; i++) {
arr[i] = i + 1;
}
for (int i = 0; i < 5; i++) {
printf("arr[%d] = %d\n", i, arr[i]);
}
free(arr);
return 0;
}

Output:
c. Demonstrating malloc()

#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int*)malloc(5 * sizeof(int));
if (!arr) {
printf("Memory allocation failed\n");
return 1;
}
for (int i = 0; i < 5; i++) {
arr[i] = i * 10;
printf("arr[%d] = %d\n", i, arr[i]);
}
free(arr);
return 0;
}

Output:

Lab # 13
a. Demonstrating Shared Memory Using shmat()

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main() {
key_t key = ftok("shmfile", 65);
int shmid = shmget(key, 1024, 0666|IPC_CREAT);
char *str = (char*)shmat(shmid, (void*)0, 0);

printf("Write data to shared memory: ");


fgets(str, 1024, stdin);
printf("Data written in memory: %s\n", str);
shmdt(str);
return 0;
}

Output:
b. Demonstrating shmdt, shmctl, and ftok
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main() {
key_t key = ftok("shmfile", 65);
int shmid = shmget(key, 1024, 0666|IPC_CREAT);
char *str = (char*)shmat(shmid, (void*)0, 0);
printf("Read data from shared memory: %s\n", str);
shmdt(str);
shmctl(shmid, IPC_RMID, NULL);
return 0;
}

Output:

Lab # 14
Shared Memory Using shmget()

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main() {
key_t key = ftok("shmfile", 65);
int shmid = shmget(key, 1024, 0666|IPC_CREAT);
char *str = (char*)shmat(shmid, (void*)0, 0);

printf("Write data to shared memory: ");


fgets(str, 1024, stdin);

printf("Data in shared memory: %s\n", str);

shmdt(str);
shmctl(shmid, IPC_RMID, NULL);

return 0;
}

Output:
Lab # 15
File Handling in C

#include <stdio.h>
int main() {
FILE *fp = fopen("example.txt", "w");
if (!fp) {
printf("Failed to open file\n");
return 1;
}

fprintf(fp, "Hello, file handling in C!\n");


fclose(fp);
fp = fopen("example.txt", "r");
if (!fp) {
printf("Failed to open file\n");
return 1;
}
char buffer[100];
while (fgets(buffer, sizeof(buffer), fp)) {
printf("%s", buffer);
}

fclose(fp);
return 0;
}

Output:

These programs cover the requirements for all weeks. Let me know if you need further
explanations or modifications!

You might also like