0% found this document useful (0 votes)
3 views8 pages

Operating System Process Management Assignment

The document is an assignment on Operating Systems (CPT-211) submitted by Muhammad Usman Gondal. It includes programming exercises related to process management using fork(), detailing the behavior of processes, their creation, and output ordering. The assignment covers multiple questions about fork behavior, process creation, and output expectations in various scenarios.

Uploaded by

awais.raza0381
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)
3 views8 pages

Operating System Process Management Assignment

The document is an assignment on Operating Systems (CPT-211) submitted by Muhammad Usman Gondal. It includes programming exercises related to process management using fork(), detailing the behavior of processes, their creation, and output ordering. The assignment covers multiple questions about fork behavior, process creation, and output expectations in various scenarios.

Uploaded by

awais.raza0381
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

Course Title:

Operating System
Course Code:
CPT-211
Assignment No:
1
Submitted by:
Muhammad Usman Gondal
Roll No:
24017322-007
Section:
A
Department:
Computer Engineering Technology
Submitted To:
Sir Wasif
Institute:
University of Gujrat
Operating Systems (CPT-211)
Process Management Assignment
Q1 — Fork Output (10 marks):

Program:

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

int main() {
printf("Start\n");
fork(); /* LINE A: fork() is called here */
printf("After fork\n");
return 0;
}

a) How many times and why each string is printed?

 "Start" — printed exactly once.


Reason: printf("Start\n") happens before fork(). Only the original process exists at
that time, so one print.
 "After fork" — printed exactly twice.
Reason: fork() creates a child process. After fork() both parent and child continue
executing the next statement, so each executes the printf("After fork\n") once → 2
prints.

b) If LINE A is the fork() call, which process(es) execute the printf immediately
after LINE A?

 Both processes execute the printf immediately after LINE A: the parent and the
child.

c) Could ordering between 'Start' and the first 'After fork' vary?

 No — "Start" will always appear before any "After fork" lines because "Start" is
executed (and the newline causes a flush) before fork() is called.
 However, the relative ordering of the two "After fork" lines (parent vs child) can
vary: either the parent or the child may print first depending on scheduler timing.

Example possible output:

Start
After fork
After fork

(But the two After fork lines may appear in either order between parent/child.)

Q2 — Three forks (10 marks):


Program:

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

int main() {
fork(); /* A */
fork(); /* B */
fork(); /* C */
printf("Hello from process!\n");
return 0;
}

a) Exactly how many processes are created in total, including the original parent?

 Each fork() doubles the number of processes. After 3 forks total processes =
2^3=8.
So 8 processes total.

b) Process tree (symbolic PIDs)

Start with original process P.

 After A: P → creates C1
 After B: both P and C1 each fork() → P creates C2; C1 creates C3
 After C: all four processes fork → total 8

Symbolically:

P
├─ C1 (created at A)
│ ├─ C3 (created at B from C1)
│ │ ├─ C5 (created at C)
│ │ └─ C6 (created at C)
│ └─ C4 (created at C)
└─ C2 (created at B from P)
├─ C7 (created at C)
└─ C8 (created at C)

(There are many ways to label children; important is the branching that leads to 8 leaves.)

c) Does every process execute the printf and why?

 Yes. The printf is after all forks and is executed by every process that still exists
after the three fork() calls. Since each fork duplicates the process including the
program counter just after the fork(), all 8 processes reach and execute the printf
once. So you get 8 prints.

Example output (order can vary):

Hello from process!


Hello from process!
Hello from process!
Hello from process!
Hello from process!
Hello from process!
Hello from process!
Hello from process!

Q3 — Two forks (10 marks)

Program

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

int main() {
fork(); /* 1 */
fork(); /* 2 */
printf("Process running...\n");
return 0;
}

a) How many processes are created including the initial parent?

 Two fork() calls → 2^2=4 processes total.

b) Show the order in which the two fork() calls are executed across processes

Step-by-step:

1. Start: one process P.


2. fork(); /*1*/ -> P creates C1. Now two processes: P, C1.
Both continue after fork() at the next line.
3. fork(); /*2*/ is executed by both P and C1.
o P executes fork -> P creates C2.
o C1 executes fork -> C1 creates C3.
4. Now processes: P, C1, C2 (child of P), C3 (child of C1).
5. All four execute the printf.

So the second fork() is executed twice (once in each of the two processes that existed after
the first fork), producing two more processes.

c) If we wanted only one child of the parent (total two processes), how to change the
code?

 Solution: remove the second fork() so there is only one fork() called:

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

int main() {
fork(); /* only a single fork -> parent + one child = 2 processes */
printf("Process running...\n");
return 0;
}

 Alternative (keeping two fork calls syntactically): ensure the second fork() is
executed only by one process (e.g., by checking return value), but simplest and
clearest is to remove the second fork().

Q4 — Conditional and common code (10 marks)

Program

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

int main() {
pid_t pid = fork();
if (pid == 0) {
printf("Child executing\n");
} else if (pid > 0) {
printf("Parent executing\n");
} else {
perror("fork failed");
return 1;
}
printf("LINE J\n");
return 0;
}

