After reading on the web that i can't really determine which process runs before i.e child or parent
I planned to disable the ASLR on my PC and run debugger to see if i can generate the pattern of execution, the observations I made are below with a GitGist to the GDB disas (full) along with the source code
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
fork();
//fork();
printf("LINUX\n");
//printf("my pid is %d",(int) getpid());
fork();
printf("REDHAT\n");
//printf("my pid is %d",(int) getpid());
//fork();
return 0;
}
this is the code i am talking about when i disas it in gdb it gave me:-
gdb-peda$ disas main
Dump of assembler code for function main:
0x000000000000068a <+0>: push rbp
0x000000000000068b <+1>: mov rbp,rsp
0x000000000000068e <+4>: call 0x560 <fork@plt>
0x0000000000000693 <+9>: lea rdi,[rip+0xaa] # 0x744
0x000000000000069a <+16>: call 0x550 <puts@plt>
0x000000000000069f <+21>: call 0x560 <fork@plt>
0x00000000000006a4 <+26>: lea rdi,[rip+0x9f] # 0x74a
0x00000000000006ab <+33>: call 0x550 <puts@plt>
0x00000000000006b0 <+38>: mov eax,0x0
0x00000000000006b5 <+43>: pop rbp
0x00000000000006b6 <+44>: ret
End of assembler dump.
so basically it gives me a set pattern of the execution, so i think that should mean the program should execute always in a particular order i tried disas main about 3 times to see if the order actually ever changes and it does not but when i finally run the binary that's generated it gives me different outputs
root@localhost:~/os/fork analysis# ./forkagain
LINUX
REDHAT
LINUX
REDHAT
REDHAT
REDHAT
root@localhost:~/os/fork analysis# ./forkagain
LINUX
LINUX
REDHAT
REDHAT
REDHAT
REDHAT
which is inconsistent to the observation that i made in the disas, can someone please fill up the gaps in my understanding?
i tried disas main about 3 times to see if the order actually ever changes
The order is fixed at compile time, so it can never change without you recompiling the program.
In addition, the order is fixed by your program source -- the compiler is not allowed to re-order your output.
What you observe then is the indeterminism introduced by the OS as a result of calling fork
-- after the fork
there are no guarantees which process will run first, or for how long. The parent may run to completion, then the child. Or the child may run to completion first. Or they may both run with time-slicing, say one line at a time.
In addition, most non-ancient Linux systems today are running on multi-processor machines, and the two independent processes can run simultaneously after the fork.
An additional complication is that your program is not well-defined, because of stdio buffering. While you see 6 lines of output, it might be hard for you to explain this result:
./forkagain | wc -l
8
./forkagain > junk.out; cat junk.out
LINUX
REDHAT
LINUX
REDHAT
LINUX
REDHAT
LINUX
REDHAT
You should add fflush(stdout);
before fork
to avoid this complication.
P.S. You should also un-learn the bad habit of running as root -- sooner or later you'll make a stupid mistake (like typing rm -rf *
in the wrong directory), and will be really sorry you did it as root.