Why do processes I fork get systemd as their parent? - c

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?

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.

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.

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

Related

How do I consistently find the PID of a program OR how do I send the kill shortcut to my terminal from a C script?

I'm answering my own question here because all of the other threads talking about this gave generally inefficient solutions to this problem[refer to title].
The most logical way to find the PID of a program is with getpid. However for some reason getpid command always gives you the PID that is two numbers behind the actual program ID it's about to be assigned. I'm sure someone more familiar with the linux kernel will be sure to explain why I'm an idiot in the comments below, so the reasoning for the -2 pid is probably down there.
Anyway, here's a reverse engineered c script(from MTU) that gives you the PID of the program.
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
void main(void)
{
pid_t pid;
char fetch[50];
pid = getpid();
int pid2=pid+2;
sprintf(fetch, "echo hello world! my PID is %d", pid2);
system(fetch);
}
However for some reason getpid command always gives you the PID that is two numbers behind the actual program ID it's about to be assigned.
Well, getpid returns the PID of the current process.
How can it return the PID of a new process that doesn't exist yet? How could it possibly know?
The current process has a process ID. When you call system, it creates a child process, with its own process ID. Presumably the child process then creates another child to execute the command you passed to system.
By default the first child's PID will be the current process PID + 1. And the second child's PID will be the current process PID + 2. However, if either of those IDs are already in use (or you hit the maximum value of a pid_t and wrap around), this brittle logic will break completely.
If you want to get a child process' PID, call fork directly:
pid_t childpid = fork();
if (childpid < 0) {
perror("failed to fork");
exit(1);
}
if (childpid == 0) {
/* this path executes in the child process */
exec_command_in_child();
} else {
/* this path executes in the parent */
wait_or_kill_or_something(childpid);
}

Creating Zombie process in C (Linux) [duplicate]

This question already has answers here:
Create zombie process
(2 answers)
Closed 1 year ago.
my task is to create zombie process. My code looks like this:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
pid_t pid = fork();
if (pid == -1) {
printf("error\n");
}
else if (pid == 0) {
printf("Child %d\n", getpid());
printf("Parents %d\n", getppid());
printf("Waiting for my Child to complete\n");
exit(0);
}
else {
sleep(5);
printf("Parent %d\n",getpid());
}
return 0;
}
When I gcc and execute the file with ./a.out I get the following output:
Child 25097
Parents 25096
Waiting for my child to complete
Parent 25096 ( a few seconds later)
My task is to create a zombie process and print out the exit-state of the child process while being in parent process. Everything is a bit confusing to me because its the first time for me using Linux and C.
Do you have some tips/ hints for me, how to solve the task? Cause I'm not sure if everything is right. I also tried playing with wait(), waitpid() and WEXITSSTATUS(), but I'm not sure about it. And I used the ps x command to check if there is a different output but I didn't notice any changes.
Thanks in advance :)
This code will successfully create a zombie process.
After the call to fork, the child prints a few lines and exits, while the parent sleeps for 5 seconds. This means you'll have a zombie process for about 5 seconds while the parent is sleeping.
When the sleep is done, the parent prints something and exits. Once the parent exits the child is inherited by the init process, which will wait for the child and make it's pid disappear fro the pid list.
You can also use wait in the parent process, in which case the child is a zombie up until the parent calls wait.

How many processes this code going to generate?

I am not sure how many processes going to be created in this program? I suppose there is going to be created three child process in a while loop. Then, each child process is going to fork two times which means there are going to be two child process plus the one created by that child process is also going to fork and there is going to be 4 child process for each state. In total, there are 12 processes. Is that true?
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
pid_t childpid;
int i=0;
while((childpid>0) && (i<3))
{
childpid=fork();
i++;
}
if(childpid==0){
fork();
fork();
}
exit(0);
}
The total number of processes is 13
while((childpid>0) && (i<3))
will only execute for the parent since the fork() system call returns the pid of the child to the parent process and a 0 to the child process.
Thus the while loop will generate 3 child processes with the childpid variable value 0, and the main parent process which now has the childpid variable value equal to that of the last forked child.
Total processes till now 4
For the condition
if(childpid==0){
fork();
fork();
}
each child process from before spawns 1 child in the first fork call. The second fork will spawn another two new processes from the two proceeses of the first fork. So for each child process we will have spawned processes a total of 3 new processes.
Thus for th 3 child processes from the while loop, we will generate 9 new processes.
So total number of processes would be 4 + 9 = 13