a) Which process(es) execute the printf at LINE J? Explain.

 Both parent and child execute printf("LINE J\n"); (so it prints twice).
Reason: After the conditional that distinguishes parent and child, both branches
end and control reaches the common printf("LINE J\n"); in each process.

b) Is there any circumstance where LINE J would be printed only once?

 With this exact code, LINE J is normally printed twice. It would be printed only
once if one of the two processes does not reach that line, for example:
o If fork() failed (pid < 0), the code goes to the else branch, calls perror(...) and
return 1; — then no LINE J is printed (0 times).
o If one of the processes explicitly called exit() or crashed before reaching
LINE J (or killed by a signal), then you could see it printed only once.
 So by default (successful fork, no exit/crash) it’s printed twice.

c) What would change if we placed wait(NULL) in the parent before LINE J?

Change:

if (pid == 0) {
printf("Child executing\n");
} else if (pid > 0) {
printf("Parent executing\n");
wait(NULL); /* parent waits here for child to finish */
}
printf("LINE J\n");

 Effect: Parent will block at wait(NULL) until the child terminates. That guarantees
child’s prints (including its LINE J) happen before the parent prints its LINE J.
 Net result: Still two prints of LINE J, but ordering is guaranteed: child prints
LINE J first, then parent prints LINE J after waiting.

Q5 — pid return values and getpid/getppid (10 marks)

Given: parent PID = 2600, child PID = 2603, shell PID = 2599.

Program

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

int main() {
pid_t pid;
pid = fork();
printf("Line A: pid (return value of fork) = %d\n", pid);
if (pid == 0) {
printf("Line B: Child PID (getpid) = %d\n", getpid());
} else if (pid > 0) {
printf("Line C: Parent PID (getpid) = %d\n", getpid());
}
printf("Line D: Parent of this process (getppid) = %d\n", getppid());
return 0;
}

a) Exact printed values at Line A–D for both parent and child

 Parent process (PID 2600):


o Line A: pid (return value of fork) = 2603 (fork returns child PID to parent)
o Line C: Parent PID (getpid) = 2600
o Line D: Parent of this process (getppid) = 2599 (the shell PID)
 Child process (PID 2603):
o Line A: pid (return value of fork) = 0 (fork returns 0 in child)
o Line B: Child PID (getpid) = 2603
o Line D: Parent of this process (getppid) = 2600 (the parent's PID)

So combined (order may vary):

Line A: pid (return value of fork) = 2603 <-- parent


Line C: Parent PID (getpid) = 2600 <-- parent
Line D: Parent of this process (getppid) = 2599 <-- parent

Line A: pid (return value of fork) = 0 <-- child


Line B: Child PID (getpid) = 2603 <-- child
Line D: Parent of this process (getppid) = 2600 <-- child
b) Explain why Line A prints different values

 fork() returns different values in the two processes:


o In the parent it returns the child’s PID (so parent sees 2603).
o In the child it returns 0.
 That’s the defined behavior of fork() and is how the program can tell which
process it is.

c) What would be printed for Line D when the parent runs under a shell with PID
2599?

 For the parent process, getppid() returns the shell PID = 2599, so Line D in the
parent prints 2599.
 For the child, getppid() returns the parent's PID = 2600, so Line D in the child
prints 2600.

Q6 — wait() ordering (10 marks):

Program

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
pid_t pid = fork();
if (pid == 0) {
printf("LINE X: Child executing\n");
} else if (pid > 0) {
wait(NULL);
printf("LINE Y: Parent after wait\n");
} else {
perror("fork failed");
}
return 0;
}

a) Provide the guaranteed order of printed lines (LINE X and LINE Y) and justify.

 Guaranteed order:
LINE X: Child executing before LINE Y: Parent after wait.
 Why: Parent calls wait(NULL) and blocks until the child process terminates. The
child prints LINE X before exiting, so the parent's LINE Y runs only after child
has finished.

b) If wait(NULL) is removed, describe how the output could appear and why.

 Without wait(NULL), parent and child execute independently; output order is not
guaranteed. Possible outputs:
o Child first then parent:
o LINE X: Child executing
o LINE Y: Parent after wait

o Parent first then child:


o LINE Y: Parent after wait
o LINE X: Child executing

o Or their outputs could even interleave if prints were more complex. The
scheduler decides which runs first.

c) If the child executes exec() to run /bin/ls before printing LINE X, how does that
affect the output?

 If the child calls execl("/bin/ls", "ls", (char *)NULL) (or a similar exec*) before printing
LINE X, then:
o The child’s process image is replaced with /bin/ls, so the original child code
(including printing LINE X) is not executed.
o The output will contain /bin/ls output (the directory listing) instead of LINE
X.
o The parent’s wait(NULL) still waits for the child (now running ls) to finish.
After ls completes and the child exits, the parent prints LINE Y.
 So LINE X may not appear at all; you’ll see ls output followed by LINE Y.

You might also like