cannot get expected id by using getppid() - c

I am doing a practice of multi processes. I just want to check out the parent process id, and it looks not the same as I expected. Here is my code:
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <string.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void child1()
{
//printf("we are child1..\n");
printf("my pid is:%d\n",getpid());
printf("I am child1..\n");
}
void child2()
{
//printf("we are child2..\n");
printf("my pid is:%d\n",getpid());
printf("I am child2.., my parent is:%d\n",getppid());
}
int main()
{
pid_t childpid[4];
int i;
printf("main pid is:%d\n",getpid());
for (i=0;i<2;i++)
{
childpid[i] = fork();
if (childpid[i]<0)
printf("fork fail..\n");
else if (childpid[i]==0)
{
childpid[i+2] = fork();
if (childpid[i+2] <0)
printf("fork inside fail..\n");
else if (childpid[i+2]==0)
child2();
else // this is parent process..
child1();
}
}
}
and here is the execution result:
my pid is:3951
I am child1..
my pid is:3950
I am child1..
my pid is:3952
I am child2.., my parent is:1118
my pid is:3954
I am child1..
my pid is:3953
I am child2.., my parent is:1118
my pid is:3956
I am child1..
my pid is:3955
I am child2.., my parent is:1118
my pid is:3957
I am child2.., my parent is:1118
since my child2 process is forked inside the process1, I expect the parent pid might be something like:3950. How come my result get:1118?
thanks for your help!

When I run your code verbatim (well, OK; I added void to each empty argument list and made the child functions static), then I got sample output:
main pid is:46761
my pid is:46762
I am child1..
my pid is:46763
my pid is:46764
I am child1..
I am child2.., my parent is:46762
my pid is:46765
I am child2.., my parent is:1
my pid is:46766
I am child1..
my pid is:46768
my pid is:46767
I am child2.., my parent is:46766
I am child1..
my pid is:46769
I am child2.., my parent is:1
For amusement value, I ran the output to a pipe and got:
main pid is:46770
main pid is:46770
my pid is:46773
I am child1..
main pid is:46770
my pid is:46772
I am child1..
main pid is:46770
my pid is:46775
I am child2.., my parent is:1
main pid is:46770
my pid is:46774
I am child2.., my parent is:46772
main pid is:46770
my pid is:46772
I am child1..
my pid is:46776
I am child1..
main pid is:46770
my pid is:46772
I am child1..
my pid is:46778
I am child2.., my parent is:1
main pid is:46770
my pid is:46774
I am child2.., my parent is:46772
my pid is:46777
I am child1..
main pid is:46770
my pid is:46774
I am child2.., my parent is:46772
my pid is:46779
I am child2.., my parent is:46777
See printf() anomaly after fork() for an explanation of that behaviour.
Then I instrumented your code slightly differently, but the core logic is unchanged:
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
static void child1(void)
{
printf("Child1: PID = %d, PPID = %d\n", (int)getpid(), (int)getppid());
}
static void child2(void)
{
printf("Child2: PID = %d, PPID = %d\n", (int)getpid(), (int)getppid());
}
int main(void)
{
pid_t childpid[4];
int i;
printf("main pid is:%d\n", getpid());
for (i = 0; i < 2; i++)
{
fflush(0);
childpid[i] = fork();
if (childpid[i] < 0)
printf("fork fail in PID %d\n", getpid());
else if (childpid[i] == 0)
{
childpid[i + 2] = fork();
if (childpid[i + 2] < 0)
printf("fork fail in PID %d\n", getpid());
else if (childpid[i + 2] == 0)
child2();
else
{
printf("child pid %d forked child %d\n", (int)getpid(), (int)childpid[i+2]);
child1();
}
}
else
printf("main pid %d forked child %d\n", (int)getpid(), (int)childpid[i]);
}
int status;
int corpse;
while ((corpse = wait(&status)) != -1)
printf("PID %d: child %d died with status %.4X\n", (int)getpid(), corpse, status);
printf("PID %d: finished\n", (int)getpid());
return getpid() % 256;
}
I did add the code to wait for children to die, and to report when a process finishes, and added non-zero exit statuses for most of the processes. The code also flushes standard output before forking to keep things clean (even if the output is going to a pipe or file).
On my Mac OS X 10.11.1 El Capitan machine, I got, for example:
main pid is:46730
main pid 46730 forked child 46731
main pid 46730 forked child 46732
child pid 46731 forked child 46733
Child1: PID = 46731, PPID = 46730
child pid 46732 forked child 46734
main pid 46731 forked child 46735
Child1: PID = 46732, PPID = 46730
Child2: PID = 46733, PPID = 46731
Child2: PID = 46734, PPID = 46732
PID 46734: finished
main pid 46733 forked child 46736
PID 46732: child 46734 died with status 8E00
PID 46732: finished
child pid 46735 forked child 46737
Child1: PID = 46735, PPID = 46731
PID 46730: child 46732 died with status 8C00
Child2: PID = 46737, PPID = 46735
child pid 46736 forked child 46738
Child1: PID = 46736, PPID = 46733
PID 46737: finished
Child2: PID = 46738, PPID = 46736
PID 46735: child 46737 died with status 9100
PID 46735: finished
PID 46738: finished
PID 46736: child 46738 died with status 9200
PID 46731: child 46735 died with status 8F00
PID 46736: finished
PID 46733: child 46736 died with status 9000
PID 46733: finished
PID 46731: child 46733 died with status 8D00
PID 46731: finished
PID 46730: child 46731 died with status 8B00
PID 46730: finished
When you study the sequencing in that output, there are some interesting interleavings of execution.
None of that explains why you got 1118; in many ways, that is impossible to explain because no-one can sequence things exactly as on your machine. However, what I've shown is plausible behaviour, and it does not reproduce the 'all processes have a single PID as the PPID'. You should be able to make incremental monitoring improvements to your code and demonstrate which change alters the behaviour on your machine.

