Multi Level Single Parent Single Child Process tree? - linux

so I wanted to write a programme where i will create multi level child processes. With single parent and single child.
example: Parent->child1->child2->child3. like that.
See image here
But the problem is I want to take input from terminal how many child processes will be created (single parent - single Child processes).
So How Can I modify that Nested if statement to some loop such that it will create child processes as i wanted it to be.
so Here goes My code
#include<stdio.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main() {
int a, b;
{
if(fork() == 0)
{
printf("child my pid is %d ppid is %d\n",getpid(),getppid());
if(fork()== 0)
{
printf("child my pid is %d ppid is %d\n",getpid(),getppid());
if(fork()== 0)
{
printf("child my pid is %d ppid is %d\n",getpid(),getppid());
}
}
}
else
printf("father my pid is %d ppid is %d\n",getpid(),getppid());
}
for(int i=0;i<3;i++)
wait(NULL);
return 0;
}
OUTPUT GOES HERE:
father my pid is 4496 ppid is 3621
child my pid is 4497 ppid is 4496
child my pid is 4498 ppid is 4497
child my pid is 4499 ppid is 4498
Thanks It's working finally.

Just loop it:
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <assert.h>
int main(int argc, char *argv[])
{
assert(argc == 2);
int num = atoi(argv[1]);
for (int i = 0; i < num; ++i) {
int child;
switch ((child = fork())) {
case 0:
printf("child my pid is %d ppid is %d\n", getpid(), getppid());
break;
case -1:
fprintf(stderr, "fork failed\n");
break;
default:
printf("father my pid is %d ppid is %d and i just created %d\n",getpid(), getppid(), child);
i = num; // break of loop
break;
}
}
wait(NULL);
return 0;
}
#edit:
The break of loop was in the wrong place. Now the process creates a tree of processes as intended:
Compiled the code using gcc and run:
$ ./a.out 5
father my pid is 21893 ppid is 21640 and i just created 21894
child my pid is 21894 ppid is 21893
father my pid is 21894 ppid is 21893 and i just created 21895
child my pid is 21895 ppid is 21894
father my pid is 21895 ppid is 21894 and i just created 21896
child my pid is 21896 ppid is 21895
father my pid is 21896 ppid is 21895 and i just created 21897
child my pid is 21897 ppid is 21896
father my pid is 21897 ppid is 21896 and i just created 21898
child my pid is 21898 ppid is 21897
The program:
starts as pid 21893
creates child with pid 21894
child 21894 creates child 21895
child 21895 creates child 21896
child 21896 creates child 21897
child 21907 creates child 21898

Related

Process and child creation by forking: unexplainable behaviour

I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
for(int i=0;i<3;i++)
{
int cpid=fork();
if(cpid==0)
printf("I am a child with id %d, and my parent is %d\n",getpid(),getppid());
else
printf("I am a parent with id %d\n",getpid());
}
}
I am trying to form a process tree. The output is:
I am a parent with id 9494
I am a parent with id 9494
I am a child with id 9495, and my parent is 9494
I am a parent with id 9494
I am a child with id 9496, and my parent is 9494
I am a parent with id 9495
I am a parent with id 9496
I am a parent with id 9495
I am a child with id 9498, and my parent is 9495
I am a parent with id 9498
I am a child with id 9499, and my parent is 3004
I am a child with id 9497, and my parent is 3004
I am a child with id 9500, and my parent is 3004
I am a child with id 9501, and my parent is 3004
I cannot figure out where is the process with id 3004 coming in. How many total processes are created as a result of this code? What will be the final process tree? I am beginner.
I'll help with the mystery of process 3004. The rest should be reasonably easy to figure out on your own (you might want to add cpid to the second printf() to help with that).
I am a child with id 9499, and my parent is 3004
What happened here is that the original parent of process 9499 had died before 9499 had a chance to call getppid(). When the parent of a process dies, that process gets re-parented. In your case, the new parent's pid is 3004. This process is not part of the process tree created by your program (it probably sits somewhere above it in the overall process tree), so you don't see a "I am a parent with id" for it.
Here is some relevant reading: process re-parenting: controlling who is the new parent.
Try this piece of code.
The output of this code will explain alot more things to you. Some of the processes print their respective printf function after their parent process died. These processes(orphan process) are adopted by some other processes. That could be the reason for a peculiar pid being printed by printf function. Also, there is a race-condition between creation of processes and printing of their respective pid which can be seen in the output of the code below.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
printf("Main\n");
for(int i=0;i<3;i++) {
printf("Loop index - %d and pid is - %d\n", i, getpid());
int cpid=fork();
if(cpid==0)
printf("I am a child with id %d, and my parent is %d with loop index - %d\n",getpid(),getppid(), i);
else
printf("I am a parent with id %d and with loop index - %d\n",getpid(), i);
}
printf("Terminated - %d\n", getpid());
return 0;
}

