OneCompiler

xae

418

Q.Write a shell program to find even or odd
number.

#!/bin/bash

Prompt the user to enter a number

echo "Enter a number: "
read num

Check if the number is divisible by 2

if (( num % 2 == 0 )); then
echo "numiseven."elseecho"num is even." else echo "num is odd."
fi

Q. Write a shell program to display list of even numbers from 1 to 100.

#!/bin/bash

echo "Even numbers from 2 to 100:"
for (( i = 2; i <= 100; i+=2 )); do
echo "$i"
done

Q. Write program to implement SJF

#include<stdio.h>

// Structure to represent a process
struct Process {
int id; // Process ID
int arrival_time; // Arrival time
int burst_time; // Burst time
int waiting_time; // Waiting time
int turnaround_time;// Turnaround time
};

// Function to perform SJF scheduling
void SJF(struct Process processes[], int n) {
// Sort the processes based on arrival time
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (processes[j].arrival_time > processes[j + 1].arrival_time) {
struct Process temp = processes[j];
processes[j] = processes[j + 1];
processes[j + 1] = temp;
}
}
}

int total_waiting_time = 0, total_turnaround_time = 0;
int current_time = 0;

// Calculate waiting time and turnaround time for each process
for (int i = 0; i < n; i++) {
    // Update current time
    current_time += processes[i].burst_time;

    // Calculate waiting time for current process
    processes[i].waiting_time = current_time - processes[i].burst_time - processes[i].arrival_time;
    total_waiting_time += processes[i].waiting_time;

    // Calculate turnaround time for current process
    processes[i].turnaround_time = current_time - processes[i].arrival_time;
    total_turnaround_time += processes[i].turnaround_time;
}

// Print the scheduling table
printf("Process ID\tArrival Time\tBurst Time\tWaiting Time\tTurnaround Time\n");
for (int i = 0; i < n; i++) {
    printf("%d\t\t%d\t\t%d\t\t%d\t\t%d\n", processes[i].id, processes[i].arrival_time, processes[i].burst_time, processes[i].waiting_time, processes[i].turnaround_time);
}

// Calculate and print average waiting time and turnaround time
printf("Average Waiting Time: %.2f\n", (float) total_waiting_time / n);
printf("Average Turnaround Time: %.2f\n", (float) total_turnaround_time / n);

}

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

// Input details of each process
struct Process processes[n];
for (int i = 0; i < n; i++) {
    processes[i].id = i + 1;
    printf("Enter arrival time for process %d: ", i + 1);
    scanf("%d", &processes[i].arrival_time);
    printf("Enter burst time for process %d: ", i + 1);
    scanf("%d", &processes[i].burst_time);
}

// Perform SJF scheduling
SJF(processes, n);

return 0;

}

Q. PROGRAM TO IMPLEMENT FCFS

#include<stdio.h>

// Structure to represent a process
struct Process {
int id; // Process ID
int arrival_time; // Arrival time
int burst_time; // Burst time
int waiting_time; // Waiting time
int turnaround_time;// Turnaround time
};

// Function to perform FCFS scheduling
void FCFS(struct Process processes[], int n) {
int total_waiting_time = 0, total_turnaround_time = 0;
int current_time = 0;

// Calculate waiting time and turnaround time for each process
for (int i = 0; i < n; i++) {
    // Update current time if arrival time of current process is greater than current time
    if (current_time < processes[i].arrival_time) {
        current_time = processes[i].arrival_time;
    }

    // Calculate waiting time for current process
    processes[i].waiting_time = current_time - processes[i].arrival_time;
    total_waiting_time += processes[i].waiting_time;

    // Calculate turnaround time for current process
    processes[i].turnaround_time = processes[i].burst_time + processes[i].waiting_time;
    total_turnaround_time += processes[i].turnaround_time;

    // Update current time
    current_time += processes[i].burst_time;
}

// Print the scheduling table
printf("Process ID\tArrival Time\tBurst Time\tWaiting Time\tTurnaround Time\n");
for (int i = 0; i < n; i++) {
    printf("%d\t\t%d\t\t%d\t\t%d\t\t%d\n", processes[i].id, processes[i].arrival_time, processes[i].burst_time, processes[i].waiting_time, processes[i].turnaround_time);
}

// Calculate and print average waiting time and turnaround time
printf("Average Waiting Time: %.2f\n", (float) total_waiting_time / n);
printf("Average Turnaround Time: %.2f\n", (float) total_turnaround_time / n);

}

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