Linux Fork: pid reuse

I wrote the following program to understand the way fork works when called without wait() or waitpid().
int main()
{
pid_t childpid;
int retval = 0;
int i;
while(1){
//usleep(1);
childpid = fork();
if (childpid >= 0)
{
i++;
if (childpid == 0)
{
exit(retval);
}
else
{
//printf("childpid is %d\n", childpid);
}
}
else
{
printf("total no. of processes created = %d\n", i);
perror("fork");
exit(0);
}
}
}
Here's the output I get->
total no. of processes created = 64901
fork: Cannot allocate memory
I expected the program to go on as I'm exiting the child process instantly and fork() should reuse the pids after pid > pid_max. Why doesn't this happen?
The exited child processes do remain in the process table as zombies. Zombie processes exist until their parent calls wait or waitpid to obtain their exit status. Also, the corresponding process id is kept, to prevent other newly created processes of duplicating it.
In your case, the process table becomes too large and the system rejects the creation of new processes.
Forking processes and then not retrieving their exit status can be regarded as a resource leak. When the parent exits, they will be adopted by the init process and then reaped, but if the parent stays alive for too long, there is no way for the system to just remove some of the zombies, because it is assumed that the parent should get interested in them at some point via wait or waitpid.
Child processes also hold some resource like memory. But they are not released because parent process can not process SIGCHLD signal, which will be sent by child processes when they exit.
Those child processes will become zombie.
You can use "ps -aux" to dump those fd.

Create zombie process

I am interested in creating a zombie process. To my understanding, zombie process happens when the parent process exits before the children process. However, I tried to recreate the zombie process using the following code:
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main ()
{
pid_t child_pid;
child_pid = fork ();
if (child_pid > 0) {
exit(0);
}
else {
sleep(100);
exit (0);
}
return 0;
}
However, this code exits right after execute which is expected. However, as I do
ps aux | grep a.out
I found a.out is just running as a normal process, rather than a zombie process as I expected.
The OS I am using is ubuntu 14.04 64 bit
Quoting:
To my understanding, zombie process happens when the parent process exits before the children process.
This is wrong. According to man 2 wait (see NOTES) :
A child that terminates, but has not been waited for becomes a "zombie".
So, if you want to create a zombie process, after the fork(2), the child-process should exit(), and the parent-process should sleep() before exiting, giving you time to observe the output of ps(1).
For instance, you can use the code below instead of yours, and use ps(1) while sleep()ing:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
int status;
if ((pid = fork()) < 0) {
perror("fork");
exit(1);
}
/* Child */
if (pid == 0)
exit(0);
/* Parent
* Gives you time to observe the zombie using ps(1) ... */
sleep(100);
/* ... and after that, parent wait(2)s its child's
* exit status, and prints a relevant message. */
pid = wait(&status);
if (WIFEXITED(status))
fprintf(stderr, "\n\t[%d]\tProcess %d exited with status %d.\n",
(int) getpid(), pid, WEXITSTATUS(status));
return 0;
}
A zombie or a "defunct process" in Linux is a process that has been completed, but its entry still remains in the process table due to lack of correspondence between the parent and child processes. Usually, a parent process keeps a check on the status of its child processes through the wait() function. When the child process has finished, the wait function signals the parent to completely exit the process from the memory. However, if the parent fails to call the wait function for any of its children, the child process remains alive in the system as a dead or zombie process. These zombie processes might accumulate, in large numbers, on your system and affect its performance.
Below is a c program to creating a Zombie-Process on our system Save this file as zombie.c:
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main ()
{
pid_t child_pid;
child_pid = fork ();
if (child_pid > 0) {
sleep (60);
}
else {
exit (0);
}
return 0;
}
The zombie process created through this code will run for 60 seconds. You can increase the time duration by specifying a time(in seconds) in the sleep() function.
Compile this program
gcc zombie.c
Now run the zombie program:
./a.out
The ps command will now also show this defunct process, open a new terminal and use the below command to check the defunct process:
aamir#aamir:~/process$ ps -ef | grep a.out
aamir 10171 3052 0 17:12 pts/0 00:00:00 ./a.out
aamir 10172 10171 0 17:12 pts/0 00:00:00 [a.out] <defunct> #Zombie process
aamir 10177 3096 0 17:12 pts/2 00:00:00 grep --color=auto a.out

Resources