Operating System - Ass

Download as pdf or txt
Download as pdf or txt
You are on page 1of 26

Operating System

Parveen Kumar
2022ucp1577

Assignment - 1

Q1. Convert text to ASCII values using file handling


Sol:
#include<iostream>
#include<fstream>
#include<sstream>
#include<vector>
using namespace std;

void to_AsciiValue(const string& str){


ofstream outputFile("output.txt");
if(!outputFile){
cerr<<"Failed to open output file"<<endl;
return ;
}
int len = str.size();
int converted_form;
for(int i=0;i<len;i++){
converted_form = str[i];
outputFile<<converted_form<<" ";
}
outputFile.close();
}
int main(){
string text;
string wholetext = "";

ifstream inputFile("input.txt");
while(getline(inputFile,text)){
wholetext += text;
}
to_AsciiValue(wholetext);
inputFile.close();
return 0;
}

Q2. convert text to hexadecimal and also print frequency


using file handling
Sol.
#include<iostream>
#include<fstream>
#include<vector>
#include<bits/stdc++>
using namespace std;

int freqCount(string str,char ch){


int count = 0;
for(int i=0;i<str.size();i++){
char s = str[i];
if(s == ch){
Count++;
}
}
return count;
}
int to_HexValue(string &str){
ofstream outputFile(“output.txt”);
vector<vector<int>>v;
int len = str.size();
int ascii;
for(int i=0;i<len;i++){
ascii = str[i];

vector<int>arr;
int j = 0;
while(ascii != 0){
j = ascii%16;
arr.push_back(j);
ascii = ascii/16;
}
reverse(arr.begin(),arr.end());
v.push_back(arr);
}
for(auto i: v){
for(auto j: i){
outputFile<<j;
}
outputFile<<” “;
}
outputFile.close();
}
Int main(){
String text;
string wholetext = “”;
ifstream inputFile(“input.txt”);
while(getline(inputFile,text)){
wholetext += text;
}
to_HexValue(wholetext);
inputFile.close();
return 0;
}
Assignment - 2
Process API and system Calls

Q1. Download the code against &#39;process


API&#39;, &#39;thread API&#39; and &#39;address
space&#39;.
Refer to the orange table after scrolling down. Run these
programs.
For each program, identify system calls, understand
these calls through the main
command.
Ans - Process API SYSTEM CODE:
(i) P1.c
The fork() system call in UNIX and UNIX-like operating
systems is used to create a new
process. The new process created by fork() is a child
process and is a near-exact copy
of the parent process that is called fork(). How fork()
works and what happens when it is
called:
1. Initial Execution: When a program starts running, it
executes from the main()
function. The process running this program is assigned
a unique process
identifier (PID).

2. Calling fork(): When fork() is called, the operating


system creates a new
process. This new process is a duplicate of the parent
process, meaning it has
the same memory contents, the same code, and the
same file descriptors.
3. Return Values:
In the child process, fork() returns 0.
In the parent process, fork() returns the PID of the newly
created child
process.
If fork() fails, it returns -1 in the parent process.

4. Execution Paths:
After fork() is called, both the parent and child processes
continue
executing from the point where fork() was called.
However, they can take
different execution paths based on the return value of
fork().

Code :
#include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4
5 int main(int argc, char *argv[]) {
6 printf("hello (pid:%d)\n", (int) getpid());
7 int rc = fork();
8 if (rc < 0) {
9 // fork failed
10 fprintf(stderr, "fork failed\n");
11 exit(1);
12 } else if (rc == 0) {
13 // child (new process)
14 printf("child (pid:%d)\n", (int) getpid());
15 } else {
16 // parent goes down this path (main)
17 printf("parent of %d (pid:%d)\n",
18 rc, (int) getpid());
19 }
20 return 0;
21 }

Output:
➜ ./p1
hello world (pid:8048)
value of rc: 8049
hello, I am parent of 8049 (pid:8048)
value of rc: 0
hello, I am child (pid:8049)
…………………………………………………………………
……………………………………
(ii) P2.c
The fork() system call is used to create a new process,
and wait() is used by the parent
process to wait for the child process to finish execution.
Here&#39;s a detailed explanation of
how these system calls work together:
1. Initial Execution: The program starts execution from
the main() function, and the
process running this program is assigned a unique
process identifier (PID).

2. Calling fork(): When fork() is called, the operating