Your processes don't wait for their children to terminate. Most likely, the parent process had already terminated and the child was reparented.

Related

How to obtain the child process PID in C

In order to get the PID of the child process I am doing this.
pid_t pid;
pid=fork();
if(pid==0){
//child's work
}else{
printf("The child's PID is %d",pid);
}
I want to print the child's pid from parent! So is it ok if I printf pid or do I need to use getpid()?
On success fork returns the pid of the child process, so pid will be the pid of the child process, So I'd say it's correct.
getpid is to get the pid of the current process, so it's not suited to get the child's pid.
I think this sums up the question :
#include <stdio.h>
#include <unistd.h>
int main(){
pid_t pid;
pid = fork();
if(pid == 0){
printf("In child => Own pid : %d\n", getpid());
printf("In child => Parent's pid : %d\n", getppid());
}
else{
printf("In Parent => Child's pid is %d\n", pid);
printf("In Parent => Own pid : %d\n", getpid());
}
return 0;
}

Forking a process into 7 children without looping

How can I create 7 processes using 1 parent in just 3 forks() calls? Looping is not allowed out of 7 1 is the parent one
I tried
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void) {
printf("master process is %d.\n", getpid());
fork();
fork();
fork();
wait(0);
printf("my pid is %d; my parent pid is %d\n", getpid(), getppid());
return 0;
}
and got the output
master process is 28982.
my pid is 28982; my parent pid is 31294
my pid is 28985; my parent pid is 28982
my pid is 28984; my parent pid is 28982
my pid is 28983; my parent pid is 1
my pid is 28986; my parent pid is 28984
my pid is 28988; my parent pid is 28983
my pid is 28987; my parent pid is 1
my pid is 28989; my parent pid is 28987
Total number of processes created using fork() can be found using 2^n where n is the number of times fork() is being called. Here if we calls fork() 3 times, then 2^3 processes will be created i.e 8.

Why does the child process think the parent's process id is 1?

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main ( void ) {
int pid, fpid, ppid;
fpid = fork();
printf ("fpid is is %d\n", fpid);
sleep(5);
if (fpid > 0) {
pid = getpid();
ppid = getppid();
printf ("\nThis is Parent. My pid %d. My parent's pid %d\n", pid, ppid);
} else if (fpid == 0) {
sleep(1);
pid = getpid();
ppid = getppid();
printf ("\nThis is Child. My pid %d. My parent'a pid %d\n", pid, ppid);
}
}
I think when the parent process ID is 1 it means that the parent process has been terminated, so the child process gets re-parented to 1 (init, the first process). Is there any reason why the parent process would be terminated?
Parent process doesn't wait (by means of wait(2)) for the child process to complete. So, if parent exits before the child (it becomes an orphan process), then child process will be re-parented (adopted) to init process whose process ID is usually 1. Thus the child process says its parent process ID is 1.
Note that the init process' ID isn't necessarily 1 on all systems. POSIX doesn't mandate any such thing.
Because the child sleeps, by the time it calls getppid(), its parent will have likely died and the child will have been reparented to the init process (pid == 1).

