Reputation: 33
I'm trying to learn UNIX programming and came across a question regarding fork()
and I couldn't interpret the output of the 2 programs below.
I understand that fork()
creates an identical process of the currently running process, but where does it start? For example, if I have these two programs below, what will be the output and how does it work ?
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main (int argc, char **argv)
{
int retval;
printf ("This is most definitely the parent process\n");
// now here fork will create a child process
// i need to know from which line child process starts execution
retval = fork ();
printf ("Which process printed this?\n");
return (0);
}
What will be the difference in above program and the one below with respect to child process execution:
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main (int argc, char **argv)
{
int retval;
printf ("This is most definitely the parent process\n");
fflush (stdout);
// how does fflush change the output of above program and why ?
// even though no string operations are being used
retval = fork ();
printf ("Which process printed this?\n");
return (0);
}
I think both of them should print :
This is most definitely the parent process
Which process printed this?
Which process printed this?
But the first one is printing:
This is most definitely the parent process
Which process printed this?
This is most definitely the parent process
Which process printed this?
Upvotes: 3
Views: 2033
Reputation: 16540
when calling fork()
there are three possible return conditions.
Do read the man page for fork()
the three return conditions are
-1 -- the fork() failed
0 -- the child is executing
some positive number -- the pid of the child, the parent is executing
The code needs to be something like this:
pid_t pid;
pid = fork();
if ( 0 > pid )
{ // then handle error
}
else if ( 0 == pid )
{ // then child executing
}
else // if ( 0 < pid )
{ // then parent executing
}
Upvotes: 0
Reputation: 21213
I understand that fork() creates an identical process of the currently running process, but where does it start?
If fork(2)
is successful (i.e. does not return -1
), it starts in the line that calls fork(2)
. fork(2)
returns twice: it returns 0 in the child, and a positive number C
in the parent, where C
is the process ID of the newborn child.
The reason you're seeing This is most definitely the parent process twice is related to stdio's buffering. Stdio buffers output in userspace buffers that are flushed only when some condition occurs (for example, the buffer becomes full). The buffering mode dictates when and how buffers are flushed.
Usually, if output is being written to an interactive device such as a terminal (or pseudoterminal), stdio is line-buffered, which means that the buffers are flushed when a newline is found or fflush(3)
is called.
OTOH, if output is redirected to a file or other non-interactive devices (for example, output is redirected to a pipe), stdio is fully-buffered, which means that buffers are flushed only when they become full or fflush(3)
is called.
So, without fflush(3)
, executing the code in a terminal device will print this:
This is most definitely the parent process
Which process printed this?
Which process printed this?
Which is expected. However, if you pipe it through cat(1)
, you will see this (or some other variant, depends on execution order):
This is most definitely the parent process
Which process printed this?
This is most definitely the parent process
Which process printed this?
This is because output is fully buffered when redirected to a pipe. The string This is most definitely the parent process
isn't enough to fill and flush the buffer, so when the parent forks, the child (which gets a copy of the parent's memory space) will get a copy of the output buffer, which already contains the string This is most definitely the parent process
. So both processes end up printing that string.
If you always call fflush(3)
before forking, this won't happen because the buffer is empty when the parent's memory space is copied to the child.
Upvotes: 6
Reputation: 19625
Execution will continue at (or just after) the fork call. You can use the return value to check if you're the parent or the child process:
RETURN VALUE
On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately.
(Source: man fork
)
For example, if you have the following program:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char **argv) {
printf("Foo.\n");
int retval = fork();
printf("Bar from %s (%d).\n", (retval == 0) ? "child" : "parent", retval);
return 0;
}
The output would be something like:
Foo.
Bar from parent (18464).
Bar from child (0).
...assuming output is line buffered.
Upvotes: 0