Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int pid = fork();
for(int i=0;i<5;i++)
{
if(pid == 0)
{
fork();
printf("fork\n");
}
}
return 0;
}
I think it should generate a total number of 6 child processes. But it is not so. Why
Explanation
fork() creates a duplicate process that continues to run the code from whereever it was called in parallel with the parent. In parent fork() returns child PID, and in child it returns zero - other than that new processes are identical but are copies of each other - setting a variable in one does not affect the other.
Normally after fork() you check its return to see if this copy of your program is a child or a parent and act accordingly.
Corrected code
So, if you were aiming to create 6 child processes (plus one parent) you should have done something like this:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
printf("Hello from parent, my PID is %d\n", getpid());
for(int i=0;i<6;i++)
{
int pid = fork();
if (pid == 0)
{
printf("Hello from child, my PID is %d\n", getpid());
return 0;
}
printf("Parent created child with PID=%d\n", pid);
}
return 0;
}
and the output on my system is:
Hello from parent, my PID is 26354
Parent created child with PID=26355
Hello from child, my PID is 26355
Parent created child with PID=26356
Parent created child with PID=26357
Parent created child with PID=26358
Hello from child, my PID is 26356
Parent created child with PID=26359
Parent created child with PID=26360
Hello from child, my PID is 26357
Hello from child, my PID is 26358
Hello from child, my PID is 26359
Hello from child, my PID is 26360
Notice that each child prints out Hello from child... message and then exits immediately by returning from main().
Mistakes
Your code does that check wrong so spawned children don't just exit - they continue creating more children of their own, and their children proceed to do the same.
You should have assigned pid = fork() each time, not just the first time.
If your child is done, it's recommended to let it quit right away by calling return rather then letting it continue to loop through your program and wrapping parts of it in if (pid==0) checks - this may lead to further mistakes
Your parent creates the first child (before the loop) and receives non-zero pid so it still goes through subsequent loop but does nothing else - the first child does all the work.
Furthermore, fork\n is printed twice each time fork() is called because both a parent and a child do it right after each (except the "before-the-loop" first) child is created - probably not what you intended.
Code analysis
Let's see what the code does.
I'll number the processes arbitrarily, process #0 is the original parent.
int pid = fork();
Process #0 creates process #1. In child (#1) pid = 0, in parent (#0) it is non-zero.
Because following code checks that pid is 0:
if(pid == 0)
{
fork();
printf("fork\n");
}
... process #0 loops 5 times but does nothing, prints out nothing and eventually exits.
Because pid is not written to anymore and is not checked, for process #1 and all subsequent processes this loop looks like this:
for(int i=0;i<5;i++)
{
fork();
printf("fork\n");
}
return 0;
Following happens in parallel, ordering is arbitrary:
Now process#1 creates five children - #2, #3, #4, #5, #6, printing out fork\n each time, and eventually exits.
Process#2 starts where process #1 left off creating it, with i=0, right before printf so it prints out fork\n and proceeds to print out the message 4 more times and create 4 more children of its own (#7, #8, #9, #10) and eventually exits
Process#3 starts where process #1 left off creating it, with i=1, right before printf so it prints out fork\n and proceeds to create 3 more children of its own, printing out the message 3 more times (#11, #12, #13) and eventually exits
Process#4 creates 2 processes (#14, #15), prints 3 messages
Process#5 creates 1 process (#16), prints 2 messages
Process#6 is left off with i=4 so it prints out a message and exits.
Process#7 (that was created by a second child) is left off in the same situation as process #3 so it prints the message 4 times and creates 3 more children of its own...
... at this point I'll probably stop, you should already see where this is going.
This is the output of your program after I added some logging to it. I also sorted output a little bit - because it all happens in parallel it is hard to keep track otherwise:
Process 27939 is the original parent
Process 27939 created process 27940 <--- this is the 'out-of-loop' child
Process 27939 finished executing
Process 27940 created process 27942
Process 27940: fork
Process 27940 created process 27943
Process 27940: fork
Process 27940 created process 27944
Process 27940: fork
Process 27940 created process 27945
Process 27940: fork
Process 27940 created process 27946
Process 27940: fork
Process 27940 finished executing
Process 27942: fork
Process 27942 created process 27954
Process 27942: fork
Process 27942 created process 27955
Process 27942: fork
Process 27942 created process 27956
Process 27942: fork
Process 27942 created process 27957
Process 27942: fork
Process 27942 finished executing
Process 27943: fork
Process 27943 created process 27958
Process 27943: fork
Process 27943 created process 27959
Process 27943: fork
Process 27943 created process 27960
Process 27943: fork
Process 27943 finished executing
Process 27944: fork
Process 27944 created process 27961
Process 27944: fork
Process 27944 created process 27962
Process 27944: fork
Process 27944 finished executing
Process 27945: fork
Process 27945 created process 27963
Process 27945: fork
Process 27945 finished executing
Process 27946: fork
Process 27946 finished executing
Process 27954: fork
Process 27954 created process 27970
Process 27954: fork
Process 27954 created process 27971
Process 27954: fork
Process 27954 created process 27972
Process 27954: fork
Process 27954 finished executing
Process 27955: fork
Process 27955 created process 27978
Process 27955: fork
Process 27955 created process 27979
Process 27955: fork
Process 27955 finished executing
Process 27956: fork
Process 27956 created process 27981
Process 27956: fork
Process 27956 finished executing
Process 27957: fork
Process 27957 finished executing
Process 27958: fork
Process 27958 created process 27980
Process 27958: fork
Process 27958 created process 27982
Process 27958: fork
Process 27958 finished executing
Process 27959: fork
Process 27959 created process 27983
Process 27959: fork
Process 27959 finished executing
Process 27960: fork
Process 27960 finished executing
Process 27961: fork
Process 27961 created process 27984
Process 27961: fork
Process 27961 finished executing
Process 27962: fork
Process 27962 finished executing
Process 27963: fork
Process 27963 finished executing
Process 27970: fork
Process 27970 created process 28002
Process 27970: fork
Process 27970 created process 28003
Process 27970: fork
Process 27970 finished executing
Process 27971: fork
Process 27971 created process 28004
Process 27971: fork
Process 27971 finished executing
Process 27972: fork
Process 27972 finished executing
Process 27978: fork
Process 27978 created process 28006
Process 27978: fork
Process 27978 finished executing
Process 27979: fork
Process 27979 finished executing
Process 27980: fork
Process 27980 created process 28008
Process 27980: fork
Process 27980 finished executing
Process 27981: fork
Process 27981 finished executing
Process 27982: fork
Process 27982 finished executing
Process 27983: fork
Process 27983 finished executing
Process 27984: fork
Process 27984 finished executing
Process 28002: fork
Process 28002 created process 28043
Process 28002: fork
Process 28002 finished executing
Process 28003: fork
Process 28003 finished executing
Process 28004: fork
Process 28004 finished executing
Process 28006: fork
Process 28006 finished executing
Process 28008: fork
Process 28008 finished executing
Process 28043: fork
Process 28043 finished executing
Related
Excluding the initial parent process, how many processes will be created by the following piece of code:
fork();
wait(0);
fork();
wait(0);
fork();
I was thinking of 7 processes because the father always waits for the child to end, but the child never exits. So it would be a 2**n - 1.
Every call to a fork function will create a new process. Every process (including the parent) will execute the code following its fork call. Every parent will wait for its child to die (remember that when a child calls fork, it also becomes a parent).
Draw a schema to be sure:
This gives as 7 processes, excluding the parent process.
Read the tree from its rightmost branch, and then maybe the following comments make sense:
fork(); // Process 'c0' was created
wait(0); // Parent process 'p' waits for its child 'c0' to change state.
fork(); // c1, c4
wait(0); // c0, p
fork(); // c2, c3, c5, c6
The Online Demo I created with printing statements and processes' IDs confirms that.
Reminder of the 0 argument in wait():
wait for any child process whose process group ID is equal to that of the calling process.
Read more in C - meaning of wait(NULL) when executing fork() in parallel.
Notice that the number of processes won't change if you comment out the wait calls.
char array[ARRAY_SIZE];
void child_process_routine(){
int j;
for(j = 0;j<ARRAY_SIZE;j++)
array[j]='d';
}
main()
{
pid_t child_pid;
int i;
for(i = 0;i<ARRAY_SIZE;i++)
array[i]='c';
child_pid = fork();
switch (child_pid) {
case -1:
perror("error");
exit(1);
case 0:
child_process_routine();
exit(0);
default:
wait(NULL);
}
print_array(array);
}
can you explain me why the parent process does not wait for the child process and this gives me the output " cccccc " again? it was changed in the child process into " dddddd "
what does wait(NULL) even do?
how does it supposed to know it should wait for the child process?
The parent process is waiting for the child process.
The child is not a thread, it is a completely different process with its own unique PID and the parent as its Parent PID. The child and the parent do not share the same array, the child has its own copy since it is a different process (not a thread of the same process). So when you set the array to 'd' in the child it does not affect the array in the parent process.
Try putting a sleep(20) in the child process flow right before it exits, and a printf() just before the parent wait(). You will see that your application pauses as the parent is waiting for the child to finish.
fork() creates a different process but parent share the same process context.
but if you try to change anything in the stack segment of parent it makes a copy of that and creates a separate stack for child process, but all the resources like data segment, code segment, etc are not copied for child process. They both share it.
This copying on changing the data after fork is called "copy on write"
Parent process is waiting for child process to finish. But its printig for both parent and child separately and different data for both
So, what I am trying to do is create a child process, have it execute execl and run ls. Then after ls is done, create another child process and have it run a cat command on a file. The second wait(pid) does not seem to wait for the second child process to complete before finishing. here is my code and output
#include <fcntl.h>
int main(){
int pid;
printf("In parent process, creating child now...\n");
pid = fork();
if (pid==0){
printf("Now in child process...\n");
execl("/bin/ls","ls","-l",(char*)0);
}
wait(pid);
printf("ls child process complete\n");
printf("in parent process\n");
printf("Creating another child process\n");
pid=fork();
if(pid==0){
execl("/bin/cat","cat","f1",(char*)0);
}
wait(pid);
return 0;
}
Here is my output
In parent process, creating child now...
Now in child process...
"Contents of ls"
ls child process complete
in parent process
creating another child process
[username#host ~]$ "Contents of file" *cursor*
the parent process seems to finish before the second child is complete. There is only 1 child existing at a time. The "Contents of file" are supposed to appear before the [username#host ~]$ prompt. I think i am misplacing a wait or wrong pid assignment or something. Thanks in advance!
The argument to wait() is not a PID. It's a pointer to an int where the exit status will be stored. You're passing an integer where a pointer is needed, which means:
The program might crash or corrupt some unrelated memory location as soon as you call wait. Its behavior after that point is unpredictable.
You need to enable more compiler warnings and pay attention to them.
Although the Cat process may have finished the disk cache may still be holding the results... Instead of waiting for cat to complete wait until the lock on the file is released.
In the below code, if there is a problem creating a child process or something happens to the child process what happens to wait(&status)?
pid_t pid;
int status;
if(pid=fork()){
printf("Parent Process\n");
wait(&status);
} else... child process here
If there is a problem creating a child process, fork will return -1, so this code will never wait.
If there's something happend to the child process, wait will return, and you can observe status.
If the child cannot be created, fork() will return with -1, you should look at errno after that. No error process is created here. Your code does not check this case.
If the child is created and dies, wait() will return the PID of the terminated process, the reason for the child's death is given in status. See the man page for wait on how to extract meaning from status.
#include <stdio.h>
int main(void)
{
fork();
fork();
printf("ppid %d pid %d\n", getppid(), getpid());
return 0;
}
The above code sometimes prints
$ ./a.out
ppid 3389 pid 3883
ppid 3883 pid 3885
ppid 1 pid 3884
ppid 3884 pid 3886
Why is process 3884's ppid 1? Doesn't it supposed to be 3883?
I'd guess the parent process had already completed running and exited by the time the third child checked for the parent's PID. That would have caused the child to be re-parented under init, which has process ID 1.
Taken from:
http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=%2Fapis%2Fgetppid.htm
"The value returned by getppid() is the process ID of the parent process for the calling process. A process ID value of 1 indicates that there is no parent process associated with the calling process."
That printf instruction was executed within the parent process, so it returned 1 because it does not have a parent process. It's perfectly normal that this was the 3rd line to be printed, since the fork run its process concurrently and no particular order is guarantied.
To build upon Jamey's answer, when a process finishes before the child's execution and exits, the child becomes an orphan i.e. orphan process so the kernel maps that orphan to the init process.
Using wait() makes sure that the parent waits until the child has finished execution.