system creates a new
process. This new process is a duplicate of the parent
process, with its own
memory space, registers, and program counter.
However, the return value of
fork() is different in the parent and child processes:
In the child process, fork() returns 0.
In the parent process, fork() returns the PID of the newly
created child
process.
If fork() fails, it returns -1 in the parent process.
3. Calling wait():
The wait() system call makes the parent process wait
until all of its child
processes have terminated. When a child process
terminates, wait()
returns the PID of the terminated child process.
This ensures that the parent process does not proceed
until the child has
finished executing, making the output deterministic.

Code:
#include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/wait.h>
5
6 int main(int argc, char *argv[]) {
7 printf("hello (pid:%d)\n", (int) getpid());
8 int rc = fork();
9 if (rc < 0) { // fork failed; exit
10 fprintf(stderr, "fork failed\n");
11 exit(1);
12 } else if (rc == 0) { // child (new process)
13 printf("child (pid:%d)\n", (int) getpid());
14 } else { // parent goes down this path
15 int rc_wait = wait(NULL);
16 printf("parent of %d (rc_wait:%d) (pid:%d)\n",
17 rc, rc_wait, (int) getpid());
18 }
19 return 0;
20 }

Output:
➜ ./p2
hello world (pid:8057)
value of rc: 8058
value of rc: 0
hello, I am child (pid:8058)
hello, I am parent of 8058 (wc:8058) (pid:8057)
…………………………………………………………………
………………………………….

(iii) P3.c
In this section, we will explore the exec() system call,
which is used to run a
different program from within a child process created by
fork(). This allows the
child process to replace its entire memory space with a
new program.
The fork() system call is used to create a new process
(the child), and the wait()
system call is used by the parent process to wait for the
child process to finish.
The exec() system call is then used by the child process
to replace its memory
space with a new program. This combination is powerful
and commonly used in
UNIX-like operating systems.

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;unistd.h&gt;
#include &lt;string.h&gt;
#include &lt;sys/wait.h&gt;