// Input details of each process
struct Process processes[n];
for (int i = 0; i < n; i++) {
    processes[i].id = i + 1;
    printf("Enter arrival time for process %d: ", i + 1);
    scanf("%d", &processes[i].arrival_time);
    printf("Enter burst time for process %d: ", i + 1);
    scanf("%d", &processes[i].burst_time);
}

// Perform FCFS scheduling
FCFS(processes, n);

return 0;

}

Q. Write program to
implement RR algorithm.

#include <stdio.h>

#define MAX_PROCESSES 10
#define TIME_QUANTUM 2

// Structure to represent a process
struct Process {
int id; // Process ID
int burst_time; // Burst time
int remaining_time; // Remaining burst time
int arrival_time; // Arrival time
int waiting_time; // Waiting time
int turnaround_time;// Turnaround time
};

// Function to perform Round Robin scheduling
void RR(struct Process processes[], int n) {
int total_waiting_time = 0, total_turnaround_time = 0;
int current_time = 0;
int completed_processes = 0;

// Run the RR algorithm until all processes are completed
while (completed_processes < n) {
    for (int i = 0; i < n; i++) {
        // If process has arrived and has remaining burst time
        if (processes[i].arrival_time <= current_time && processes[i].remaining_time > 0) {
            // Execute the process for the time quantum or remaining burst time, whichever is smaller
            int execute_time = (processes[i].remaining_time > TIME_QUANTUM) ? TIME_QUANTUM : processes[i].remaining_time;
            current_time += execute_time;
            processes[i].remaining_time -= execute_time;

            // Update waiting time for other processes
            for (int j = 0; j < n; j++) {
                if (j != i && processes[j].arrival_time <= current_time && processes[j].remaining_time > 0) {
                    processes[j].waiting_time += execute_time;
                }
            }

            // If process has completed its burst time
            if (processes[i].remaining_time == 0) {
                completed_processes++;
                // Calculate turnaround time for the completed process
                processes[i].turnaround_time = current_time - processes[i].arrival_time;
                total_turnaround_time += processes[i].turnaround_time;
            }
        }
    }
}

// Calculate and print average waiting time and turnaround time
for (int i = 0; i < n; i++) {
    total_waiting_time += processes[i].waiting_time;
}
printf("Average Waiting Time: %.2f\n", (float) total_waiting_time / n);
printf("Average Turnaround Time: %.2f\n", (float) total_turnaround_time / n);

}

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

// Input details of each process
struct Process processes[MAX_PROCESSES];
for (int i = 0; i < n; i++) {
    processes[i].id = i + 1;
    printf("Enter arrival time for process %d: ", i + 1);
    scanf("%d", &processes[i].arrival_time);
    printf("Enter burst time for process %d: ", i + 1);
    scanf("%d", &processes[i].burst_time);
    processes[i].remaining_time = processes[i].burst_time;
    processes[i].waiting_time = 0;
    processes[i].turnaround_time = 0;
}

// Perform RR scheduling
RR(processes, n);

return 0;

}

Q. Write Program to implement IPC
using shared memory

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>

#define SHM_SIZE 1024

int main() {
int shmid;
key_t key;
char *shm, *s;

// Generate a unique key for the shared memory segment
if ((key = ftok(".", 'R')) == -1) {
    perror("ftok");
    exit(1);
}

// Create the shared memory segment
if ((shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666)) == -1) {
    perror("shmget");
    exit(1);
}

// Attach the shared memory segment
if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
    perror("shmat");
    exit(1);
}

