0

I wrote this program

main()
{
    int pid;
    pid=fork();
    if(pid==0)
        printf("\nI am child\n");
    else
        printf("\nI am parent\n");

    return 0;
}

Whose output when executed is

 ./a.out 

I am parent

I am child

When I run with the strace program, the output is [Last part]

arch_prctl(ARCH_SET_FS, 0x7fd1bbf52700) = 0
mprotect(0x7fd1bbd47000, 16384, PROT_READ) = 0
mprotect(0x7fd1bbf70000, 4096, PROT_READ) = 0
munmap(0x7fd1bbf54000, 103886)          = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fd1bbf529d0) = 5109

I am child
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
--- SIGCHLD (Child exited) @ 0 (0) ---
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd1bbf6d000
write(1, "\n", 1
)                       = 1
write(1, "I am parent\n", 12I am parent
)           = 12
exit_group(13)                          = ?

The output shows that parent is run first, but the strace output seems to show that child runs first, since its printed first.

What is the rule?

jww
  • 97,681
  • 90
  • 411
  • 885
user567879
  • 5,139
  • 20
  • 71
  • 105
  • Possible duplicate of [Can the order of execution of fork() be determined?](https://stackoverflow.com/q/6696959/608639), [In fork() which will run first, parent or child?](https://stackoverflow.com/q/21586292/608639), [Is there a good way to alter execution order of child processes created with fork()?](https://stackoverflow.com/q/46523164/608639), [Using fork(), how can I make child process run always first?](https://stackoverflow.com/q/30276244/608639), [Forked processes order of execution](https://stackoverflow.com/q/39756509/608639), etc. – jww Oct 28 '19 at 21:47

2 Answers2

3

There is no rule. As soon as a process is ready for execution (i.e. the fork system call returns), it may run according to the scheduling configuration (priority, scheduler chosen, etc.). Depending on how the process is added to the scheduler, either process may be scheduled first after returning from fork. (And, as pointed out by @nos in a comment, both processes may run concurrently on a multi-CPU/multicore system).

Additionally, when using printf, keep in mind that the output flush may happen in a different order even if the processes are scheduled on a fixed rule. This is why the output differs between the no-strace and the strace runs.

nneonneo
  • 171,345
  • 36
  • 312
  • 383
0

in most cases the parent process

fork() is not a blocking system call, so unless the parent has used up its scheduling quantum, it will continue to run after the fork. The child process is placed on the ready list and will be run by the next available cpu, but the parent process will run as soon as the system call returns.

Here is the output produced by a small program that forks 10 child processes, run on a 2-core laptop:

PARENT child PARENT PARENT child PARENT PARENT child PARENT PARENT child PARENT PARENT child PARENT child child child child child
PARENT child PARENT child PARENT PARENT PARENT child PARENT PARENT child PARENT PARENT child PARENT child child child child child
PARENT child PARENT PARENT child PARENT PARENT child PARENT PARENT child PARENT PARENT child PARENT child child child child child
PARENT child PARENT PARENT child PARENT PARENT child PARENT PARENT child PARENT PARENT child PARENT child child child child child

main() {
    int i;
    for (i=0; i<10; i++) {
        if (fork()) {
            write(1, "PARENT ", 7);
        }
        else {
            write(1, "child ", 6);
            exit(0);
        }
    }
}

Edit: however, write is a blocking call. A better test records the child process pid's, and has the child fork as well. If the parent runs without a child running inbetween, it will allocate contiguous pid's. Here's a run of 20 forks in a row (line breaks show sequences):

7824 7825
7827 7828 7829
7831 7832 7833 7834 7835 7836
7838 7839 7840 7841 7842 7843 7844 7845
7847

main() {
    int i;
    int pid, pids[1000];
    for (i=0; i<20; i++) {
        if (pid = fork()) {
            //write(1, "PARENT\n", 7);
            pids[i] = pid;
        }
        else {
            fork();
            //write(1, "child\n", 6);
            exit(0);
        }
    }
    for (i=0; i<20; i++) printf("%d\n", pids[i]);
}
Andras
  • 2,995
  • 11
  • 17