int
main(int argc, char *argv[])
{
printf(&quot;hello world (pid:%d)\n&quot;, (int) getpid());
int rc = fork();
if (rc &lt; 0) {
// fork failed; exit
fprintf(stderr, &quot;fork failed\n&quot;);
exit(1);
} else if (rc == 0) {
// child (new process)
printf(&quot;hello, I am child (pid:%d)\n&quot;, (int)
getpid());

char *myargs[3];
myargs[0] = strdup(&quot;wc&quot;); // program:
&quot;wc&quot; (word count)
myargs[1] = strdup(&quot;p3.c&quot;); // argument: file
to count
myargs[2] = NULL; // marks end of array
execvp(myargs[0], myargs); // runs word count
printf(&quot;this shouldn&#39;t print out&quot;);
} else {
// parent goes down this path (original process)
int wc = wait(NULL);
printf(&quot;hello, I am parent of %d (wc:%d)
(pid:%d)\n&quot;,
rc, wc, (int) getpid());
}
return 0;
}
➜ ./p3
hello world (pid:8064)
value of rc: 8065
value of rc: 0
hello, I am child (pid:8065)
34 130 1020 p3.c
hello, I am parent of 8065 (wc:8065) (pid:8064)
…………………………………………………………………
…………………………………..

(iv) p4.c
we extend the process creation and management API to
include output
redirection. We use the fork() system call to create a
new process (child),
the wait() system call to wait for the child process to
complete, and the

execvp() system call to replace the child process&#39;s


memory space with a
new program. Additionally, we demonstrate how to
redirect the output of
the child process to a file using the close() and open()
system calls.
Example Code with Explanation
Example code demonstrating the use of fork(), wait(),
execvp(), and output
redirection:

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;unistd.h&gt;
#include &lt;string.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;assert.h&gt;
#include &lt;sys/wait.h&gt;

int
main(int argc, char *argv[])
{
int rc = fork();
if (rc &lt; 0) {
// fork failed; exit
fprintf(stderr, &quot;fork failed\n&quot;);
exit(1);
} else if (rc == 0) {
// child: redirect standard output to a file

close(STDOUT_FILENO);
open(&quot;./p4.output&quot;,
O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);

// now exec &quot;wc&quot;...


char *myargs[3];
myargs[0] = strdup(&quot;wc&quot;); // program:
&quot;wc&quot; (word count)
myargs[1] = strdup(&quot;p4.c&quot;); // argument: file
to count
myargs[2] = NULL; // marks end of array
execvp(myargs[0], myargs); // runs word count
} else {
// parent goes down this path (original process)
int wc = wait(NULL);
assert(wc &gt;= 0);
}
return 0;
}

Output:
➜ ./p4
value of rc: 8074
value of rc: 0
Assignment - 3
CPU Scheduling using file handling and printing
statues of processes at all time.

#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
#include <string>
#include <sstream>
#include <map>
using namespace std;
struct Process {
int id, priority, arrivalTime;
vector<int> bursts; // CPU and IO bursts
int burstIndex = 0, remainingTime, startTime = -1,
completionTime = -1;
string history = "";
};
void readProcessesFromFile(vector<Process>&
processes, const string& filename) {
ifstream file(filename);
string line;
getline(file, line);
int n = stoi(line);
for (int i = 0; i < n; ++i) {
getline(file, line);
stringstream ss(line);
string token;
Process proc;
getline(ss, token, ','); proc.id = stoi(token);
getline(ss, token, ','); proc.priority = stoi(token);
getline(ss, token, ','); proc.arrivalTime = stoi(token);
while (getline(ss, token, ',')) {
int burst = stoi(token);
if (burst == -1) break;
proc.bursts.push_back(burst);
}
proc.remainingTime = proc.bursts[0];
processes.push_back(proc);
}
file.close();
}
void printProcessHistory(const vector<Process>&
processes) {
for (const auto& proc : processes) {
cout << "Process " << proc.id << ": " << proc.history <<
endl;
}
}
void fcfs(vector<Process> processes) {
queue<Process*> readyQueue;
int time = 0;
while (!processes.empty() || !readyQueue.empty()) {
for (auto it = processes.begin(); it != processes.end();) {
if (it->arrivalTime <= time) {
readyQueue.push(&(*it));
it = processes.erase(it);
} else {
++it;
}
}
if (!readyQueue.empty()) {
Process* proc = readyQueue.front();
readyQueue.pop();
while (proc->burstIndex < proc->bursts.size()) {
for (int t = 0; t < proc->bursts[proc->burstIndex]; ++t) {
proc->history += 'C';
++time;
}
proc->burstIndex++;
if (proc->burstIndex < proc->bursts.size()) {
for (int t = 0; t < proc->bursts[proc->burstIndex]; ++t) {
proc->history += 'R';
++time;
}
proc->burstIndex++;
}
}
proc->completionTime = time;
} else {
++time;
}
}
printProcessHistory(processes);
}
void sjf(vector<Process> processes) {
auto cmp = [](Process* a, Process* b) {
return a->remainingTime > b->remainingTime;

};
priority_queue<Process*, vector<Process*>,
decltype(cmp)> readyQueue(cmp);
int time = 0;
while (!processes.empty() || !readyQueue.empty()) {
for (auto it = processes.begin(); it != processes.end();) {
if (it->arrivalTime <= time) {
readyQueue.push(&(*it));
it = processes.erase(it);
} else {
++it;
}
}
if (!readyQueue.empty()) {
Process* proc = readyQueue.top();
readyQueue.pop();
while (proc->burstIndex < proc->bursts.size()) {
proc->history += 'C';
++time;
proc->remainingTime--;
if (proc->remainingTime == 0) {
proc->burstIndex += 2;
if (proc->burstIndex < proc->bursts.size()) {
proc->remainingTime = proc->bursts[proc->burstIndex];
}
break;
}
}
if (proc->remainingTime > 0) {
readyQueue.push(proc);
} else {
proc->completionTime = time;
}
} else {
++time;
}
}
printProcessHistory(processes);
}
void priorityScheduling(vector<Process> processes) {
auto cmp = [](Process* a, Process* b) {
return a->priority > b->priority;
};
priority_queue<Process*, vector<Process*>,
decltype(cmp)> readyQueue(cmp);

int time = 0;
while (!processes.empty() || !readyQueue.empty()) {
for (auto it = processes.begin(); it != processes.end();) {
if (it->arrivalTime <= time) {
readyQueue.push(&(*it));
it = processes.erase(it);
} else {
++it;
}
}
if (!readyQueue.empty()) {
Process* proc = readyQueue.top();
readyQueue.pop();
while (proc->burstIndex < proc->bursts.size()) {
proc->history += 'C';
++time;
proc->remainingTime--;
if (proc->remainingTime == 0) {
proc->burstIndex += 2;
if (proc->burstIndex < proc->bursts.size()) {
proc->remainingTime = proc->bursts[proc->burstIndex];
}
break;
}
}
if (proc->remainingTime > 0) {
readyQueue.push(proc);
} else {
proc->completionTime = time;
}
} else {
++time;
}
}
printProcessHistory(processes);
}
void roundRobin(vector<Process> processes, int
quantum) {
queue<Process*> readyQueue;
int time = 0;
while (!processes.empty() || !readyQueue.empty()) {
for (auto it = processes.begin(); it != processes.end();) {
if (it->arrivalTime <= time) {
readyQueue.push(&(*it));

it = processes.erase(it);
} else {
++it;
}
}
if (!readyQueue.empty()) {
Process* proc = readyQueue.front();
readyQueue.pop();
int slice = min(quantum, proc->remainingTime);
for (int t = 0; t < slice; ++t) {
proc->history += 'C';
++time;
}
proc->remainingTime -= slice;
if (proc->remainingTime == 0) {
proc->burstIndex += 2;
if (proc->burstIndex < proc->bursts.size()) {
proc->remainingTime = proc->bursts[proc->burstIndex];
} else {
proc->completionTime = time;
}
}
if (proc->remainingTime > 0) {
readyQueue.push(proc);
}
} else {
++time;
}
}
printProcessHistory(processes);
}
int main() {
vector<Process> processes;
readProcessesFromFile(processes, "proc.dat");
int choice;
cout << "Choose Scheduling Algorithm:\n";
cout << "1. FCFS\n2. SJF (Preemptive)\n3. Priority
(Preemptive)\n4. Round Robin\n";
cin >> choice;
switch (choice) {
case 1: fcfs(processes); break;
case 2: sjf(processes); break;

case 3: priorityScheduling(processes); break;


case 4: roundRobin(processes, 1); break;
default: cout << "Invalid choice\n"; break;
}
return 0;
}
..........................................................................................
......
Proc.dat File:
3
1,3,0,8,5,-1
2,1,2,4,2,3,6,-1
3,2,4,5,4,-1
..........................................................................................
......
Explanation:
Process 1:
○ Priority: 3
○ Arrival Time: 0
○ CPU bursts: 8 and 5
● Process 2:
○ Priority: 1
○ Arrival Time: 2
○ CPU bursts: 4 and 6
○ IO bursts: 2 and 3
● Process 3:
○ Priority: 2
○ Arrival Time: 4
○ CPU bursts: 5 and 4
Explanation of Output Symbols:
● C: Process running on CPU.
● W: Process waiting for CPU.
● R: Process running on IO.

I. FCFS (First-Come, First-Served) Output


● Process 1 arrives at time 0 and runs immediately.
● Process 2 arrives at time 2 but waits until Process 1
finishes.
● Process 3 arrives at time 4 but waits for Processes 1
and 2.
Process 1: CCCCCCCCCWWWWWWWWWCCCC
Process 2: WWWWCCCCWWWWWWWWRRRRRRR
Process 3: WWWWWWWWWWWWWCCCCCCCC

II. SJF (Preemptive Shortest Job First) Output


● Process 1 starts at time 0.
● Process 2 arrives at time 2 but has a shorter CPU
burst and preempts Process 1.
● Process 3 arrives at time 4 and will be scheduled
according to the remaining burst times
Process 1: CCWWCCWWWWWWWWCCCCCCCC
Process 2: WWCCCCWWWWWWWWWWRRRRRR
Process 3: WWWWCCCCCCCCWWWWWWWW

III. Priority (Preemptive) Output


● Process 2 arrives at time 2 with the highest priority
and preempts Process 1.
● Process 3 arrives at time 4 but has a lower priority
than Process 2, so Process 2
continues.
Process 1: CCWWWWWWWWCCCCCCCC
Process 2: WWCCCCRRRRRRWWWWWWWW
Process 3: WWWWCCCCCCCCWWWWWW

IV. Round Robin (Quantum = 1) Output


● Processes are scheduled in a round-robin fashion with
a quantum of 1.
● All processes get a chance to run one CPU burst at a
time.
Process 1: CCCWWCCCWWWWCCCCCCCC
Process 2: WWCCCCWRRCCCCWRRRRR
Process 3: WWWWCCWWCCWWWWWWWW

You might also like