Name: - sumit kumar
Subject: - operating system
Roll No.: -23020570053
Submitted to: -Ms. Shital
Index of Practicals
1. Execution of Various LINUX Commands:
    • i. Information Maintenance:
            o wc
            o clear
            o cal
            o who
            o date
            o pwd
    • ii. File Management:
            o cat
            o cp
            o rm
            o mv
            o cmp
            o comm
            o diff
            o find
            o grep
            o awk
    • iii. Directory Management:
            o cd
            o mkdir
            o rmdir
            o ls
2. Execution of Various LINUX Commands:
    • i. Process Control:
            o fork
            o getpid
            o ps
            o kill
            o sleep
    • ii. Communication:
            o Input-output redirection
            o Pipe
    • iii. Protection Management:
            o chmod
            o chown
            o chgrp
3. Program using fork() and/or exec():
    • i. Parent and child execute same program, same code.
    • ii. Parent and child execute same program, different code.
    • iii. Parent waits for child to finish before terminating.
4. Report Behavior of Linux Kernel (Kernel Version, CPU Type, and CPU Information)
5. Report Behavior of Linux Kernel (Memory Information, Configured Memory, Free/Used
Memory)
6. Program to Copy Files Using System Calls
7. Implementation of FCFS Scheduling Algorithm
8. Implementation of SJF Scheduling Algorithm
9. Implementation of Non-preemptive Priority-based Scheduling Algorithm
10. Implementation of SRTF Scheduling Algorithm
11. Calculate Sum of n Numbers Using Pthreads
    • Divide n numbers into two smaller lists.
    • Use two separate threads to sum the sub-lists.
12. Implementation of First-fit, Best-fit, and Worst-fit Allocation Strategies
           Acknowledgment
I would like to express my sincere gratitude to
my instructor, Mrs. Sheetal Singh, for providing
me with the opportunity to work on this series
  of practicals. Their invaluable guidance and
       support have been instrumental in
understanding the core concepts of Operating
                   Systems.
 I would also like to thank Ramanujan College,
   University of Delhi, for offering such a rich
  curriculum that fosters technical learning and
hands-on experience. The practical applications
    of various algorithms and transformation
techniques have deepened my knowledge in the
                       field.
Furthermore, I would like to thank my peers for
 their encouragement and collaboration during
  the course of this project. Their inputs have
     enhanced my learning experience and
  contributed to a stimulating environment for
                problem-solving.
1. Execute various LINUX commands for:
i. Information Maintenance: wc, clear, cal,
who, date, pwd.
ii. File Management: cat, cp, rm, mv, cmp,
comm, diff, find, grep, awk.
iii. Directory Management: cd, mkdir, rmdir, ls.
Outputs:
i. Information Maintenance
wc(word count)
Clear (clears the terminal)
Cal(Shows calender)
Who(The who command is a simple and
effective way to display information about
currently logged-in users.)
Date(shows Date)
Pwd(displays the current working directory's
full path)
ii. File Management:
cat(a tool for working with files and their
contents)
Cp(Copies content of files)
Rm(removes files)
mv(used to move and rename files and
directories)
                                          ,
cmp(Compares two files byte-by-byte.)
Comm(Compares two sorted files line-by-line.)
 Diff(Shows line-by-line differences between
files.)
, find(Finds files/directories in a directory
hierarchy.)
, grep(Searches for patterns in files.)
, awk(Text-processing tool for structured
data.).
iii. Directory Management:
cd(Changes the current directory.).
mkdir,
rmdir,
ls.
Q2.Execute various LINUX commands for:
 i. Process Control: fork, getpid, ps, kill,
sleep
 ii. Communication: Input-output
redirection, Pipe
 iii. Protection Management: chmod,
chown, chgrp
Output:
i. Process Control:
  1. fork(): Used to create a new process
    by duplicating the calling process. It’s
    a system call, so it won't be executed
         directly in the shell, but through C
         programming.
Example in C:
#include <stdio.h>
#include <unistd.h>
int main() {
    pid_t pid = fork();
    if (pid == 0) {
        printf("This is the child process\n");
    } else {
        printf("This is the parent process\n");
    }
    return 0;
}
        2. getpid(): Gets the process ID of the
          calling process. Like fork(), this is used
          in C programming.