Is child process pid() gets assigned to parent process?

I have read this in books and also in some online forums that child process pid is assigned to its parent. But I have this code:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
pid_t pid;
pid=fork();
if(pid==0)
{
printf("In Child Process\n");
printf("Child process PID : %d\n",getpid());
printf("Parent Process PID : %d\n",getppid());
}
else
{
printf("In Parent Process\n");
printf("Child PID : %d\n",getpid());
printf("Parent PID : %d\n",getppid());
}
}
It outputs:
In Parent Process
Child PID : 2061
Parent PID : 1830
In Child Process
Child process PID : 2062
Parent Process PID : 1161
But if I write a wait() function in else block, i.e:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
pid_t pid;
pid=fork();
if(pid==0)
{
printf("In Child Process\n");
printf("Child process PID : %d\n",getpid());
printf("Parent Process PID : %d\n",getppid());
}
else
{
wait();
printf("In Parent Process\n");
printf("Child PID : %d\n",getpid());
printf("Parent PID : %d\n",getppid());
}
}
It outputs-
In Child Process
Child process PID : 2044
Parent Process PID : 2043
In Parent Process
Child PID : 2043
Parent PID : 1830
I'm not getting why the pid value returned by child process in first code is not the same as parent pid.
While in the second code, it is the same. Can someone please explain the reason for the above problem?
Remember that getpid returns the pid of the current process, and that getppid returns the parent pid of the current process.
So in the second example, when you call getpid in the parent process you get the pid of if itself (the parent process) and getppid gets the pid of the grand-parent.
The child pid is the value returned by fork.
More related to your problem is that you have no control over when a specific process runs in a modern multi-tasking system, which means that the child and parent processes may take turn printing out text. In your case it seems that the child process in the first example doesn't get to run until the parent process has printed its lines.
What the wait function does, is to actually wait until one child process has exited, and so the parent process will block until the child process has exited.
Joachim's answer is excellent. As additional note, you can get the child process' pid in the else branch by printing the result of fork:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
pid_t pid;
pid=fork();
if(pid==0)
{
printf("In Child Process\n");
printf("Child process PID : %d\n",getpid());
printf("Parent Process PID : %d\n",getppid());
}
else
{
wait();
printf("In Parent Process\n");
printf("Child PID : %d\n", pid); // fork returns the pid of the child
printf("Parent PID : %d\n", getpid()); // because I'm the parent
}
}
First Example:
fork returns two processes, In your first example after fork the parent starts execution and prints its pid 2061 and parent pid 1830 (of bash) and the parent will terminate without waiting for the child to finish, So when child starts executing it will print its pid 2062 and its parent has already terminated it is printing some other pid.
You please sleep() before printing parent pid when child process is running and on other terminal use command ps -l to see which pid the child is printing as a parent pid.
Second example:
You are using wait in parent process that is parent will wait untill child terminates thus child process is printing the correct parentpid because parent is still not terminated.

Why getppid() from the child return 1

I was running the program
#include<stdio.h>
#include <unistd.h>
main()
{
pid_t pid, ppid;
printf("Hello World1\n");
pid=fork();
if(pid==0)
{
printf("I am the child\n");
printf("The PID of child is %d\n",getpid());
printf("The PID of parent of child is %d\n",getppid());
}
else
{
printf("I am the parent\n");
printf("The PID of parent is %d\n",getpid());
printf("The PID of parent of parent is %d\n",getppid());
}
}
THe output I got was.
$ ./a.out
Hello World1
I am the parent
The PID of parent is 3071
The PID of parent of parent is 2456
I am the child
The PID of child is 3072
The PID of parent of child is 1
I couldnt understand the line
The PID of parent of child is 1
It should have been 3071?
Because parent process is finished by the time the child asks for its parent's pid.
When a process finishes, all its children are reassigned as children of the init process, which pid is 1.
Try using wait() in parent's code to wait for the child to execute. It should then work as you expect.
pid 1 is for init process and it looks like the parent process finished before the child could print.
If you edit the else part like this :-
else
{
printf("I am the parent\n");
printf("The PID of parent is %d\n",getpid());
printf("The PID of parent of parent is %d\n",getppid());
while(1);
}
You should see the right output.

Resources