Need to know how fork works? - c

I am trying the following C code:
int main()
{
printf("text1\n");
fork();
printf("text2\n");
return 0;
}
I was expecting to get the output where i get two "text1" and two "text2", like:
text1
text1
text2
text2
But, i am, instead, getting:
text1
text2
text2
only one "text1"???
Ok, if child process executes from the fork(), then why do i get two "text1" for following:
int main()
{
printf("text1");
fork();
printf("text2\n");
return 0;
}
the output now is:
text1text2
text1text2
If the child process starts after the fork, output should be:
text1
text2
text2

fork() creates a new process by copying everything in the current process into the new process. That typically includes everything in memory and the current values of the CPU registers with some minor adjustments. So in effect, the new process gets a copy of the process's instruction pointer as well so it resumes at the same point where the original process would continue (the instruction following the fork()).
To address your update, printf() is buffered. Normally the buffer is flushed when it encounters a newline character at the end, '\n'. However since you have omitted this, the contents of the buffer stays and is not flushed. In the end, both processes (the original and the child) will have the output buffer with "text1" in it. When it eventually gets flushed, you'll see this in both processes.
In practice, you should always flush files and all buffers (that includes stdout) before forking to ensure that this does not happen.
printf("text1");
fflush(stdout);
fork();
The output should look like this (in some order):
text1text2
text2

The forked process gets a copy of the variable memory, and at the time of the fork the output buffer has yet to be flushed. No output has been written to the console when you fork, only buffered up. Both processes thus continues with text1 already in the buffer, and thus both print it.

fork clones the current process. The new process will "start" at the fork call, not at the start of main as you seem to expect. Thus when you print the first time there is 1 process, then when you fork there are two.
Since you are forking after printing "text1", it is only printed once.
In the second example the duplicated output is due to output buffering - printf doesn't actually output anything to the screen until it is flushed or it hits a newline ('\n').
Consequently the first call to printf actually just wrote data to a buffer somewhere, the data was then copied into the second process' address space, and then the second call to printf would have flushed the buffer, complete with "text1" in both buffers.

It is because forked process starts after fork, not from very beginning. exec starts process from entry point and will print what you expect.

The child process will start from the position of the fork(), so you are getting the correct output.

Problem 1 : the output as
text1
text2
text2
This is because fork() create exact copy (child) of parent process and both processes start their execution right after the system call fork().
Problem 2 : the output as
text1text2
text1text2
This is all about buffering. Refer this link and learn about fork() basics.
http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/create.html

from man 2 fork: fork returns 0 to the child process.
value = fork();
if( value == -1 ) {
printf( "fork failed\n" );
exit(1);
}
if( value ) {
printf( "test1\n" );
} else {
printf( "test2\n" };
}

Related

Why is main called twice?

I've just learnt about fork, and as I understand it the child process starts execution from the call to fork (otherwise fork would be recursive?).
However in this code (ideone link):
int main() {
printf("%d: Common code1\n", getpid());
if (fork() != 0) {
printf("%d: Parent code\n", getpid());
} else {
printf("%d: Child code\n", getpid());
}
printf("%d: Common code\n", getpid());
}
The output is:
27380: Common code1
27380: Parent code
27380: Common code
27380: Common code1
27383: Child code
27383: Common code
I don't understand why the 4th line is printed? I could understand if it was printed from the child process and fork called main but it's printed from the parent, and fork doesn't call main.
Good question! I was a little bit confused at first.
When you use printf, the output is buffered. That means that things printed by printf won't be actually flushed to the console until a newline is reached, or even until the program terminates if stdout is redirected.
In this case. the parent PID's stdout buffer is being copied to the child during the fork. Then, both the parent and child write to their buffers before terminating. This results in duplicated data being printed.
Here's an ideone link that includes fflush(stdout); before fork() is called.
The problem comes from buffering. When stdout is not associated with a terminal, it isn't line buffered. The strings you write are short enough to stay inside the buffer and are only written out once the program terminates. Thus, you first see process 27380 dumping its buffers and then process 27383 dumping its buffers. The line 27380: Common code1 hasn't been flushed out before the fork, so it's in the buffer of both the original and the forked process. Call fflush() right before forking to fix this problem.
Buffering. Printf does not (usually) write anything to stdout. It merely updates some internal data structures. Those data structures are duplicated in the child, and when the stream is flushed the data is written. You should flush(stdout) before you fork.

Forking a process with C

I'm following this guide about fork() but something isn't clear for me.
Both processes will start their execution at the next statement following the fork() call. In this case, both processes will start their execution at the assignment statement as shown below:
According to this sentence, this script
printf("before ");
fork();
printf("after ");
should print this: (Because child process will start from printf("after"))
before after after
but it is printing this instead:
before after before after
So did the child process start from the 1st line of the file? Can you tell me what's wrong with my code? Did I misunderstood that sentence?
EDIT
Script compiled and executed on OS X
When you create a new process, it 'inherits' all the variables of the original process - thus all the buffers as well. Since "before" wasn't flushed yet and is still in the buffer, the child process will as well contain this string in the buffer and print it. Therefore you have to call fflush(stdout); before forking the process.
You understood the sentence correctly, but...
When you call fork it takes a snapshot of the process, and creates an exact duplicate. So if there is data buffered in stdout waiting to be written to the console, then that data will be in the child's output buffer after the fork, as well as the parent's buffer.
There are two ways to clear the output buffer before the fork. You can either add a newline \n at the end of the printf
printf( "before\n" );
fork();
printf( "after\n" );
or you can use the fflush function
printf( "before " );
fflush( stdout );
fork();
printf( "after " );
It is because the "before" is buffered and only outputted when that buffer is flushed. This occurs in when the two processes terminates.
If you call fflush on stdout prior to fork, you will see the output you expect. In general, C buffered IO won't play nicely when you do operations at the OS level.
The memory buffer associated with the standard output is cloned on fork including any previously buffered output. That's why you see the "before" twice.