// Write to the shared memory
printf("Enter message: ");
fgets(shm, SHM_SIZE, stdin);

// Wait for the receiver to read the message
while (*shm != '*')
    sleep(1);

printf("Message received by receiver: %s", shm);

// Detach the shared memory segment
if (shmdt(shm) == -1) {
    perror("shmdt");
    exit(1);
}

// Delete the shared memory segment
if (shmctl(shmid, IPC_RMID, NULL) == -1) {
    perror("shmctl");
    exit(1);
}

return 0;

}

Q. Write Program to implement
Producer-Consumer problem using semaphores

#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

int buffer[BUFFER_SIZE];
int in = 0;
int out = 0;

sem_t empty, full, mutex;

void *producer(void *arg) {
int item;

for (int i = 0; i < NUM_ITEMS; i++) {
    item = rand() % 100; // Generate a random item

    sem_wait(&empty); // Wait for an empty slot in the buffer
    sem_wait(&mutex); // Lock the critical section

    buffer[in] = item;
    printf("Producer %ld produced item %d\n", (long)arg, item);
    in = (in + 1) % BUFFER_SIZE;

    sem_post(&mutex); // Unlock the critical section
    sem_post(&full); // Signal that a slot in the buffer is full

    sleep(1); // Simulate some work
}

pthread_exit(NULL);

}

void *consumer(void *arg) {
int item;

for (int i = 0; i < NUM_ITEMS; i++) {
    sem_wait(&full); // Wait for a full slot in the buffer
    sem_wait(&mutex); // Lock the critical section

    item = buffer[out];
    printf("Consumer %ld consumed item %d\n", (long)arg, item);
    out = (out + 1) % BUFFER_SIZE;

    sem_post(&mutex); // Unlock the critical section
    sem_post(&empty); // Signal that a slot in the buffer is empty

    sleep(2); // Simulate some work
}

pthread_exit(NULL);

}

int main() {
pthread_t producer_threads[NUM_PRODUCERS];
pthread_t consumer_threads[NUM_CONSUMERS];

// Initialize semaphores
sem_init(&empty, 0, BUFFER_SIZE);
sem_init(&full, 0, 0);
sem_init(&mutex, 0, 1);

// Create producer threads
for (long i = 0; i < NUM_PRODUCERS; i++) {
    pthread_create(&producer_threads[i], NULL, producer, (void *)i);
}

// Create consumer threads
for (long i = 0; i < NUM_CONSUMERS; i++) {
    pthread_create(&consumer_threads[i], NULL, consumer, (void *)i);
}

// Join producer threads
for (int i = 0; i < NUM_PRODUCERS; i++) {
    pthread_join(producer_threads[i], NULL);
}

// Join consumer threads
for (int i = 0; i < NUM_CONSUMERS; i++) {
    pthread_join(consumer_threads[i], NULL);
}

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

return 0;

}

Q. Write Program to
implement Dining Philosopher problem using semaphores

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

#define NUM_PHILOSOPHERS 5
#define THINKING 0
#define HUNGRY 1
#define EATING 2

sem_t mutex;
sem_t phil_sem[NUM_PHILOSOPHERS];

int state[NUM_PHILOSOPHERS];

void test(int philosopher_id) {
if (state[philosopher_id] == HUNGRY &&
state[(philosopher_id + 1) % NUM_PHILOSOPHERS] != EATING &&
state[(philosopher_id + NUM_PHILOSOPHERS - 1) % NUM_PHILOSOPHERS] != EATING) {

    state[philosopher_id] = EATING;
    printf("Philosopher %d is eating\n", philosopher_id);
    sem_post(&phil_sem[philosopher_id]);
}

}

void grab_forks(int philosopher_id) {
sem_wait(&mutex);
state[philosopher_id] = HUNGRY;
printf("Philosopher %d is hungry\n", philosopher_id);
test(philosopher_id);
sem_post(&mutex);
sem_wait(&phil_sem[philosopher_id]);
}