Example in C:
c
#include <stdio.h>
#include <unistd.h>
int main() {
    printf("Process ID: %d\n", getpid());
    return 0;
}
    3. ps: Shows information about active
      processes. The basic command is:
ps
    4. kill: Sends a signal to a process. It
      is commonly used to terminate a
      process.
 5. sleep: Pauses the execution of a
   script or process for a specified time
   (in seconds).
ii. Communication:
 1.    Input-output redirection: Allows
   you to redirect the input and output of
   commands to/from files or other
   streams.
 2.    Pipe: Allows you to send the output
   of one command to another command
   as input.
iii. Protection Management:
 1.   chmod: Changes the file
   permissions.
     o   To give read (r), write (w), and
         execute (x) permissions to the
         owner and read and execute
         permissions to the group and
         others.
     o   To add execute permission for the
         user.
 2.     chown: Changes the ownership of a
   file.
     o   Change owner to user1 and group to
         group1:
 3.  chgrp: Changes the group
   ownership of a file.
     o   Change the group of a file to
         group1:
These commands help in managing
processes, communication between
processes, and setting file permissions and
ownership in Linux.
 Q3. Write a program (using fork () and/or
exec () commands) where parent and child
                  execute:
        i.   same program, same code.
               ii.    same program, different
                      code.
               iii.   before terminating, the
                      parent waits for the child to
                      finish its task
Code: (i)
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
int main() {
  pid_t pid = fork(); // Create child process
  if (pid == 0) { // Child process
    std::cout << "This is the child process with PID " <<
getpid() << std::endl;
  } else { // Parent process
    std::cout << "This is the parent process with PID " <<
getpid() << std::endl;
      wait(NULL); // Wait for child to finish
  }
    return 0;
}
Output:
Code(ii):
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
int main() {
    pid_t pid = fork(); // Create child process
    if (pid == 0) { // Child process
    std::cout << "This is the child process with PID " <<
getpid() << std::endl;
      // Child performs a different task
    std::cout << "Child: Executing different code!" <<
std::endl;
    } else { // Parent process
    std::cout << "This is the parent process with PID " <<
getpid() << std::endl;
        // Parent performs its task
    std::cout << "Parent: Executing different code!" <<
std::endl;
        wait(NULL); // Wait for child to finish
    }
    return 0;
}
Output:
Code(iii):
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
int main() {
    pid_t pid = fork(); // Create child process
    if (pid == 0) { // Child process
    std::cout << "Child process with PID " << getpid() << "
started." << std::endl;
        sleep(2); // Simulating work in child
        std::cout << "Child process finished." << std::endl;
    } else { // Parent process
    std::cout << "Parent process with PID " << getpid() << "
started." << std::endl;
        wait(NULL); // Wait for child to finish
     std::cout << "Parent process resumed after child
finished." << std::endl;
    }
    return 0;
}
Output:
4. Write a program to report behaviour of
Linux kernel including kernel version, CPU
type and CPU information.
Code:
#include <iostream>
#include <cstdlib>
using namespace std;
int main() {
  cout << "Kernel Version and Information:" << endl;
  system("uname -r");
  cout << "\nCPU Information:" << endl;
  system("lscpu");
  return 0;
}Output:
5. Write a program to report behaviour of
Linux kernel including information on
configured memory, amount of free and
used memory. (Memory information)
Code:
#include <iostream>
#include <cstdlib>
int main() {
    std::cout << "Memory Information:" << std::endl;
    system("free -h");
    return 0;
}
Output:
6. Write a program to copy files using
system calls.
Code:
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
int main() {
  const char* source = "source.txt";
  const char* destination = "destination.txt";
  int src = open(source, O_RDONLY);
  if (src == -1) {
      std::cerr << "Error opening source file!" << std::endl;
      return 1;
  }
 int dest = open(destination, O_WRONLY | O_CREAT |
O_TRUNC, 0644);
  if (dest == -1) {
    std::cerr << "Error opening destination file!" <<
std::endl;
      close(src);
      return 1;
    }
    char buffer[1024];
    ssize_t bytesRead;
    while ((bytesRead = read(src, buffer, sizeof(buffer))) > 0) {
        write(dest, buffer, bytesRead);
    }
    close(src);
    close(dest);
    std::cout << "File copied successfully!" << std::endl;
    return 0;
}
Output:
(because there is no source file present)
 7. Write a program to implement FCFS
