I am creating new processes by forking:
printf("original process = %d\n", getpid());
fork();
printf("parent = %d; child = %d\n", getpid(), getppid());
fork();
printf("parent = %d; child = %d\n", getpid(), getppid());
if(fork() == 0){
printf("parent = %d; child = %d\n", getpid(), getppid());
if(fork() == 0){
printf("parent = %d; child = %d\n", getpid(), getppid());
}
}
fork();
printf("parent = %d; child = %d\n", getpid(), getppid());
and I want to print out how many processes I have created. My approach as seen above is not the best way of printing how many processes have been created. So my question is: how can we print how many new processes have been created each time we fork without having some kind of loop?
Each successful call to fork creates a new process, and both the parent and the child return from fork(). The child will get 0 as return, the parent the PID of the child.
printf("I am the root %d\n", getpid());
if (fork() == 0)
printf("I am %d, child of %d\n", getpid(), getppid());
if (fork() == 0)
{
printf("I am %d, child of %d\n", getpid(), getppid());
if (fork() == 0)
printf("I am %d, child of %d\n", getpid(), getppid());
}
if (fork() == 0)
printf("I am %d, child of %d\n", getpid(), getppid());
And so on...
The problem in your code is that you are printing the text in some cases without checking the return value of fork(), so these lines will be printed both by the parent and the child. With my code, each process prints just one line, on creation.
As each creates/spawns a child process,
Based on the order in which the fork() is called
Totally 24 child process are created, this is how its done
1st fork(); (has 4 more fork() calls)
2st fork(); (has 3 more fork() calls)
3st fork(); (has 2 more fork() calls)
4st fork(); (has 1 more fork() calls)
So the totall number of child process would be 4! - 1, that is 4x3x2x1 = 24 - 1
23 child process are created
Related
I want to create a tree of processes like the one on the picture. The Z process should display the whole tree after seconds given as program argument and I need to handle proper destruction of tree. Additionally, I can't use sleep() command. Program output should look like that:
I’m the process arb: my pid is 751
I’m the process A: my pid is 752. My father is 751
I’m the process B: my pid is 753. My father is 752, grandfather 751
I’m the process X: my pid is 754. My father is 753, grandfather 752, great-grandfather is 751
I’m the process Y: my pid is 755. My father is 753, grandfather 752, great-grandfather is 751
I’m the process Z: my pid is 756. My father is 753, grandfather 752, great-grandfather is 751
//wait some seconds and display process tree
I am Z (755) and I die
I am Y (755) and I die
I am X (754) and I die
I am B (753) and I die
I am A (752) and I die
I am arb (751) and I die
After getting to last child and raising alarm it doesn't display the process tree and starts to create some new processes instead of killing them. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
int arb;
void z_function() {
printf("pstree\n");
execl("/bin/pstree", "pstree", "-p", arb, (char*)0);
printf("I am Z (%d) and I die\n", getpid());
kill(getpid(), SIGKILL);
}
int main(int argc, char **argv) {
signal(SIGALRM, z_function);
int arg = atoi(argv[1]);
printf("arg: %d\n", arg);
arb = getpid();
printf("I'm the process arb: my pid is %d\n", getpid());
//A
if (fork() == 0) {
int a = getpid();
printf("I'm the process A: my pid is %d. My father is %d\n", getpid(), getppid());
//B
if (fork() == 0) {
int b = getpid();
printf("I'm the process B: my pid is %d. My father is %d, grandfather %d\n", getpid(), getppid(), arb);
int children[3];
for (int i = 0; i < 3; i++) {
if (fork() == 0) {
children[i] = getpid();
switch(i) {
case 0:
printf("I'm the process X: my pid is %d. My father is %d, grandfather %d, great-grandfather is %d\n", getpid(), getppid(), a, arb);
wait(NULL);
break;
case 1:
printf("I'm the process Y: my pid is %d. My father is %d, grandfather %d, great-grandfather is %d\n", getpid(), getppid(), a, arb);
wait(NULL);
break;
case 2:
printf("I'm the process Z: my pid is %d. My father is %d, grandfather %d, great-grandfather is %d\n", getpid(), getppid(), a, arb);
alarm(arg);
pause();
//exit(0);
break;
}
}
else {
wait(NULL);
}
}
wait(NULL);
kill(children[1], SIGKILL);
printf("I am Y (%d) and I die\n", children[1]);
kill(children[0], SIGKILL);
printf("I am X (%d) and I die\n", children[0]);
printf("I am B (%d) and I die\n", getpid());
exit(0);
}
wait(NULL);
printf("I am A (%d) and I die\n", getpid());
exit(0);
}
else {
wait(NULL);
printf("I am arb (%d) and I die\n", getpid());
exit(0);
}
while (wait(NULL) > 0)
exit(0);
return 0;
}
I am trying to better understand fork(), waitpid() and child/parent processes, however there are some strange behaviors I have encountered with the following code:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void){ // Main
int status;
pid_t wPID, cPID;
printf("[%i] Hi I am the parent and I am about to create a child...\n", getpid());
fflush(0);
pid_t childPID = fork();
if (childPID >= 0){
if(childPID == 0){ //child process
cPID = getpid();
printf("[%i] %i\n", getpid(), cPID );
printf("[%i] Hi, I am the child process...\n", getpid() );
sleep(1);
for(int i = 0; i<3; i++){
printf("[%i] %i\n", getpid(), i);
}
exit(0);
}
else{ //parent
printf("[%i] %i\n", getpid(), cPID );
wPID = waitpid(cPID, &status, 0);
printf("[%i] value returned by waitpid: %i\n", getpid(), wPID);
if (WIFEXITED(status))
printf("[%i] child exited, status=%d\n", getpid(), WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("[%i] child killed (signal %d)\n", getpid(), WTERMSIG(status));
else if (WIFSTOPPED(status))
printf("[%i] child stopped (signal %d)\n", getpid(), WSTOPSIG(status));
else /* Non-standard case -- may never happen */
printf("Unexpected status (0x%x)\n", status);
return 0;
}
}
else{
printf("\n Fork failed, quitting!\n");
return 2; // error
}
}
console output:
$ ./waitpidexample
[6103] Hi I am the parent and I am about to create a child...
Error: No child processes
[6103] 1540418008
[6103] value returned by waitpid: -1
[6103] child killed (signal 54)
[6104] 6285
[6104] Hi, I am the child process...
[6104] 0
[6104] 1
[6104] 2
I believe my issue is in the cPID variable being used in waitpid()...
there is some sort of scope issue happening here, as it evaluates to different values in the child / parent.
How am I supposed to get the correct child process id for use in waitpid()?
Why is the code after my waitpid() being executed before the code in the child process?
cPID is only changed in the child process. When you call fork, a complete copy is made (functionally, in reality until something is changed, the memory is shared). This means that when cPID is written in the child (first branch) the parent does not see it. Change the references to cPID in the parent (second branch) to childPID (assigned from fork()):
else{ //parent
printf("[%i] %i\n", getpid(), childPID );
wPID = waitpid(childPID, &status, 0);
printf("[%i] value returned by waitpid: %i\n", getpid(), wPID);
if (WIFEXITED(status))
printf("[%i] child exited, status=%d\n", getpid(), WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("[%i] child killed (signal %d)\n", getpid(), WTERMSIG(status));
else if (WIFSTOPPED(status))
printf("[%i] child stopped (signal %d)\n", getpid(), WSTOPSIG(status));
else /* Non-standard case -- may never happen */
printf("Unexpected status (0x%x)\n", status);
return 0;
}
Also, I recommend using braces after all your if statements
Run Order
fork() does not define which process gets run first, just that there is now a child process (in which it returns 0) and a parent process (in which it returns the child's PID). The child process will be identical to the parent, except for the return value of fork(). Sometimes, the parent goes first, sometimes the child does. It is non-deterministic.
In the parent process, cPID is never initialized. The variables in the parent and child are separate from each other, so a variable change in the child is not visible in the parent and vice versa.
The parent already has the child pid in childPID, so use that instead.
printf("[%i] %i\n", getpid(), childPID );
wPID = waitpid(childPID, &status, 0);
I'm writing a C program that creates a child process. After creating the child process, the parent process should ouput two messages: "I am the parent" then it should print "The parent is done". Same for child process "I am child" and "The child is done". However I want to make sure, the second message of the child is always done before the second message of the parent. How can I achieve to print "The child is done" and "The parent is done" rather than printing their pid?
#include <unistd.h>
#include <stdio.h>
main()
{
int pid, stat_loc;
printf("\nmy pid = %d\n", getpid());
pid = fork();
if (pid == -1)
perror("error in fork");
else if (pid ==0 )
{
printf("\nI am the child process, my pid = %d\n\n", getpid());
}
else
{
printf("\nI am the parent process, my pid = %d\n\n", getpid());
sleep(2);
}
printf("\nThe %d is done\n\n", getpid());
}
You could have a flag variable, that is set in the parent, but then the child clears it. Then simply check for that for the last output.
Something like
int is_parent = 1; // Important to create and initialize before the fork
pid = fork();
if (pid == -1) { ... }
if (pid == 0)
{
printf("\nI am the child process, my pid = %d\n\n", getpid());
in_parent = 0; // We're not in the parent anymore
}
else { ... }
printf("\nThe %s is done\n\n", is_parent ? "parent" : child");
Call wait(2) in the parent process for the child to complete.
else
{
wait(0);
printf("\nI am the parent process, my pid = %d\n\n", getpid());
}
You should check if wait() succeeds and main()'s return type should be int.
I have this code that gets its process ID and its parent process:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(){
int pid;
printf("I am the original process with PID %d and PPID %d. \n", getpid(), getppid());
pid = fork();
if (pid >0){
printf("I am the original process with PID %d and PPID %d \n", getpid(), getppid());
printf("My child’s pid is %d \n" , pid);
}
else if(pid == 0) {
printf ("I am the original process with PID %d and PPID %d \n", getpid(), getppid());
}
else if (pid == 1){
printf ("Error – no child process was created \n");
}else{
printf ("Error – system error \n");
}
printf (" PID %d terminates \n", getpid()); /* both processes execute this instruction */
return 0;
}
OUTPUT
I am the original process with PID 1009 and PPID 964.
I am the original process with PID 1009 and PPID 964
My child’s pid is 1010
PID 1009 terminates
I am the original process with PID 1010 and PPID 1009
PID 1010 terminates
Few questions that confuses me..
how does this code is executed?
In the output, you can see that it runs the code under under if(pid == 0) while the condition if(pid > 0) is already executed. how come pid is equal to 0? while it was set already to greater than 0.
Lastly , what does fork() really do?
fork() makes multiple processes, or a "child". So the parent and child execute the code. The parent's pid is > 0 and the child's is ==0.
So, the parent and child execute at similar times starting at the fork command. So let's start with the parent. The parent checks the first statement (pid > 0) and finds it is true, so it prints out the two statements. Then it goes all the way to the print statement after the last else.
Now to the child. The child checks the first if statement, and is false. Checks the next (pid == 0) and finds it is true. So now it's going to print out that statement. Now it will skip to the print statement after the else and prints again.
Note: The parent and child can execute at different times, so if you run the code multiple times the output may be in a different order.
I'm trying to write a C program where I have one parent that create two childs.
My task is to retrieve the process ID of the parent of and both childs. For this I've been using getpid().
Now I've been asked to get the child information from the parent. I don't get how I can do this. Like how can I obtain the processing ID for a child from the parent?
I have this at the moment (simplified)
fork1 = fork();
if (fork1 < 0)
fork error
else if (fork1 == 0) {
child 1
use getpid()
use getppid()
} else {
fork2 = fork();
if (fork2 < 0)
fork error
else if (fork2 == 0) {
child 2
use getpid()
use getppid()
} else
parent again
}
After a minute of googling I found this page, where everything you need is written:
System call fork() is used to create processes. It takes no arguments and returns a process ID.
I highlighted the part which is importand for you, so you don't need to do anything to get the process IDs of the children. You have them already in fork1 and fork2!
Here is some code which will print the PIDs from parent and children.
#include <stdio.h>
int main() {
int fork1 = fork();
if (fork1 < 0) {
printf("error\n");
} else if (fork1 == 0) {
printf("I'm child 1\n");
printf("child 1: parent: %i\n", getppid());
printf("child 1: my pid: %i\n", getpid());
} else {
int fork2 = fork();
if (fork2 < 0) {
printf("error\n");
} else if (fork2 == 0) {
printf("I'm child 2\n");
printf("child 2: parent: %i\n", getppid());
printf("child 2: my pid: %i\n", getpid());
} else {
printf("I'm the parent\n");
printf("The PIDs are:\n");
printf("parent: %i\n", getpid());
printf("child 1: %i\n", fork1);
printf("child 2: %i\n", fork2);
}
}
return 0;
}
fork() returns two different values, it returns zero to the child and returns non-zero positive value to the parent, this value is the child process ID, so in your last else, fork1 is the pid of child1 and fork2 is the pid of child2.