How many times are executed the programs invoked by execl? - c

Can you help me with this?
How many times are executed the programs "exam" and "students" invoked by execl? I think the correct answer is 8 runtimes for program "exam" and 0 for "students", because in the two first forks will be created 3 child processes, after that in loop the first fork() will create more 4 processes, since the three children already created also will run this code, thereafter we have a exec that will replace the current code of the 7 processes created and of the actual program and run it(program "exam") 8 times. My reasoning is correct?
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
int main(){
int i;
pid_t
pid=fork();
pid=fork();
for(i=0;i<5;i++){
pid=fork();
execlp("exam","exam",NULL);
if(pid==0){
break;
}
}
execlp("students", "students","sistcomp",NULL);
return 0;
}

Theoretically, you are right. Let me draw a diagram to explain:
+---1 ...
|
+---+---2 ...
|
----+---+---3 ...
fork()|
+---4+---- execlp("exam","exam",NULL);
fork() |
+---- execlp("exam","exam",NULL);
^
after the first two fork()
you see, after 2 fork(), we get 4 process. Take the No.4 as an example, it enter for loop and fork() again, then we get another child process here, this child process and its father will exec execlp("exam","exam",NULL); as you see this will replace the current code.The same is true for No.1, No.2 and No.3.
So, it will be 8 runtimes for program "exam" and 0 for "students".
But, when you run this code, runtimes for program "exam" may be 7 or 6, it may be caused by Copy-on-write(I am not pretty sure about this)
PS:
It is a good practice to use execlp like this:
if (pid == 0)
execlp("exam","exam",NULL);
or
if (pid != 0)
execlp("exam","exam",NULL);

Related

Number of print statements Fork() [duplicate]

So I have to find the output of this code which is using the fork() method. I thought the output was 5 "hello" s but instead I got 8. Why is that? This is the code:
#include "csapp.h"
void doit()
{
Fork();
Fork();
printf("hello\n");
return;
}
int main()
{
doit();
printf("hello\n");
exit(0);
}
Here's what your code is doing:
main->doit()->Fork()->Fork()->printf()->return->printf()->exit()
| |
| ----->printf()->return->printf()->exit()
|
----->Fork()->printf()->return->printf()->exit()
|
----->printf()->return->printf()->exit()
As you can see, you have a total of 8 calls to printf().
It would have been easier for you to see what was going on if you chose to print different strings in your main and doit functions.
Setting breakpoint on each printf() call is another effective strategy for figuring out these kinds of problems.
First you call fork and your one process forks into two. Then you call fork in each resulting process and you have a total of 4. Then the 4 processes print hello, return, and print hello again, for a total of 8 hellos.
You create process #1. Before printing anything, process #1 calls fork() and generates a clone that we will call process #2. Both processes #1 and #2 call fork() again, cloning into processes #3 and #4. Now you have 4 processes and each one of them will print hello twice. How many hello are printed?

Understanding POSIX - fork()

I was reading about the fork function and how it creates new processes. The following program runs fine and prints here sixteen times, but, I am having trouble understanding the flow of execution:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
int main()
{
int i;
for (i = 0; i < 4; i++) { // line no. 12
fork(); // line no. 13
}
printf("%s\n", "here");
return 0;
}
It seems to me that there are two ways this program can be viewed as:
1st approach: fork() is called a total of four times. If I replace the loop with four calls to the fork() function, things seem to fall in place and I understand why here is printed 2 ^ 4 times.
2nd approach: fork() spawns a new process exactly from where it is invoked and each of these child processes have their own local variables. So, after line no. 13, each of these child processes see the end of the loop (}) and they go to line no. 12. Since, all these child processes have their own local variable i set to 0 (maybe i is set to some garbage value?), they all fork again. Again for these child processes their local variable i is set to 0. This should result in a fork bomb.
I am certainly missing something in my 2nd approach could someone please help?
Thanks.
Your 2nd approach is not right. Because after fork() the child process inherits the current value of i. It's nneither set to 0 everytime fork() is called nor do they have garbage value. So, your code can't have a fork bomb. The fact that it's a local variable is irrelevant. fork() clones pretty much everything and the child process is identical to its parent except for certain things as noted in the POSIX manual.
I'll reduce the loop count to 2 for ease of explaining and assume all fork() calls succeed:
for (i = 0; i < 2; i++) {
fork();
}
printf("%s\n", "here");
1) When i=0, fork() is executed and there are two processes now. Call them P1 and P2.
2) Now, each P1 and P2 processes continue with i=0 the loop and increment i to 1. The for loop condition is true, so each of them spawn another two processes and in total 4. Call them P1a & P1b and P2a & P2b. All 4 processes now have i=1 and increment it to 2 (as they continue the loop).
3) Now, all 4 processes have the value of i as 2 and for loop condition is false in all of them and "here" will be printed 4 times (one by each process).
If it helps, you can convert the for loop to a while loop and how i gets incremented by both processes returning from each fork() might become a bit more clear:
i = 0;
while(i < 2) {
fork();
i++;
}
printf("%s\n", "here");
Your first approach was right.
That's a rather boring answer, so I'll give you all the technical details.
When fork is called, several things happen:
A new process is created ('the child')
The stack of the parent is duplicated, and assigned to the child.
The stack pointer of the child is set to that of the parent.
The PID (process ID) of the child is returned to the parent.
Zero is returned to the child
variables declared inside a function are stored in the stack, and are therefore start at the same value, but are not shared.
variables declared outside a function (at the top level) are not in the stack, so are shared between child/parent.
(Some other things are or are not duplicated; see man fork for more information.)
So, when you run your code:
what happens # of processes
1. the parent forks. 2
2. the parent and it's child fork. 4
3. everyone forks 8
4. everyone forks 16
5. everyone prints "here". 16
You end up with sixteen processes, and the word 'here' sixteen times.
basically,
if(fork() != 0) {
parent_stuff();
} else {
child_stuff();
}
Using following code and you can easily see how fork create the value of variable i:
for (i = 0; i < 4; i++) {
printf("%d %s\n", i, "here");
fork();
}
As what you could expect, the child process copy the value of parent process and so we get 0 line with i = 0; 2 lines with i = 1; 4 lines with i = 2 and 8 lines with i = 3. Which I think answers your 2nd question.