void put_forks(int philosopher_id) {
sem_wait(&mutex);
state[philosopher_id] = THINKING;
printf("Philosopher %d is thinking\n", philosopher_id);
test((philosopher_id + 1) % NUM_PHILOSOPHERS);
test((philosopher_id + NUM_PHILOSOPHERS - 1) % NUM_PHILOSOPHERS);
sem_post(&mutex);
}

void *philosopher(void *arg) {
int philosopher_id = *(int *)arg;

while (1) {
    // Simulate thinking
    sleep(rand() % 3);

    grab_forks(philosopher_id);

    // Simulate eating
    sleep(rand() % 3);

    put_forks(philosopher_id);
}

}

int main() {
pthread_t philosopher_threads[NUM_PHILOSOPHERS];
int philosopher_ids[NUM_PHILOSOPHERS];

// Initialize semaphores
sem_init(&mutex, 0, 1);
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
    sem_init(&phil_sem[i], 0, 0);
    philosopher_ids[i] = i;
}

// Create philosopher threads
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
    pthread_create(&philosopher_threads[i], NULL, philosopher, (void *)&philosopher_ids[i]);
}

// Join philosopher threads
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
    pthread_join(philosopher_threads[i], NULL);
}

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

return 0;

}

Q. Write
Program to implement Banker’s algorithm for deadlock avoidance.

#include <stdio.h>
#include <stdbool.h>

#define MAX_PROCESSES 10
#define MAX_RESOURCES 10

int available[MAX_RESOURCES];
int max[MAX_PROCESSES][MAX_RESOURCES];
int allocation[MAX_PROCESSES][MAX_RESOURCES];
int need[MAX_PROCESSES][MAX_RESOURCES];
bool finish[MAX_PROCESSES];

int num_processes, num_resources;

// Function to check if the current state is safe
bool isSafe() {
int work[MAX_RESOURCES];
bool finish_copy[MAX_PROCESSES];
int i, j;

// Initialize work to available resources
for (i = 0; i < num_resources; i++) {
    work[i] = available[i];
}

// Initialize finish_copy to finish array
for (i = 0; i < num_processes; i++) {
    finish_copy[i] = finish[i];
}

// Check for unfinished processes
int unfinished = num_processes;
while (unfinished > 0) {
    bool found = false;
    for (i = 0; i < num_processes; i++) {
        if (!finish_copy[i]) {
            // Check if need can be satisfied with available resources
            bool canBeSatisfied = true;
            for (j = 0; j < num_resources; j++) {
                if (need[i][j] > work[j]) {
                    canBeSatisfied = false;
                    break;
                }
            }

            // If need can be satisfied, mark the process as finished and release allocated resources
            if (canBeSatisfied) {
                finish_copy[i] = true;
                for (j = 0; j < num_resources; j++) {
                    work[j] += allocation[i][j];
                }
                found = true;
                unfinished--;
            }
        }
    }

    // If no process can be executed, the current state is unsafe
    if (!found) {
        return false;
    }
}

return true;

}

// Function to request resources by a process
void requestResources(int process_id, int request[]) {
int i;

// Check if the request can be granted
for (i = 0; i < num_resources; i++) {
    if (request[i] > need[process_id][i] || request[i] > available[i]) {
        printf("Process %d's request cannot be granted.\n", process_id);
        return;
    }
}

// Try to allocate resources
for (i = 0; i < num_resources; i++) {
    available[i] -= request[i];
    allocation[process_id][i] += request[i];
    need[process_id][i] -= request[i];
}

// Check if the current state is safe
if (isSafe()) {
    printf("Process %d's request is granted.\n", process_id);
} else {
    // If the current state is not safe, rollback the allocation
    for (i = 0; i < num_resources; i++) {
        available[i] += request[i];
        allocation[process_id][i] -= request[i];
        need[process_id][i] += request[i];
    }
    printf("Process %d's request cannot be granted.\n", process_id);
}

}