Why does PPID change?

This is my code:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main() {
pid_t pid;
int status;
if ((pid = fork()) < 0) {
printf("Fork failed.");
} else if (pid == 0) {
printf("CHILD:\nPID: %d, PPID: %d, UID: %d\n", pid, getppid(), getuid());
} else {
wait(&status); //wait for child to terminate
printf("PARENT:\nPID: %d, PPID: %d, UID: %d\n", pid, getppid(), getuid());
}
return 0;
}
This is the output:
CHILD:
PID: 0, PPID: 4309, UID: 1000
PARENT:
PID: 4310, PPID: 3188, UID: 1000
Why is 4309 the PPID of the child? Shouldn't it be 4310?
Thnak you.
You didn't print out the parent's PID in the parent code, so you have nothing to compare it to. fork() returns the child's PID to the parent. In your example it appears that the parent has PID 4309 and the child 4310.

How can you make a parent process display PID of child instead of value variable?

In linux how can I make a parent process display the PID of a child process rather than the value variable?
Your chance to get the child PID is while you fork.
Python:
import os
child_pid = os.fork()
if child_pid == 0:
print "This is the child, my pid is", os.getpid()
else:
print "This is the parent, my child pid is", child_pid
C:
pid_t child_pid = fork();
if (child_pid == 0) {
printf("This is the child, my pid is %d\n", getpid());
}
else {
printf("This is the parent, my child pid is %d\n", child_pid);
}

second call prctl() dont work

