Why does this ppid == 1? Am I missing something about fork()? - c

#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.

Related

fork(): Number of child processes created [closed]

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

fork: child process doesn't stay in an infinite loop

#include <stdio.h>
#include <unistd.h>
int main()
{
pid_t pid;
pid = fork();
printf("pid : %d\n", getpid());
if( pid == 0)
{
printf("child: pid : %d \n", getpid());
while(1);
}
else
{
printf("parent: pid : %d \n", getpid());
//while(1);
}
}
In the above code snippet inside if statement if we put while(1), it doesn't remains blocked and when enter key is pressed program is exited, but in case of parent if we put while(1), parent remains blocked until we give ctrl+c. Please clarify this behaviour of child.
In the above code snippet inside if statement if we put while(1), it doesn't remains blocked
The child process doesn't exit actually; it just becomes an orphan process because its parent exits. The orphaned chuld process will be adopted by the init process of your system. You can see it via ps command.
But if you put the while(1); in the parent process it remains blocked.
Basically whichever process has while(1); infinite loop, it's still running. When parent exits you get the prompt back and the child becomes orphan. But the child process is still running.
In general, you need to wait(2) for the child process in the parent process to reap child processes.

segmentation fault in c program in linux

I am getting segmentation fault in the following program.
Why? And how to resolve it?
#include <stdio.h>
main()
{
int pid;
printf("I'm the original process with PID %d and PPID %d.\n", getpid(),getppid());
pid=vfork();
if (pid!=0)
{
printf("I'm the parent process with PID %d and PPID %d.\n",getpid(),getppid());
printf("My child's PID is %d.\n", pid);
}
else
{
printf("I'm the child process with PID %d and PPID %d.\n",getpid(),getppid());
}
}
Output:
I'm the original process with PID 18563 and PPID 18500.
I'm the child process with PID 18564 and PPID 18563.
I'm the parent process with PID 18563 and PPID 18500.
My child's PID is 18564.
Segmentation fault
From vfork man page
(From POSIX.1) The vfork() function has the same effect as fork(2),
except that the behavior is undefined if the process created by
vfork() either modifies any data other than a variable of type pid_t
used to store the return value from vfork(), or returns from the
function in which vfork() was called, or calls any other function
before successfully calling _exit(2) or one of the exec(3) family of
functions.
You are returning before a successful call to _exit, so this behavior is undefined. Try fixing that and see if the problem persists.
A quote from the man page of vfork:
vfork() differs from fork(2) in that the calling thread is suspended until the child terminates (either normally, by calling _exit(2), or abnormally, after delivery of a fatal signal), or it makes a call to execve(2). Until that point, the child shares all memory with its parent, including the stack. The child MUST NOT RETURN FROM THE CURRENT FUNCTION or call exit(3), but may call _exit(2).
Your child process has returned from the function it was created in, so you probably corrupted the stack shared by both threads.

Parent and child of fork() in C

Since each process is doing its own thing, which to me feels more like a "brothers/sisters" relationship. Is there a specific reason behind calling them parent process and child process?
Also, is it true that the parent process always run before the child process?
The parent owns the process group and thus spawns and reaps the children. Usually this process does a little bit of administrative work, while the children act as peers and siblings.
The naming is just convention for describing which process spawned the other, though.
The parent process and child process does the work based on your code but not because of parent or child relationship. When you execute fork() in the main thread it will create a child process, here the fork returns a value which is different in parent process and child process which can be used to differentiate the work of parent and child processes accordingly.
fork() always return pid of child in parent process and 0 in child process.
Coming to your second question it always depends on the scheduler as soon as the fork() is called and we cannot predict which process gets to run first after fork() function call.
Is there a specific reason behind calling them parent process and child process?
Well, since it one process (the parent) that creates the second one (the child), that might be the reasoning for the naming.
Also, is it true that the parent process always run before the child process?
The short answer. Nope.
I have been using this in all of my C-code
pid_t pid = fork();
if(pid == 0){ // child
// Child stuff
}else{ // parent
// Parent stuff
}
You might also want to use the
waitpid(pid, NULL, 0);
Parents are always before child. Sort and sweet!!!
fork() creates a copy of the current process which is a part of the process control group. The new process is subordinate to the originating process, for example when a child process dies, SIGCHLD is sent to the parent. Also, the clone is an inferior copy: for instance, any stored getpid() results will be inaccurate in the child; the child has a different parentid, the child has copies of the parent's file descriptors, and has independent resource usage counters.
The parent process, then, is always the one that made the call to fork(), if that's what you mean by run first. If you mean "will the scheduler always give the parent process slices first" then the answer is no.
See: http://gauss.ececs.uc.edu/Courses/c694/lectures/ForksThreads/forks.html, http://linux.die.net/man/2/fork
#include <stdio.h>
#include <unistd.h>
int main(int argc, const char* argv[])
{
pid_t otherPid;
printf("parent pid = %u\n", getpid());
otherPid = fork();
// in the parent, otherPid = the child's (new) process ID
// in the child, otherPid = 0.
switch (otherPid) {
case -1:
printf("Fork failed: %d\n", errno);
return errno;
break;
case 0: // child
sleep(2);
printf("child: my pid is %u\n", getpid());
break;
default:
printf("parent: pid is %u, child should have %u\n", getpid(), otherPid);
sleep(3);
break;
}
return 0;
}

How to get child PID in C?

I'm creating child processes in a for-loop. Inside the child process, I can retrieve the child PID with getpid().
However, for some reason when I try to store the value of getpid() into a variable declared by the parent process, the change is nullified when I check for it in the parent process. I'm assuming this has to do with some sort of process variable scope. Not really familiar with C, so can't be too sure.
Anyhow what is a way of storing the result of getpid() of a child PID (when called from the child process) into a variable in the parent process?
Or maybe another approach is storing fork() into a variable in the parent and calling some function on that variable to retrieve the child's PID? I don't know how to do this either, so if this is the better way, how would you do this?
fork already returns the child's pid. Just store the return value.
look at man 2 fork:
RETURN VALUES
Upon successful completion, fork() returns a value of 0 to the child process and
returns the process ID of the child process to the parent process. Otherwise, a
value of -1 is returned to the parent process, no child process is created, and
the global variable errno is set to indicate the error.
As mentioned in previous answer that "fork() returns a value of 0 to the child process and returns the process ID of the child process to the parent process." So, the code can be written in this way:
pid = fork(); /* call fork() from parent process*/
if (0 == pid)
{
/* fork returned 0. This part will be executed by child process*/
/* getpid() will give child process id here */
}
else
{
/* fork returned child pid which is non zero. This part will be executed by parent process*/
/* getpid() will give parent process id here */
}
This link is very helpful and explains in detail.
if fork() is successfully created then it returns 0 value in the child process.
int main(void)
{
int id;
id= fork();
if(id==0)
{
printf("I am child process my ID is = %d\n" , getpid());
}
}
If you are calling fork in the following way:
pid = fork()
Then pid is in fact your child PID. So you can print it out from the parent.
Yes, the child process's pid is already returned with fork(), fork() is called once but return twice, different return value in parent and child process, so you can do this:
pid_t pid, pid_c;
pid = fork();
if (pid == -1) { // error
perror("Falied to fork");
} else if(pid == 0) { // execute in child process
// you can get child's pid by getpid() in child process:
pid_t tmp_pid_c = getpid();
execl("bin/ls", "ls", "./", NULL);
} else {
// you can also get child's pid that already returned by fork() in parent process
pid_c = pid;
}
There are two main functions to get the process id of parent process and child. getpid() and getppid()

Resources