Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do processes I fork get systemd as their parent?

I am learning fork() in Linux, and here is my program:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 int main(void){
  5         int pid;
  6         pid = fork();
  7         if(pid < 0){
  8                 exit(1);
  9         }
 10         if(pid == 0){
 11                 fork();
 12                 fork();
 13                 printf("pid:%d ppid:%d\n",getpid(),getppid());
 14                 exit(0);
 15                 }
 16         else{
 17                 printf("parent pid:%d ppid:%d\n",getpid(),getppid());
 18                 exit(0);
 19         }       
 20        
 21 }

Sometimes it worked fine, with result like this:

./test1.out
parent pid:27596 ppid:21425
pid:27599 ppid:27597
pid:27597 ppid:27596
pid:27598 ppid:27597
pid:27600 ppid:27598

But the result was not consistent, more often than not it worked like this:

parent pid:27566 ppid:21425
pid:27567 ppid:27566
pid:27568 ppid:27567
pid:27569 ppid:1599
pid:27570 ppid:1599

Which makes no sense to me, so I typed $ps aux to find out what process 1599 is:(with some columns deleted)

  USER       PID  VSZ   RSS    STAT START   COMMAND
  linux     1599  63236  6316   Ss   09:03  /lib/systemd/systemd --user

Can anybody help me straighted things up?

like image 825
Lucas Avatar asked Nov 04 '16 13:11

Lucas


People also ask

Why do some child processes have 1 as their parent PID?

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.

How does forking affect the parent process?

fork() creates a new process by duplicating the calling process. The new process is referred to as the child process. The calling process is referred to as the parent process. The child process and the parent process run in separate memory spaces.

What does fork return for parent?

RETURN VALUE Upon successful completion, fork() returns 0 to the child process and returns the process ID of the child process to the parent process. Otherwise, -1 is returned to the parent process, no child process is created, and errno is set to indicate the error.

Do fork call return in both child and parent process?

The fork() call is unusual in that it returns twice: It returns in both the process calling fork() and in the newly created process. The child process returns zero and the parent process returns a number greater then zero.


3 Answers

The "inconsistency" you observed is because sometimes, the parent process(es) exited before their child process(es) terminated. So, these child processes become "orphans" as their parent processes are not waiting for them. As a result, they are "re-parented" to the init process. While traditionally the process id of the "init" process is 1, it's not always true. POSIX leaves it as implementation-defined:

The parent process ID of all of the existing child processes and zombie processes of the calling process shall be set to the process ID of an implementation-defined system process. That is, these processes shall be inherited by a special system process.

Thus you see a particular PID as the parent (1599 in your example), which happens to be "init" process equivalent on your Linux. The systemd is an init variant used in Debian Linux distributions - which follows a slightly more complicated implementation.

In essense, what you observed is pretty normal. Ideally, you should reap all the processes in order to avoid zombie processes.

like image 62
P.P Avatar answered Oct 01 '22 16:10

P.P


I suppose that, sometimes, a race condition happens, and the parent dies before the child. Hence, the child becomes children from init process. In your case, that must be systemd.

Anyway, be advised that running fork(); fork(); will produce 4 processes, which is (probably) not what you intend. Use control structure as you did with the first one to have fine control on the behaviour of your program.

like image 41
Aif Avatar answered Oct 04 '22 16:10

Aif


It is because the parent process terminates first. In Linux there are no ophan processes. They are assigned to the init process.

If you want to control your processes so that child process terminates first, make parent process wait. Using wait() sys_call.

Example:

   #include <stdio.h>
   #include <stdlib.h>
   #include <unistd.h>
   int main(void)
   {
        int pid;
        int pid2;
        pid = fork();
        if(pid < 0){
                 exit(1);
        }
        if(pid == 0){ // child process
            pid2 = fork()
            if (pid2 < 0)
                exit(1);
            if (pid2 == 0)
            {
                printf("pid:%dppid:%d\n",getpid(),getppid());
                exit(0);
            }
            wait();
            printf("pid:%d ppid:%d\n",getpid(),getppid());
            exit(0);
        }
        else{         // parent process
           wait();
           printf("parent pid:%d ppid:%d\n",getpid(),getppid());
           exit(0);
        }       
        return 0;            
  }

systemd is an init system used in Linux distributions to bootstrap the user space and manage all processes subsequently

like image 33
Tony Tannous Avatar answered Oct 03 '22 16:10

Tony Tannous