int main() {
int i, j;
int request[MAX_RESOURCES];
int process_id;

// Input the number of processes and resources
printf("Enter the number of processes: ");
scanf("%d", &num_processes);
printf("Enter the number of resources: ");
scanf("%d", &num_resources);

// Input the available resources
printf("Enter the available resources: ");
for (i = 0; i < num_resources; i++) {
    scanf("%d", &available[i]);
}

// Input the maximum resource allocation for each process
printf("Enter the maximum resource allocation for each process:\n");
for (i = 0; i < num_processes; i++) {
    printf("For process %d: ", i);
    for (j = 0; j < num_resources; j++) {
        scanf("%d", &max[i][j]);
        need[i][j] = max[i][j];
    }
    finish[i] = false;
}

// Input the current resource allocation for each process
printf("Enter the current resource allocation for each process:\n");
for (i = 0; i < num_processes; i++) {
    printf("For process %d: ", i);
    for (j = 0; j < num_resources; j++) {
        scanf("%d", &allocation[i][j]);
        need[i][j] -= allocation[i][j];
    }
}

// Input the process ID and resource request
printf("Enter the process ID making the request: ");
scanf("%d", &process_id);
printf("Enter the resource request: ");
for (i = 0; i < num_resources; i++) {
    scanf("%d", &request[i]);
}

// Process the resource request
requestResources(process_id, request);

return 0;

}

Q. Write Program to implement different memory management
techniques

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

// Define a block of memory with a fixed size
#define MEMORY_SIZE 1000
char memory[MEMORY_SIZE];

// Linked list node to represent a memory block
typedef struct Node {
int size;
int start;
struct Node* next;
} Node;

Node* head = NULL; // Head of the free memory block linked list

// Function to initialize the memory allocator
void initialize() {
head = (Node*)malloc(sizeof(Node));
head->size = MEMORY_SIZE;
head->start = 0;
head->next = NULL;
}

// Function to allocate memory using first-fit approach
void* allocate(int size) {
Node* current = head;
Node* prev = NULL;

while (current != NULL) {
    if (current->size >= size) {
        // Allocate memory from this block
        void* ptr = &memory[current->start];
        if (current->size == size) {
            // If the block size exactly matches, remove the block from the list
            if (prev != NULL) {
                prev->next = current->next;
            } else {
                head = current->next;
            }
            free(current);
        } else {
            // Update the block's size and start address
            current->size -= size;
            current->start += size;
        }
        return ptr;
    }
    prev = current;
    current = current->next;
}

// No suitable block found
return NULL;

}

// Function to free memory
void deallocate(void* ptr, int size) {
Node* current = head;
Node* prev = NULL;

// Find the position to insert the freed block in the list
while (current != NULL && current->start < (ptr - &memory[0])) {
    prev = current;
    current = current->next;
}

// Create a new block for the freed memory
Node* new_block = (Node*)malloc(sizeof(Node));
new_block->size = size;
new_block->start = ptr - &memory[0];

// Insert the new block into the list
if (prev != NULL) {
    new_block->next = prev->next;
    prev->next = new_block;
} else {
    new_block->next = head;
    head = new_block;
}

// Merge adjacent blocks if possible
if (new_block->next != NULL && new_block->start + new_block->size == new_block->next->start) {
    new_block->size += new_block->next->size;
    Node* temp = new_block->next;
    new_block->next = new_block->next->next;
    free(temp);
}

if (prev != NULL && prev->start + prev->size == new_block->start) {
    prev->size += new_block->size;
    prev->next = new_block->next;
    free(new_block);
}

}

// Function to display the memory blocks
void displayMemory() {
Node* current = head;
while (current != NULL) {
printf("Start: %d, Size: %d\n", current->start, current->size);
current = current->next;
}
}

int main() {
initialize();

// Allocate memory blocks
void* block1 = allocate(100);
void* block2 = allocate(200);
void* block3 = allocate(150);

printf("Allocated blocks:\n");
displayMemory();

// Free a memory block
deallocate(block2, 200);

printf("\nAfter freeing a block:\n");
displayMemory();

// Allocate a new memory block after freeing the previous one
void* block4 = allocate(300);

printf("\nAllocated blocks after allocating a new one:\n");
displayMemory();

return 0;

}

