0

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!

KennyYang
  • 235
  • 2
  • 13
  • What process has id 1118? – David Schwartz Dec 02 '15 at 06:32
  • 1
    In part, you're (probably) confusing yourself because your children return to the loop in the main program and do more forking; that's why you have so many processes showing up. I'm puzzled that you don't print the PID and PPID in every process; that's one of the first things I'd do in debugging. I'd also have the parent process report on the children it creates as it creates them. What happened to 'main pid' in the output? It's also not a bad idea to use `fflush(0)` before you `fork()` — see [`printf()` anomaly after `fork()`](https://stackoverflow.com/questions/2530663/). – Jonathan Leffler Dec 02 '15 at 06:34

2 Answers2

1

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.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

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

David Schwartz
  • 179,497
  • 17
  • 214
  • 278