scheduling algorithm.
Code:
#include <iostream>
#include <vector>
#include <algorithm> // For std::sort
struct Process {
     int id, arrival_time, burst_time;
};
// Comparison function to sort processes by arrival time
bool compareByArrival(const Process& a, const Process&
b) {
     return a.arrival_time < b.arrival_time;
}
int main() {
     int n;
     std::cout << "Enter number of processes: ";
     std::cin >> n;
     std::vector<Process> processes(n);
     for (int i = 0; i < n; ++i) {
   std::cout << "Enter arrival time and burst time for
process " << i + 1 << ": ";
   std::cin >> processes[i].arrival_time >>
processes[i].burst_time;
     processes[i].id = i + 1;
 }
 // Sort processes by arrival time
  std::sort(processes.begin(), processes.end(),
compareByArrival);
 int time = 0;
 std::cout << "\nProcess Execution Order (FCFS):\n";
 for (const auto& p : processes) {
     if (time < p.arrival_time)
       time = p.arrival_time; // Wait for the process to arrive
     time += p.burst_time;        // Execute the process
     std::cout << "P" << p.id << " (Arrival: " << p.arrival_time
          << ", Burst: " << p.burst_time << ")\n";
 }
    return 0;
}
Output:
8. Write a program to implement SJF
scheduling algorithm.
Code:
#include <iostream>
#include <vector>
#include <algorithm>
struct Process {
     int id, burst_time, waiting_time, turnaround_time;
};
bool compare(Process p1, Process p2) {
     return p1.burst_time < p2.burst_time;
}
int main() {
     int n;
     std::cout << "Enter number of processes: ";
     std::cin >> n;
     std::vector<Process> processes(n);
     for (int i = 0; i < n; ++i) {
        std::cout << "Enter burst time for process " << i + 1 <<
": ";
        std::cin >> processes[i].burst_time;
      processes[i].id = i + 1;
  }
  std::sort(processes.begin(), processes.end(), compare);
  int time = 0;
  double total_wt = 0, total_tat = 0;
  std::cout << "Process Execution Order (SJF):\n";
  for (auto& p : processes) {
      p.waiting_time = time;
      p.turnaround_time = p.waiting_time + p.burst_time;
      time += p.burst_time;
      total_wt += p.waiting_time;
      total_tat += p.turnaround_time;
      std::cout << "P" << p.id << " (Burst: " << p.burst_time
           << ", Waiting Time: " << p.waiting_time
           << ", Turnaround Time: " << p.turnaround_time <<
")\n";
  }
  std::cout << "Average Waiting Time: " << total_wt / n <<
std::endl;
  std::cout << "Average Turnaround Time: " << total_tat / n
<< std::endl;
    return 0;
}
Output:
9. Write a program to implement non-
preemptive priority-based scheduling
algorithm.
Code:
#include <iostream>
#include <vector>
#include <algorithm>
struct Process {
  int id, burst_time, priority, waiting_time,
turnaround_time;
};
bool compare(Process p1, Process p2) {
     return p1.priority < p2.priority;
}
int main() {
     int n;
     std::cout << "Enter number of processes: ";
     std::cin >> n;
     std::vector<Process> processes(n);
     for (int i = 0; i < n; ++i) {
     std::cout << "Enter burst time and priority for process "
<< i + 1 << ": ";
   std::cin >> processes[i].burst_time >>
processes[i].priority;
     processes[i].id = i + 1;
 }
 std::sort(processes.begin(), processes.end(), compare);
 int time = 0;
 double total_wt = 0, total_tat = 0;
 std::cout << "Process Execution Order (Priority
Scheduling):\n";
 for (auto& p : processes) {
     p.waiting_time = time;
     p.turnaround_time = p.waiting_time + p.burst_time;
     time += p.burst_time;
     total_wt += p.waiting_time;
     total_tat += p.turnaround_time;
     std::cout << "P" << p.id << " (Burst: " << p.burst_time
          << ", Priority: " << p.priority
           << ", Waiting Time: " << p.waiting_time
           << ", Turnaround Time: " << p.turnaround_time <<
")\n";
    }
  std::cout << "Average Waiting Time: " << total_wt / n <<