Q. Write Program to implement
sequential and indexed file allocation methods.

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

#define MAX_BLOCKS 100
#define MAX_FILES 10

// Structure to represent a block
struct Block {
int block_id;
bool allocated;
};

// Structure to represent a file
struct File {
int file_id;
int num_blocks;
int block_ids[MAX_BLOCKS];
};

// Global array to represent blocks
struct Block blocks[MAX_BLOCKS];

// Function to initialize blocks
void initializeBlocks() {
for (int i = 0; i < MAX_BLOCKS; i++) {
blocks[i].block_id = i;
blocks[i].allocated = false;
}
}

// Function to allocate blocks for a file using sequential allocation
bool sequentialAllocation(struct File *file) {
int start_block = -1;
int count = 0;

// Find consecutive free blocks
for (int i = 0; i < MAX_BLOCKS; i++) {
    if (!blocks[i].allocated) {
        if (start_block == -1) {
            start_block = i;
        }
        count++;
        if (count == file->num_blocks) {
            break;
        }
    } else {
        start_block = -1;
        count = 0;
    }
}

// If enough free blocks are found, allocate them
if (start_block != -1 && count == file->num_blocks) {
    for (int i = start_block; i < start_block + file->num_blocks; i++) {
        blocks[i].allocated = true;
        file->block_ids[i - start_block] = i;
    }
    return true;
} else {
    printf("Error: Not enough free blocks for sequential allocation.\n");
    return false;
}

}

// Function to allocate blocks for a file using indexed allocation
bool indexedAllocation(struct File *file) {
int index_block = -1;

// Find a free block for the index block
for (int i = 0; i < MAX_BLOCKS; i++) {
    if (!blocks[i].allocated) {
        index_block = i;
        break;
    }
}

// If free block is found, allocate index block and allocate data blocks
if (index_block != -1) {
    blocks[index_block].allocated = true;
    file->block_ids[0] = index_block;

    // Allocate data blocks using index block
    for (int i = 1; i <= file->num_blocks; i++) {
        int data_block = -1;
        for (int j = 0; j < MAX_BLOCKS; j++) {
            if (!blocks[j].allocated) {
                data_block = j;
                break;
            }
        }
        if (data_block == -1) {
            printf("Error: Not enough free blocks for indexed allocation.\n");
            return false;
        }
        blocks[data_block].allocated = true;
        blocks[index_block].block_id = data_block;
        file->block_ids[i] = data_block;
    }
    return true;
} else {
    printf("Error: Not enough free blocks for indexed allocation.\n");
    return false;
}

}

// Function to deallocate blocks allocated for a file
void deallocateBlocks(struct File *file) {
for (int i = 0; i < file->num_blocks; i++) {
blocks[file->block_ids[i]].allocated = false;
}
}

int main() {
// Initialize blocks
initializeBlocks();

// Example files
struct File files[MAX_FILES] = {
    {0, 3, {0, 0, 0}},
    {1, 5, {0, 0, 0, 0, 0}},
    {2, 2, {0, 0}},
    {3, 4, {0, 0, 0, 0}}
};

// Allocate blocks for each file using sequential allocation
printf("Sequential Allocation:\n");
for (int i = 0; i < MAX_FILES; i++) {
    printf("Allocating blocks for File %d...\n", files[i].file_id);
    if (sequentialAllocation(&files[i])) {
        printf("Blocks allocated successfully.\n");
    } else {
        printf("Failed to allocate blocks.\n");
    }
}

// Deallocate blocks for each file
printf("\nDeallocating blocks...\n");
for (int i = 0; i < MAX_FILES; i++) {
    printf("Deallocating blocks for File %d...\n", files[i].file_id);
    deallocateBlocks(&files[i]);
    printf("Blocks deallocated successfully.\n");
}