I try write program, which realize next idea:
After start, program using fork() and:
parent process stopped on function wait() (for waiting death child process);
child process use prctl(PR_SET_PDEATHSIG, SIGHUP), and setup signal handler (It's helps detect parent death);
After death any process, program use fork() again.
void forking_process() {
pid_t id;
printf("forking_process is called!\n");
if (id = fork()) {
parent_process_operation();
} else {
child_process_operation();
}
}
void parent_process_operation() {
int status = 0;
printf("It's parent process! Pid = %d\n", (int)getpid());
pid_t chid = wait(&status);
printf("Terminated child process with PID = %d\n", chid);
inform_about_parent_death(status);
}
void child_process_operation() {
printf("It's child process! pid = %d, ppid = %d\n",
(int)getpid(), (int)getppid());
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = inform_about_parent_death;
if (sigaction(SIGHUP, &sa, NULL))
fprintf(stderr, "sigaction error\n");
prctl(PR_SET_PDEATHSIG, SIGHUP);
while(1) {
printf("."); fflush(stdout);
sleep(1);
}
}
void inform_about_parent_death(int i) {
printf("Process is dead. Restart!\n");
forking_process();
}
int main (void) {
forking_process();
return EXIT_SUCCESS;
}
If I run this application, and in another terminal kill child process - then will create child process.
If I kill the parent process once, - signal handler started and call fork().
If I again kill the parent process, - signal handler not responded.
That is - prctl() in first process work, but prctl() in second child process don't work.
Why it is happen? How I can correct it's program?

ptrace'ing of parent process

Can child process use the ptrace system call to trace its parent?
Os is linux 2.6
Thanks.
upd1:
I want to trace process1 from "itself". It is impossible, so I do fork and try to do ptrace(process1_pid, PTRACE_ATTACH) from child process. But I can't, there is a strange error, like kernel prohibits child from tracing their parent processes
UPD2: such tracing can be prohibited by security policies. Which polices do this? Where is the checking code in the kernel?
UPD3: on my embedded linux I have no errors with PEEKDATA, but not with GETREGS:
child: getregs parent: -1
errno is 1, strerror is Operation not permitted
errno = EPERM
This question really interested me. So I wrote some code to try it out.
Firstly keep in mind, that when tracing a process, the tracing process becomes a parent for most purposes, except in name (i.e. getppid()). Firstly, a snippet of the PTRACE_ATTACH section of the manual is helpful:
PTRACE_ATTACH
Attaches to the process specified in pid, making it a traced
"child" of the calling process; the behavior of the child is as
if it had done a PTRACE_TRACEME. The calling process actually
becomes the parent of the child process for most purposes (e.g.,
it will receive notification of child events and appears in
ps(1) output as the child's parent), but a getppid(2) by the
child will still return the PID of the original parent. The
child is sent a SIGSTOP, but will not necessarily have stopped
by the completion of this call; use wait(2) to wait for the
child to stop. (addr and data are ignored.)
Now here is the code I wrote to test and verify that you can in fact ptrace() your parent (you can build this by dumping it in a file named blah.c and running make blah:
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ptrace.h>
int main()
{
pid_t pid = fork();
assert(pid != -1);
int status;
long readme = 0;
if (pid)
{
readme = 42;
printf("parent: child pid is %d\n", pid);
assert(pid == wait(&status));
printf("parent: child terminated?\n");
assert(0 == status);
}
else
{
pid_t tracee = getppid();
printf("child: parent pid is %d\n", tracee);
sleep(1); // give parent time to set readme
assert(0 == ptrace(PTRACE_ATTACH, tracee));
assert(tracee == waitpid(tracee, &status, 0));
printf("child: parent should be stopped\n");
printf("child: peeking at parent: %ld\n", ptrace(PTRACE_PEEKDATA, tracee, &readme));
}
return 0;
}
Note that I'm exploiting the replication of the parent's virtual address space to know where to look. Also note that when the child then terminates, I suspect there's an implicit detach which must allow the parent to continue, I didn't investigate further.
Yes it is possible...
Even GETREGS works.
Checked on x86
(based on Matt Joiner code, thanks him)
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/user.h>
int main()
{
pid_t pid = fork();
// assert(pid != -1);
int status;
long readme = 0;
struct user_regs_struct regs;
if (pid)
{
readme = 42;
printf("parent: child pid is %d\n", pid);
assert(pid == wait(&status));
printf("parent: child terminated?\n");
assert(0 == status);
}
else
{
pid_t tracee = getppid();
printf("child: parent pid is %d\n", tracee);
sleep(1); // give parent time to set readme
assert(0 == ptrace(PTRACE_ATTACH, tracee));
assert(tracee == waitpid(tracee, &status, 0));
printf("child: parent should be stopped\n");
printf("child: peeking at parent: %ld\n", ptrace(PTRACE_PEEKDATA, tracee, &readme, NULL));
printf("Regs was %p, %p, %p, %p; &status is %p \n", regs.eax, regs.ebx, regs.ecx, regs.edx, &status);
printf("child: getregs parent: %ld\n", ptrace(PTRACE_GETREGS, tracee, NULL, &regs));
printf("Regs is %p, %p, %p, %p; &status is %p \n", regs.eax, regs.ebx, regs.ecx, regs.edx, &status);
}
return 0;
}
result:
child: parent pid is 1188
parent: child pid is 1189
child: parent should be stopped
child: peeking at parent: 42
Regs was (nil), (nil), (nil), (nil); &status is 0xbfffea50
child: getregs parent: 0
Regs is 0xfffffe00, 0xffffffff, 0xbfffea50, (nil); &status is 0xbfffea50
parent: child terminated?

Resources