27

I have read in books and online resources that the fork() system call creates a copy of current process and both the processes start executing from the point after the fork() system call is made. Is it correct?

If it is correct then why does the code below print "Test Test"? It should print "Test" just one time (by the parent process).

#include <sys/types.h> /* pid_t */
#include <sys/wait.h>  /* waitpid */
#include <stdio.h>     /* printf, perror */
#include <stdlib.h>    /* exit */
#include <unistd.h>    /* _exit, fork */


int main(void)
{
    int ctr =1;
    int pc = 1;
    printf("%s", "Test ");
    pid_t pidmain = fork();
    return EXIT_SUCCESS;
}
Akash Mahajan
  • 512
  • 4
  • 16

2 Answers2

37

When you call fork() the operating system creates a copy of the current processes entire memory (it doesn't actually copy the memory since it can use the MMU to do this efficiently).

Since stdout is buffered by default it will only print the message once a newline characters is written or the stream is flushed. When you fork a new process the current write buffer (containing "Test ") will also be duplicated in the new process. This will then be printed once the process exits since that implicitly closes (and flushes) stdout. If you replace the printf("%s", "Test "); with printf("%s\n", "Test "); or add a fflush(stdout); call before the fork() you will see the expected output.

ar31
  • 3,576
  • 1
  • 25
  • 22
  • 6
    or if the C library decides there's starting to be too much in the buffer... It would be wrong to depend on the output remaining in the buffer and being copied during the fork call. – Ben Voigt Feb 22 '15 at 04:27
18

At the point where you call fork, both processes have the string "Test " in their buffers for the standard output. When each process exits, they both flush this text to the output (see exit for explanation). You could (as suggested) add a newline to the buffer (and it would happen to come out because of the buffering -- see setbuf for explanation). Or you could call fflush(stdout) before the fork and get exactly what you asked for - the "Test " string.

ninjalj
  • 42,493
  • 9
  • 106
  • 148
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105