Fork system call not exiting

I've run the following code :
#include <stdio.h>
#include <sys/types.h>
int main()
{
fork();
fork();
fork();
printf("hello\n");
return 0;
}
After printing the word "Hello" 8 times, the program is not exiting. What is the reason behind this?
This is an accidentally interesting way to calculate 2^3. The first fork makes the second fork happen twice and they each make the third fork happen twice and all 8 children run printf! The 8 processes do exit, but your prompt is lost in the noise.
As the commenters implied, you are fundamentally misunderstanding what fork() is and what it is doing. But along the way you made an interesting toy, so bravo!

How do processes branch out when you use fork() in a for loop?

fork() calls outside a loop are easy to figure out, but when they are inside a loop I find it difficult. Can anyone figuratively explain how the processes branch out with an example like this one?
#include <stdio.h>
int main(){
int i;
for(i=0;i<2;i++)
{
fork();
printf("hi");
fork();
}
exit(0);
}
Ideally, this would be the case:
There is one "hi" printed with each process (abbreviated as proc)
Each fork doubles the number of process (each process spawns one child)
The calculation could be done by following each event:
start: 1 proc
fork: 2 x 1 = 2 procs
print: 2 procs -> 2 hi's
fork: 2 x 2 = 4 procs
fork: 2 x 4 = 8 procs
print: 8 procs -> 8 hi's
fork: 2 x 8 procs -> 16 procs
Now we add up the the number of hi's:
2 + 8 = 10 hi's in total
However, this is not necessarily the case. On different systems, you may get different results.
A call to fork() causes a child process to be spawned that is identical to the parent.
If there is any buffering done when printing stdout and the buffers are not flushed before the next fork, then the child will appear to print when it "should not have". Refer to this question for some details on buffering.
This causes a different number of hi's to be printed an different systems.
Just unroll the loop:
int main() {
int i;
fork();
printf("hi");
fork();
fork();
printf("hi");
fork();
exit(0);
}
I've used this code :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
int i;
for(i=0;i<2;i++)
{
fork();
printf("hi from pid %d\n",getpid());
fork();
}
exit(0);
}
Now i've piped the output to fk.out.
[aft#kruki sf]$ cat fk.out
hi from pid 6698
hi from pid 6698
hi from pid 6699
.......................
Now look at this :
[aft#kruki sf]$ cat fk.out | awk '{print $4}' | sort | uniq | wc -l
8
There, you have it, you have 8 processes !. Don't coun't hi's. Because stdin buffer will switched back and forth, so counting hi's will be ambiguous.

Why the output is printing twice?

May be it look childish for most of you but I am unable to understand this small piece of code.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char** argv) {
int i, pid;
pid = fork();
printf("Forking the pid: %d\n",pid);
for(i =0; i<5; i++)
printf("%d %d\n", i,getpid());
if(pid)
wait(NULL);
return (0);
}
Out put of this program is
Forking the pid: 2223
0 2221
1 2221
2 2221
3 2221
4 2221
Forking the pid: 0
0 2223
1 2223
2 2223
3 2223
4 2223
Press [Enter] to close the terminal ...
In the for loop the printf command is used once. Why "Forking the pid" and after that the pid's are printed twice. How this is working? Can anybody explain me this? Thanks in advance.
Can anybody explain me why we have to use wait here? What I understood from the man pages is wait retuns the control to parent process? Is what I understood is correct?Is it necessary to use wait after forking a process?
Operating system : ubuntu, compiler : gcc, IDE : netbeans
But that' exactly what fork does. You forked the process and everything after the fork is done twice because now you have two processes executing the same printing code. You are basically asking why fork forks. fork forks because is is supposed to fork. That's what it's for.
After fork the parent and the child processes are generally executed in parallel, meaning that the nice sequential output you see in your example is not guaranteed. You might have easily ended up with line-interleaved output from two processes.
wait function in your case is executed from the parent process only. It makes it wait until the child process terminates, and only after that the parent process proceeds to terminate as well. Calling wait in this particular example is not really critical, since the program does nothing after that, it just terminates. But, for example, if you wanted to receive some feedback from the child process into the parent process and do some additional work on that feedback in the parent process, you'd have to use wait to wait for the child process to complete its execution.
The fork() call makes a new process. The rest of the code is then executed from each of the 2 processes. (Man page)
You're printing in both processes. Put your printing loop in an else clause of the if (pid):
pid = fork();
if(pid)
{
printf("Child pid: %d\n",pid);
wait(NULL);
}
else
{
for(i =0; i<5; i++)
printf("%d %d\n", i,getpid());
}
You see, fork returns twice, once in the parent process and once in the child process. It returns 0 in the child and the pid of the created process in the parent.
Because both the parent and child process are outputting their results.
See here: http://en.wikipedia.org/wiki/Fork_(operating_system)#Example_in_C for a good example.
fork creates a new process, and returns in both the old process (the parent) and in the new process (the child).
You can tell which one you are in by looking at the return value from fork. In the parent process it returns the PID of the child process. In the child process it return 0.

Resources