/* ========================================
SET A - PROBLEM 1
Basic fork() implementation with process identification
======================================== */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
// Set A - Problem 1: Basic fork() demo
void setA_problem1() {
printf("\n=== SET A - PROBLEM 1: Basic fork() Demo ===\n");
pid_t pid;
pid = fork(); // Create child process
if (pid < 0) {
// Fork failed
fprintf(stderr, "Fork Failed\n");
exit(1);
}
else if (pid == 0) {
// Child process
printf("I am Child Process\n");
printf("Child PID: %d, Parent PID: %d\n", getpid(), getppid());
}
else {
// Parent process
printf("I am Parent Process\n");
printf("Parent PID: %d, Child PID: %d\n", getpid(), pid);
wait(NULL); // Wait for child to complete
}
}
/* ========================================
SET A - PROBLEM 2
nice() system call demonstration
======================================== */
#include <sys/wait.h>
void setA_problem2() {
printf("\n=== SET A - PROBLEM 2: nice() System Call Demo ===\n");
pid_t pid;
int retnice;
printf("Original priority: %d\n", nice(0));
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork Failed\n");
exit(1);
}
else if (pid == 0) {
// Child process - higher priority
retnice = nice(-5);
printf("Child gets higher CPU priority: %d\n", retnice);
// Simulate work
for(int i = 0; i < 100000; i++) {
// CPU intensive task
}
printf("Child process completed\n");
}
else {
// Parent process - lower priority
retnice = nice(4);
printf("Parent gets lower CPU priority: %d\n", retnice);
// Simulate work
for(int i = 0; i < 100000; i++) {
// CPU intensive task
}
printf("Parent process completed\n");
wait(NULL);
}
}
/* ========================================
SET B - PROBLEM 1
Sorting with parent-child coordination
======================================== */
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-i-1; j++) {
if (arr[j] > arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
void insertionSort(int arr[], int n) {
for (int i = 1; i < n; i++) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}
}
void setB_problem1() {
printf("\n=== SET B - PROBLEM 1: Parent-Child Sorting ===\n");
int n;
printf("Enter number of integers: ");
scanf("%d", &n);
int arr1[n], arr2[n];
printf("Enter %d integers: ", n);
for(int i = 0; i < n; i++) {
scanf("%d", &arr1[i]);
arr2[i] = arr1[i]; // Copy for child process
}
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork Failed\n");
exit(1);
}
else if (pid == 0) {
// Child process - Insertion Sort
printf("Child performing Insertion Sort...\n");
insertionSort(arr2, n);
printf("Child sorted array: ");
for(int i = 0; i < n; i++) {
printf("%d ", arr2[i]);
}
printf("\n");
}
else {
// Parent process - Bubble Sort
printf("Parent performing Bubble Sort...\n");
bubbleSort(arr1, n);
printf("Parent sorted array: ");
for(int i = 0; i < n; i++) {
printf("%d ", arr1[i]);
}
printf("\n");
wait(NULL); // Wait for child to complete
printf("Both sorting processes completed\n");
}
}
/* ========================================
SET B - PROBLEM 2
Orphan process demonstration
======================================== */
void setB_problem2() {
printf("\n=== SET B - PROBLEM 2: Orphan Process Demo ===\n");
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork Failed\n");
exit(1);
}
else if (pid == 0) {
// Child process
printf("Child created - PID: %d, Parent PID: %d\n", getpid(), getppid());
sleep(5); // Child sleeps longer than parent
printf("Child wakes up - PID: %d, Parent PID: %d\n", getpid(), getppid());
printf("Child is now orphan (adopted by init)\n");
}
else {
// Parent process
printf("Parent created child - PID: %d, Child PID: %d\n", getpid(), pid);
sleep(2); // Parent terminates before child
printf("Parent terminating...\n");
// Parent exits without waiting for child - creates orphan
}
}
/* ========================================
SET C - PROBLEM 1
Binary search program (to be called by execve)
======================================== */
// This would be a separate program file (binary_search.c)
void binary_search_program(int argc, char *argv[]) {
if (argc < 3) {
printf("Usage: %s <search_element> <sorted_array_elements>\n", argv[0]);
return;
}
int search = atoi(argv[1]);
int n = argc - 2;
int arr[n];
// Read sorted array from command line arguments
for(int i = 0; i < n; i++) {
arr[i] = atoi(argv[i + 2]);
}
printf("Searching for %d in sorted array: ", search);
for(int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// Binary search
int left = 0, right = n - 1;
int found = 0;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == search) {
printf("Element %d found at position %d\n", search, mid + 1);
found = 1;
break;
}
if (arr[mid] < search)
left = mid + 1;
else
right = mid - 1;
}
if (!found) {
printf("Element %d not found in array\n", search);
}
}
void setC_problem1() {
printf("\n=== SET C - PROBLEM 1: execve() with Array Passing ===\n");
int n;
printf("Enter number of integers: ");
scanf("%d", &n);
int arr[n];
printf("Enter %d integers: ", n);
for(int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork Failed\n");
exit(1);
}
else if (pid == 0) {
// Child process will use execve to run binary search
// Note: In real implementation, you'd compile binary_search.c separately
printf("Child: This would call execve() to run binary search program\n");
printf("For demo, calling binary search function directly:\n");
// Simulate command line arguments
char *args[n + 3];
args[0] = "binary_search";
args[1] = "25"; // Search for element 25
char str_arr[n][10];
for(int i = 0; i < n; i++) {
sprintf(str_arr[i], "%d", arr[i]);
args[i + 2] = str_arr[i];
}
args[n + 2] = NULL;
binary_search_program(n + 2, args);
}
else {
// Parent process sorts the array
printf("Parent sorting array using bubble sort...\n");
bubbleSort(arr, n);
printf("Parent sorted array: ");
for(int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
wait(NULL); // Wait for child
printf("Parent: Child process completed\n");
}
}
/* ========================================
SET C - PROBLEM 2
Combined fork() and exec() demonstration
======================================== */
void setC_problem2() {
printf("\n=== SET C - PROBLEM 2: fork() with exec() Demo ===\n");
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork Failed\n");
exit(1);
}
else if (pid == 0) {
// Child process uses exec()
printf("Child: About to execute Set A(1) program using exec()\n");
// In real scenario, this would be:
// execl("./setA_problem1", "setA_problem1", NULL);
// For demonstration, calling the function directly
printf("Child executing Set A Problem 1:\n");
setA_problem1();
// If exec() was used, this line would never execute
printf("Child: exec() completed (this would not print if real exec() was
used)\n");
}
else {
// Parent process continues
printf("I am parent\n");
printf("Parent PID: %d, Child PID: %d\n", getpid(), pid);
wait(NULL); // Wait for child
printf("Parent: Child process completed\n");
}
}
/* ========================================
MAIN FUNCTION - Test Menu
======================================== */
int main() {
int choice;
printf("Operating Systems Practical Assignments\n");
printf("========================================\n");
printf("1. Set A - Problem 1 (Basic fork())\n");
printf("2. Set A - Problem 2 (nice() system call)\n");
printf("3. Set B - Problem 1 (Parent-Child Sorting)\n");
printf("4. Set B - Problem 2 (Orphan Process)\n");
printf("5. Set C - Problem 1 (execve() with arrays)\n");
printf("6. Set C - Problem 2 (fork() + exec())\n");
printf("7. Run All\n");
printf("Enter your choice (1-7): ");
scanf("%d", &choice);
switch(choice) {
case 1:
setA_problem1();
break;
case 2:
setA_problem2();
break;
case 3:
setB_problem1();
break;
case 4:
setB_problem2();
break;
case 5:
setC_problem1();
break;
case 6:
setC_problem2();
break;
case 7:
setA_problem1();
setA_problem2();
setB_problem1();
setB_problem2();
setC_problem1();
setC_problem2();
break;
default:
printf("Invalid choice!\n");
}
return 0;
}