Why parent and son not mixed?

gdf

New Member
Joined
Mar 1, 2022
Messages
29
Reaction score
2
Credits
287
int main(){
4 pid_t pid = fork();
5 int i;
6 setbuf(stdout,NULL);
7 if(pid == 0){
8 for(i = 0;i < 10;i++){
9 printf("AA");
10 }
11 sleep(1);
12 exit(0);
13 }else{
14 for(i = 0;i < 10;i++){
15 printf("BB");
16 }
17 sleep(1);
18 }
19 return 0;
20 }
For this program,I just want to know why father process always first ,output like this:

BBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAroot@ubuntu:
 


The answer to your question, to the best of my knowledge, is that the programmer does not know whether the Operating System will first give control to the parent process or the child process after the fork() is called. One could imagine it is logical to output the parent before the child, and maybe the compiler does that as a default, but I don't know. I suppose you could try and compile it with clang and see if that has the same behaviour. Your code is not written in code tags and so the format is awry and the include files are missing, so here's a formatted version with some extras:
Code:
 1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 int main()
  5 {
  6   pid_t pid = fork();
  7   int i;
  8   setbuf(stdout,NULL);
  9     if(pid == 0)
 10       {
 11         for(i = 0;i < 10;i++)
 12           {
 13           printf("AA");
 14           }
 15        printf("child pid = %u\n\n",pid);
 16        sleep(1);
 17        exit(0);
 18       }
 19     else
 20
 21       {
 22          for(i = 0;i < 10;i++)
 23           {
 24            printf("BB");
 25           }
 26         printf("parent pid = %u\n\n", getpid());
 27         sleep(1);
 28       }
 29  return 0;
 30 }
And here is the output:

Code:
BBBBBBBBBBBBBBBBBBBBparent pid = 23840

AAAAAAAAAAAAAAAAAAAAchild pid = 0
 
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <stdlib.h>
4
5 int main(int argc,char * argv[]){
6 pid_t pid = fork();
7 int i;
8 int count = atoi(argv[1]);
9 if(argc != 2){
10 printf("usage:%s <loops>\n",argv[0]);
11 exit(0);
12 }
13 setbuf(stdout,NULL);
14 if(pid == 0){
15 for(i = 0;i < count;i++){
16 printf("AA");
17 usleep(500000);
18 }
19 exit(0);
20 }else{
21 for(i = 0;i < count;i++){
22 printf("BB");
23 usleep(500000);
24 }
25 }
26 return 0;
27 }

I've changed a lot,this is what I want:10 times could not show how it works!


./fork 100
BBAABBAABBAABBAABBAABBAABBAABBAABBAABBAABBAABBAABBAABBAABBAABBAABBAABBAABBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAABBAABBAABBAABBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBBBAAAABBAABBBBAAAABBBBAAAABBBBAA
 
In order to get the As to interleave with the Bs, I can see that changing the sleep times will go some way to achieve that. If the parent process starts to write the Bs, but then sleeps, the child process can continue to write As which will follow the Bs while the parent process sleeps, until the parent process wakes up to write the Bs again to follow the As. Here is an example of what I've just outlined using your first lot of code ... I've used newlines in the code for clarity in the output:
Code:
 1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 int main()
  5 {
  6   pid_t pid = fork();
  7   int i;
  8   setbuf(stdout,NULL);
  9     if(pid == 0)
 10       {
 11         for(i = 0;i < 10;i++)
 12           {
 13           printf("AA\n");
 14
 15           }
 16           printf("child pid = %u\n", pid);
 17
 18        sleep(1);
 19        exit(0);
 20       }
 21     else
 22   
 23       {
 24          printf("parent pid = %u\n", getpid());
 25          for(i = 0;i < 10;i++)
 26           {
 27            printf("BB\n");
 28           }
 29
 30         sleep(5);
 31       }
 32  return 0;
 33 }

And the output is:
Code:
parent pid = 3934
BB
BB
BB
BB
AABB

AABB

AABB

AABB

AABB

AABB

AA
AA
AA
AA
child pid = 0
 
You are using a fork in the code which creates a child process, which executes all the lines below the fork(), hence we have two processes submitted to the scheduler in total and the sequence of execution of these two processes(parent or child) is decided by the scheduler.
Since you are not using wait() in the parent, the sequence of execution of parent and child is unpredictable. And about interleaving of outputs "AA" and "BB" is because of race conditions which may or may not happen depending on preemption.
If you run your code by including necessary header files, you'll see that sometimes there is an interleaving of outputs (BBAABB....) and sometimes there isn't (and you get BB....AA....)
So, it isn't necessary that the parent(father) process is always executed prior to the child(son).
Actually, this is what is supposed to happen and I got these outputs when testing the code on VSCode.
But when you run your code in the terminal directly, the output is always the same i.e., without interleaving because there is no context switch. This happens due to the stdout buffer present in the VScode which does not allow the program to run directly on the terminal instead uses a pipe, and you get the output only when the buffer is fully flushed.

P.S: Try to run the same code more than once you'll get both the outputs
Code :
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(){
pid_t pid = fork();
int i;
setbuf(stdout,NULL);
if(pid == 0){
for(i = 0;i < 10;i++){
printf("AA");
}
sleep(1);
exit(0);
}
else{
for(i = 0;i < 10;i++){
printf("BB");
}
sleep(1);
}
return 0;
}
 
Last edited:

Members online


Latest posts

Top