Is there a reason for the child to not to print until the parent process finishes printing?
Asked Answered
C

2

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

int do_fork(int depth)
{
    if (!depth) {
        return fork();
    }

    int val = do_fork(depth - 1);

    printf("%d\n", val);

    return val;
}

int main()
{
    int val;
    scanf("%d", &val);
    do_fork(val);
}

I tried this code several times, with several different values on several different machines. It doesn't matter how big the number is, I always see the pid of the child printed one next to the other with no zeros in between. Only when the pids are all printed, the child starts printing zeros.

Here is an example with an input of a 1000.

Is there a reason for this phenomenon or is it just random?

Cadwell answered 4/9, 2020 at 21:53 Comment(0)
I
2

Is there a reason for this phenomenon or is it just random?

Neither C nor POSIX has any provisions that direct the particular output you observe, and likely you would see different results on some machines. In particular, different operating systems and operating system versions may differ with respect to whether parent or child first takes the CPU after a fork(). (Even on a multicore system, only one of them can immediately take the core on which fork() was executed.)

However, the two processes resulting from the fork do print using the same open file description in the kernel, and this means that they are actively prevented from writing to it at the same time. This is likely related to why you see long runs of the same output. One process obtains a lock, prints, releases the lock, and very soon after attempts to acquire the lock again. Under these circumstances there is a high probability that the same process reacquires the lock before the other can acquire it.

Additionally, it does take some time for a new process to actually get scheduled on a CPU. That probably explains the behavior I see for your program for inputs exceeding about 40, which is about 35 nonzero outputs, followed by fairly strict alternation between zero and nonzero, followed by all zeroes.

Of course, all of the above supposes that the two processes get scheduled concurrently at all. If you have only one core serving both then it naturally follows that each would produce long runs of its own output while it had the core. That could easily manifest as the two processes' outputs not being intermingled at all.

Indaba answered 4/9, 2020 at 22:21 Comment(0)
F
2

There's no guarantee who runs first. And granularity does matter. Try 5000, and you will see a mix of prints. Here's the result I've got:

enter image description here

Fewell answered 4/9, 2020 at 22:8 Comment(3)
Did you also add fflush() to flush the incomplete lines?Raptor
^ Without a newline in the output or an explicit flush, this variation on the program is not testing the same thing that the OP's does.Indaba
@Raptor I did fflush(). This run kept his code as is, with 5000 as inputFewell
I
2

Is there a reason for this phenomenon or is it just random?

Neither C nor POSIX has any provisions that direct the particular output you observe, and likely you would see different results on some machines. In particular, different operating systems and operating system versions may differ with respect to whether parent or child first takes the CPU after a fork(). (Even on a multicore system, only one of them can immediately take the core on which fork() was executed.)

However, the two processes resulting from the fork do print using the same open file description in the kernel, and this means that they are actively prevented from writing to it at the same time. This is likely related to why you see long runs of the same output. One process obtains a lock, prints, releases the lock, and very soon after attempts to acquire the lock again. Under these circumstances there is a high probability that the same process reacquires the lock before the other can acquire it.

Additionally, it does take some time for a new process to actually get scheduled on a CPU. That probably explains the behavior I see for your program for inputs exceeding about 40, which is about 35 nonzero outputs, followed by fairly strict alternation between zero and nonzero, followed by all zeroes.

Of course, all of the above supposes that the two processes get scheduled concurrently at all. If you have only one core serving both then it naturally follows that each would produce long runs of its own output while it had the core. That could easily manifest as the two processes' outputs not being intermingled at all.

Indaba answered 4/9, 2020 at 22:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.