Forking a process- execution before the system call (execution point)

"When we call fork() on a process and its child is created, it is said that the point of execution starts from the point next to the fork() call in both the processes. But when I checked,
main() {
printf("hello");
val =fork();
if(val==0){
printf("child");
}
if(val>0){
printf("parent");
}
}
This program printed hello also twice. I am a little confused. Please help me out.
When you do printf("hello");, the output is line buffered for STDOUT which is not flushed. Now when the buffer still containing data, fork() call makes both parent and child process inherit data present in the buffer making it print twice.
Ideally you should be flushing the standard output as below:
printf("hello");
fflush(stdout);
fork();

fork() and write commands

#include<stdio.h>
int main()
{
if (fork())
{
wait();
printf("Now I am showing you ls -l"); // why can't we see this ?
execlp("ls","ls", "-l", 0); //gets printed second
}
else
{
printf("We are in the child process."); // gets printed first
}
}
I have this simple peace of code. My question is why don't we see on the console the first print, in the parent process?
The printf function provides buffered IO. When printing to stdout, as you are here, the buffer will normally get flushed when you print a newline \n, which you have not done, so your string is sitting in a buffer waiting to be printed.
The next thing you are doing is calling execlp. The exec family of functions replace the current process with the new one you have specified. The buffer is lost without ever being flushed, because the whole process is replaced.
If you add \n to the strings you are printing, you will probably see the output.
you have to flush stdout before the execlp.
if you put a \n at the end of the printf (or you call fflush(stdout)) you will get the correct result
In the interactive case, standard output is line buffered by default. And that execlp() will replace its memory image, therefore that output line may be dropped before it is written to console.
Change that print() statement to
printf("Now I am showing you ls -l\n");
to fix this problem.
There is 2 problems with your code:
first you need to flush your outputs, either by adding \n in the strings or by calling fflush(stdout)
But it should be the job of the son to exec(), of course you can always exec in the parent, but this is probably not what you want.
A more common fork/exec sample looks like :
int main() {
if (fork()) { // parent
wait(NULL); // wait his child
printf("Ok, my children finished the job\n");
exit(0);
}
else { // child
printf("We are in the child process.\n"); // gets printed first
printf("Now I am showing you ls -l\n");
execlp("ls","ls", "-l", 0); // never return from this
}
}

Need to know how fork works [duplicate]

I am trying the following C code:
int main()
{
printf("text1\n");
fork();
printf("text2\n");
return 0;
}
I was expecting to get the output where i get two "text1" and two "text2", like:
text1
text1
text2
text2
But, i am, instead, getting:
text1
text2
text2
only one "text1"???
Ok, if child process executes from the fork(), then why do i get two "text1" for following:
int main()
{
printf("text1");
fork();
printf("text2\n");
return 0;
}
the output now is:
text1text2
text1text2
If the child process starts after the fork, output should be:
text1
text2
text2
fork() creates a new process by copying everything in the current process into the new process. That typically includes everything in memory and the current values of the CPU registers with some minor adjustments. So in effect, the new process gets a copy of the process's instruction pointer as well so it resumes at the same point where the original process would continue (the instruction following the fork()).
To address your update, printf() is buffered. Normally the buffer is flushed when it encounters a newline character at the end, '\n'. However since you have omitted this, the contents of the buffer stays and is not flushed. In the end, both processes (the original and the child) will have the output buffer with "text1" in it. When it eventually gets flushed, you'll see this in both processes.
In practice, you should always flush files and all buffers (that includes stdout) before forking to ensure that this does not happen.
printf("text1");
fflush(stdout);
fork();
The output should look like this (in some order):
text1text2
text2
The forked process gets a copy of the variable memory, and at the time of the fork the output buffer has yet to be flushed. No output has been written to the console when you fork, only buffered up. Both processes thus continues with text1 already in the buffer, and thus both print it.
fork clones the current process. The new process will "start" at the fork call, not at the start of main as you seem to expect. Thus when you print the first time there is 1 process, then when you fork there are two.
Since you are forking after printing "text1", it is only printed once.
In the second example the duplicated output is due to output buffering - printf doesn't actually output anything to the screen until it is flushed or it hits a newline ('\n').
Consequently the first call to printf actually just wrote data to a buffer somewhere, the data was then copied into the second process' address space, and then the second call to printf would have flushed the buffer, complete with "text1" in both buffers.
It is because forked process starts after fork, not from very beginning. exec starts process from entry point and will print what you expect.
The child process will start from the position of the fork(), so you are getting the correct output.
Problem 1 : the output as
text1
text2
text2
This is because fork() create exact copy (child) of parent process and both processes start their execution right after the system call fork().
Problem 2 : the output as
text1text2
text1text2
This is all about buffering. Refer this link and learn about fork() basics.
http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/create.html
from man 2 fork: fork returns 0 to the child process.
value = fork();
if( value == -1 ) {
printf( "fork failed\n" );
exit(1);
}
if( value ) {
printf( "test1\n" );
} else {
printf( "test2\n" };
}

Resources