I have this basic code about parent/child relation:
#define _DEFAULT_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/types.h>
int main(){
int sum = 6;
int *p = (int*) mmap(NULL, sizeof (int) , PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
*p = 7;
printf("filled %d in memory\n", *p);
int pID = fork();
if (pID == 0){
printf(" found %d\n", *p);
printf(" sum inside %d\n",sum (*p));
exit(0);
}
else if (pID> 0){
wait(NULL);
printf("sum %d\n",sum *p);
printf("exit\n");
exit(0);
}
return 0;
}
when i compile it in terminal it gives me this result:
filled 7 in memory
found 7
sum inside 13
sum 13
exit
but when i want to keep that output in a .txt file with ./a.out > output.txt
command, my code seems to run filling block twice and my output.txt file is filled by this:
filled 7 in memory
found 7
sum inside 13
filled 7 in memory //**printed twice
sum 13
exit
How can I solve it?
CodePudding user response:
This has nothing to do with mmap
, it's purely about your use of fork
.
fork
doesn't flush your buffers for you, so if you fork with unflushed data in your output buffers, the child will contain the same data and will eventually flush it. An easy solution in this case is to just manually flush
stdout
just before the fork
:
// ...
printf("filled %d in memory\n", *p);
fflush(stdout); // To flush all output streams in more complicated cases: fflush(NULL)
int pID = fork();
// ...
The reason you only saw it when writing to a file is that, when stdout
is connected to a terminal (on most systems) it's line-buffered, and the newline in your printf
ensured it flushed. When it's not connected to a terminal, it's typically block buffered (so the data was still in the buffer when the fork
occurred).