#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
void main()
{
int i = 1;
pid_t child_pid;
printf("The main program process ID is %d", (int) getpid());
printf("%d", i);
child_pid = fork();
if (child_pid != 0) {
i++;
printf("%d", i);
printf("This is the parent process, with ID %d \n", (int) getpid());
printf("The child process is %d ", (int) child_pid);
} else {
printf("%d", i);
printf("This is the child process, with ID %d \n", (int) getpid());
}
}
I'm running this program using the C language, using the fork() function. As I understand it, when a process calls fork(), a duplicate process, called a child process, is created.
The parent process continues executing from the point that fork() was called, and the child process, too, executes the same program from the same place.
So when I run my program, I expect the output be like the following text:
The main program process ID is 181411This is the child process, with ID 1815
The main program process ID is 18142This is the parent process,with ID 1814
The child process is 1815
But I actually see this output:
The main program process ID is 181411This is the child process, with ID 1815
The main program process ID is 181412This is the parent process,with ID 1814
The child process is 1815
It means that the child executes the program first!!!
When I put \n at the end of each printf statement the output is correct!!!
I've tried it on the Fedora v12 and rhel 5 distributions.
Is there any logical relation between the \n and the fork() operation? How I can solve this problem?
The problem is that output is line-buffered and it isn't really flushed to your screen until you either output \n or explicitly call fflush on stdout. (That said, there's no guarantee about which process is going to be faster at outputting stuff).
stdoutcommonly is line buffered. So the text to be printed is flushed to the console when receiving a '\n'.
Which process writes first is nondeterministicly handled by the OS.
To have things printed out without the need to have it triggered by '\n' using strerr is an option, as it normally is unbuffered.
My experience is that using stderr as fprintf(stderr,......) always appears to write unbuffered output. I was able to print the contents of a line before a segment error stopped execution. Try it again with stderr.
You can use:
setbuf(stdout, NULL)
to set the unbuffered output in stdout stream.
Related
I am trying to learn the fork() and wait() system calls. If I run this code :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main (){
printf("Hi, I am the parent with pid %d \n ",getpid());
int rc = fork();
printf("Fork returned : %d \n ",rc);
printf("I am the process with pid %d \n ",getpid());
wait(NULL);
return 0;
}
I get the output as expected on the terminal :
Hi, I am the parent with pid 3639
Fork returned : 3640
I am the process with pid 3639
Fork returned : 0
I am the process with pid 3640
However , If I remove wait(NULL) , I get a strange output on the terminal :
Hi, I am the parent with pid 3715
Fork returned : 3716
I am the process with pid 3715
John#John-VirtualBox:~/Fork5$ Fork returned : 0
I am the process with pid 3716
I totally understand that , we use wait() to make the parent process waits for the child to end executiion so that we can remove it from the process table and deallocate its PID . But here , if I remove the wait , we see that the terminal is called again :
John#John-VirtualBox:~/Fork5$ Fork returned : 0
I am the process with pid 3716
And even it doesn't return again back . I don't understand what this have to do with the functionality of wait ? Or in other words , why wait will fix this issue ?
The sequence of events appears to be:
The shell is the parent process to your program. When it forks your program your program inherits the standard streams (to the terminal).
Your program forks a child process which also inherits the standard streams (to the terminal).
When your parent process terminates, the shell notices (because it is waiting) and issues a prompt to the terminal.
However, your program’s child has not yet terminated, so after the shell issues its prompt the child prints its output (and then terminates).
You will notice that the shell does not issue a second prompt after the child terminates. (The shell does not know anything about your child process.)
Order of output
The fact that you get complete output lines (instead of anything interleaved) is because the standard streams for all processes are in line oriented mode.
However, there is no guarantee of order between processes. The OS scheduler can order them any way it wants. Your child could have printed before the parent.
:O)
I have been learning about fork in c and i have this program:
int main(void) {
int i;
printf("Start program\n");
printf("This is parent process %d: %d\n", getpid(), i);
int pid = fork();
printf("%d ", pid);
if(pid == 0) {
printf("This is process %d: %d\n", getpid(), i);
}
return 0;
}
This is the output:
Start program
This is parent process 4467: 0
4578 Start program
This is parent process 4467: 0
0 This is process 4578: 0
I do not understand why the parent code is called twice.
stdout is buffered. See e.g. setvbuf(3).
You forgot to call fflush(3) before doing your fork(2). As a rule of thumb, you'll better do fflush(NULL) before any fork().
That could explain the observed behavior (because flushing happens later in both parent and child processes, e.g. at program exit or return from main in crt0). You might (on Linux) use strace(1) to understand more exactly what is happenning.
BTW, fork(2) could fail. You should handle that (that is, handle the pid == -1 (or pid<0) case...).
"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();
I have a small program written in C on linux. It's purpose is to examine the behaviour of the fork() call and the resulting child processes
Upon first inspection everything seems simple enough. However
Sometimes output is written in a funny order
Sometimes the child PPID is '1' not whatever the parent PID is.
I can't find any pattern or correlation between when it works as expected and when it does not.
I think that point 2. is probably caused by the parent process dying before the child process has executed fully. If so, is there a way to stop this from happening.
However I have no idea what is causing point 1.
Code below:
#include <stdio.h>
#include <unistd.h>
int main()
{
int x = fork();
if (x == 0)
{
printf("Child:");
printf ("\nChild PID : %d", getpid());
printf ("\nChild PPID: %d", getppid());
printf("\nHello Child World\n");
}
if (x != 0)
{
printf("Parent :");
printf ("\nParent PID : %d", getpid());
printf ("\nParent PPID: %d", getppid());
printf("\nHello Parent World\n");
}
return 0;
}
this behaviour is seen because of scheduling policy of operating system. if you are aware of process management concepts of os, then if your parent code is running and fork() is encountered, child is created, but if within that time, parent's time slice has not been completed, then parent continues running and if within its time slice, parent executes and terminates, then child becomes orphan precess and after parent process' time slice completes, child's execution starts, thats why getppid() function returns 1, because child is an orphan process and it it now adopted by init process which starts first when operating system boots and is having process id 1.
Explanation of Behaviour 1:
The order of output cannot be controlled by the program normally. That's the point of parallel process. The OS decides which process to execute at any point of time and both processes are executed simultaneously (to the human eye).
Thus the output would generally be inter-tweened.
Explanation of Behaviour 2:
You guessed that right.
The parent process has finished before the forked one.
If you want the parent pid, you can use waitpid(x, &status, 0) in the parent process if you need the parent to stay alive till child execution. This link may help you.
System information: I am running 64bit Ubuntu 10.10 on a 2 month old laptop.
Hi everyone, I've got a question about the fork() function in C. From the resources I'm using (Stevens/Rago, YoLinux, and Opengroup) it is my understanding that when you fork a process, both the parent and child continue execution from the next command. Since fork() returns 0 to the child, and the process id of the child to the parent, you can diverge their behavior with two if statements, one if(pid = 0) for the child and if(pid > 0), assuming you forked with pid = fork().
Now, I am having the weirdest thing occur. At the beginning of my main function, I am printing to stdout a couple of command line arguments that have been assigned to variables. This is this first non assignment statement in the entire program, yet, it would seem that sometimes when I call fork later in the program, this print statement is executed.
The goal of my program is to create a "process tree" with each process having two children, down to a depth of 3, thus creating 14 total children of the initial executable. Each process prints its parent's process ID and its process ID before and after the fork.
My code is as follows and is properly commented, command line arguments should be "ofile 3 2 -p" (i haven't gotten to implementing -p/-c flags yet":
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[])
{
if(argc != 5)//checks for correct amount of arguments
{
return 0;
}
FILE * ofile;//file to write to
pid_t pid = 1;//holds child process id
int depth = atoi(argv[2]);//depth of the process tree
int arity = atoi(argv[3]);//number of children each process should have
printf("%d%d", depth, arity);
ofile = fopen(argv[1], "w+");//opens specified file for writing
int a = 0;//counter for arity
int d = 0;//counter for depth
while(a < arity && d < depth)//makes sure depth and arity are within limits, if the children reach too high(low?) of a depth, loop fails to execute
//and if the process has forked arity times, then the loop fails to execute
{
fprintf(ofile, "before fork: parent's pid: %d, current pid: %d\n", getppid(), getpid());//prints parent and self id to buffer
pid = fork(); //forks program
if(pid == 0)//executes for child
{
fprintf(ofile, "after fork (child):parent's pid: %d, current pid: %d\n", getppid(), getpid());//prints parent's id and self id to buffer
a=-1;//resets arity to 0 (after current iteration of loop is finished), so new process makes correct number of children
d++;//increases depth counter for child and all of its children
}
if(pid > 0)//executes for parent process
{
waitpid(pid, NULL, 0);//waits on child to execute to print status
fprintf(ofile, "after fork (parent):parent's pid: %d, current pid: %d\n", getppid(), getpid());//prints parent's id and self id to buffer
}
a++;//increments arity counter
}
fclose(ofile);
}
When I run "gcc main.c -o ptree" then "ptree ofile 3 2 -p", the console is spammed with "32" a few times, and the file "ofile" is of seemingly proper format, but a bit too large for what I think my program should be doing, showing 34 child processes, when there should be 2^3+2^2+2^1=14. I think this is somehow related to the statement that is printing "32", as that would seem to possibly spawn more forks than intended.
Any help would be greatly appreciated.
When you call printf, the data is stored in a buffer internally. When you fork, that buffer is inherited by the child. At some point, (when you call printf again, or when you close the file), the buffer is flushed and data is written to the underlying file descriptor. To prevent the data in the buffer from being inherited by the child, you can flush the FILE * before you call fork, via fflush.