std::endl;
  std::cout << "Average Turnaround Time: " << total_tat / n
<< std::endl;
    return 0;
}
Output:
10. Write a program to implement SRTF
scheduling algorithm.
Code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
struct Process {
  int id, arrival_time, burst_time, remaining_time,
completion_time, waiting_time, turnaround_time;
};
bool compareArrivalTime(Process p1, Process p2) {
     return p1.arrival_time < p2.arrival_time;
}
int main() {
     int n;
     std::cout << "Enter number of processes: ";
     std::cin >> n;
     std::vector<Process> processes(n);
     for (int i = 0; i < n; ++i) {
   std::cout << "Enter arrival time and burst time for
process " << i + 1 << ": ";
   std::cin >> processes[i].arrival_time >>
processes[i].burst_time;
     processes[i].id = i + 1;
   processes[i].remaining_time =
processes[i].burst_time; // Initialize remaining time
 }
 // Sort processes based on arrival time
  std::sort(processes.begin(), processes.end(),
compareArrivalTime);
 int currentTime = 0, completed = 0;
 float totalWaitingTime = 0, totalTurnaroundTime = 0;
 std::vector<bool> isCompleted(n, false);
 // Execute processes until all are completed
 while (completed < n) {
     int shortestProcess = -1;
     int minRemainingTime = INT_MAX;
    // Find the process with the shortest remaining time
that has arrived
    for (int i = 0; i < n; ++i) {
     if (!isCompleted[i] && processes[i].arrival_time <=
currentTime && processes[i].remaining_time <
minRemainingTime) {
            minRemainingTime = processes[i].remaining_time;
            shortestProcess = i;
        }
    }
    if (shortestProcess != -1) {
        // Process the shortest job
        processes[shortestProcess].remaining_time--;
        currentTime++;
        // If the process is completed
        if (processes[shortestProcess].remaining_time == 0)
{
       processes[shortestProcess].completion_time =
currentTime;
       processes[shortestProcess].turnaround_time =
processes[shortestProcess].completion_time -
processes[shortestProcess].arrival_time;
       processes[shortestProcess].waiting_time =
processes[shortestProcess].turnaround_time -
processes[shortestProcess].burst_time;
       totalWaitingTime +=
processes[shortestProcess].waiting_time;
       totalTurnaroundTime +=
processes[shortestProcess].turnaround_time;
             isCompleted[shortestProcess] = true;
             completed++;
         }
     } else {
         // If no process is ready to execute, increment time
         currentTime++;
     }
 }
 // Output the results
 std::cout << "\nProcess execution details (SRTF
Scheduling):\n";
  for (const auto& p : processes) {
    std::cout << "P" << p.id << " (Arrival Time: " <<
p.arrival_time
         << ", Burst Time: " << p.burst_time
         << ", Completion Time: " << p.completion_time
         << ", Turnaround Time: " << p.turnaround_time
         << ", Waiting Time: " << p.waiting_time << ")\n";
  }
  std::cout << "\nAverage Waiting Time: " <<
totalWaitingTime / n << std::endl;
  std::cout << "Average Turnaround Time: " <<
totalTurnaroundTime / n << std::endl;
return 0;}
Output:
11. Write a program to calculate sum of n
numbers using Pthreads. A list of n
numbers is divided into two smaller list of
equal size, two separate threads are used
to sum the sub lists.
Code:
#include <iostream>
#include <pthread.h>
#include <vector>
struct ThreadData {
     std::vector<int>* data;
     int start, end;
     int sum;
};
void* sum_partial(void* arg) {
     ThreadData* td = (ThreadData*)arg;
     td->sum = 0;
     for (int i = td->start; i < td->end; ++i) {
       td->sum += (*td->data)[i];
    }
    return nullptr;
}
int main() {
    int n;
    std::cout << "Enter number of elements: ";
    std::cin >> n;
    std::vector<int> data(n);
    std::cout << "Enter the numbers:\n";
    for (int i = 0; i < n; ++i) {
        std::cin >> data[i];
    }
    pthread_t threads[2];
    ThreadData td1 = {&data, 0, n / 2, 0};
    ThreadData td2 = {&data, n / 2, n, 0};
    pthread_create(&threads[0], nullptr, sum_partial, &td1);
    pthread_create(&threads[1], nullptr, sum_partial, &td2);
    pthread_join(threads[0], nullptr);
    pthread_join(threads[1], nullptr);
    int total_sum = td1.sum + td2.sum;
    std::cout << "Total sum: " << total_sum << std::endl;
    return 0;
}
Output:
12. Write a program to implement first-fit,
best-fit and worst-fit allocation strategies.
Code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// Function to display memory allocation
void displayAllocation(const vector<int>& blockSize,
const vector<int>& processSize, const vector<int>&
allocation) {
  cout << "Process No.\tProcess Size\tBlock No.\tBlock
Size\n";
  for (size_t i = 0; i < allocation.size(); ++i) {
    if (allocation[i] != -1) {
        cout << " " << i + 1 << "\t\t" << processSize[i]
        << "\t\t" << allocation[i] + 1 << "\t\t" <<
blockSize[allocation[i]] << endl;
    } else {
      cout << " " << i + 1 << "\t\t" << processSize[i] <<
"\t\tNot Allocated\n";
    }
    }
}
// First-Fit Memory Allocation
vector<int> firstFit(const vector<int>& blockSize, const
vector<int>& processSize) {
 vector<int> allocation(processSize.size(), -1); // -1
means not allocated
    vector<int> blocks = blockSize;
    for (size_t i = 0; i < processSize.size(); ++i) {
        for (size_t j = 0; j < blocks.size(); ++j) {
            if (blocks[j] >= processSize[i]) {
                allocation[i] = j;
        blocks[j] -= processSize[i]; // Reduce the available
block size
                break;
            }
        }
    }
    return allocation;
}
// Best-Fit Memory Allocation
vector<int> bestFit(const vector<int>& blockSize, const
vector<int>& processSize) {
 vector<int> allocation(processSize.size(), -1); // -1
means not allocated
    vector<int> blocks = blockSize;
    for (size_t i = 0; i < processSize.size(); ++i) {
      int bestIdx = -1;
      for (size_t j = 0; j < blocks.size(); ++j) {
          if (blocks[j] >= processSize[i]) {
              if (bestIdx == -1 || blocks[bestIdx] > blocks[j]) {
                  bestIdx = j;
              }
          }
      }
      if (bestIdx != -1) {
          allocation[i] = bestIdx;
      blocks[bestIdx] -= processSize[i]; // Reduce the
available block size
        }
    }
    return allocation;
}
// Worst-Fit Memory Allocation
vector<int> worstFit(const vector<int>& blockSize, const
vector<int>& processSize) {
 vector<int> allocation(processSize.size(), -1); // -1
means not allocated
    vector<int> blocks = blockSize;
    for (size_t i = 0; i < processSize.size(); ++i) {
        int worstIdx = -1;
        for (size_t j = 0; j < blocks.size(); ++j) {
            if (blocks[j] >= processSize[i]) {
              if (worstIdx == -1 || blocks[worstIdx] < blocks[j]) {
                  worstIdx = j;
              }
            }
        }
        if (worstIdx != -1) {
            allocation[i] = worstIdx;
      blocks[worstIdx] -= processSize[i]; // Reduce the
available block size
        }
    }
    return allocation;
}
int main() {
    // Sample input for memory blocks and processes
  vector<int> blockSize = {100, 500, 200, 300, 600}; //
Block sizes
  vector<int> processSize = {212, 417, 112, 426}; //
Process sizes
    // First-Fit Allocation
  vector<int> firstFitAlloc = firstFit(blockSize,
processSize);
    cout << "First-Fit Allocation:\n";
    displayAllocation(blockSize, processSize, firstFitAlloc);
    // Best-Fit Allocation
  vector<int> bestFitAlloc = bestFit(blockSize,
processSize);
    cout << "\nBest-Fit Allocation:\n";
    displayAllocation(blockSize, processSize, bestFitAlloc);
    // Worst-Fit Allocation
  vector<int> worstFitAlloc = worstFit(blockSize,
processSize);
    cout << "\nWorst-Fit Allocation:\n";
    displayAllocation(blockSize, processSize, worstFitAlloc);
    return 0;
}
Output: