How to Obtain Youngest Child's PID from task_struct - c

I'm working on a project that involves writing a new system call for Linux 3.18.20. This system call is supposed to store various information about the currently running process in a newly defined struct.
One of the fields of the struct is the PID of the process's youngest child, and I've been searching for information about this in the struct task_struct, as defined here: http://lxr.free-electrons.com/source/include/linux/sched.h. I've been testing my new system call, and I can't seem to find the appropriate PID value from the struct list_head children.
My test function involves forking a child, storing the return value of fork, and comparing it to the value I get from doing various things in the parent's task_struct. I got the parent's task_struct, and I tried all of the following macros for struct list_head to get the correct PID. None of them have been correct.
printk("list_next_entry pid = %d\n", list_next_entry(task, children)->pid);
printk("list_prev_entry pid = %d\n", list_prev_entry(task, children)->pid);
printk("list_entry pid = %d\n", list_entry(&task->children, struct task_struct, children)->pid);
printk("list_first_entry pid = %d\n", list_first_entry(&task->children, struct task_struct, children)->pid);
printk("list_last_entry pid = %d\n", list_last_entry(&task->children, struct task_struct, children)->pid);
Is this even close to the correct way to try to find the youngest child of the parent process? How can I find a process's youngest child's PID from that process's task_struct?

As comments to fields in task_struct note, children is
list of my children
and siblings is
linkage in my parent's children list
So pointer to the first children task can be requested using
list_first_entry(&task->children, struct task_struct, siblings)

One process can get the youngest process pid from it's last fork(2) system call it made. You'll have to patch the clone(2) system call (as it's the base for al fork calls in linux) and store the pid of the returning process in the u-area (or whatever its called in linux kernel) so you can get it from there when the user calls your system call.

Related

Get Process Info (Current proc, parent proc, oldest child proc)

I have an exercise about adding a system call in the Linux kernel, but I'm struggling to implement it. Below is the description:
The main part of this assignment is to implement a new system call that lets the user determine the information about both the parent and the oldest child process. The information about the processes' information is represented through the following struct:
struct procinfos{
long studentID;
struct proc_info proc;
struct proc_info parent_proc;
struct proc_info oldest_child_proc;
};
Where proc_info is defined as follows:
struct proc_info{
pid_t pid;
char name[16];
};
procinfos contains information of three processes:
proc, the current process or process with PID
parent_proc, the parent of the first process
oldest_child_proc, the oldest child process of the first process
The processes' information is stored in the struct proc_info and contains:
pid, the pid of the process
name, the name of the program which is executed
The prototype of our system call is described below:
To invoke get_proc_info system call, the user must provide the PID of the process or −1 in the case of the current process. If the system call finds the process with the given PID, it will get the process' information, put it in output parameter *info, and return 0. However, if the system call cannot find such a process, it will return
EINVAL.
#include <linux/kernel.h>
#include <unistd.h>
struct procinfos{
long studentID;
struct proc_info proc;
struct proc_info parent_proc;
struct proc_info oldest_child_proc;
};
struct proc_info{
pid_t pid;
char name[16];
};
asmlinkage long sys_get_proc_info(pid_t pid, struct proinfos *info){
// TODO: implement the system call
}
HINT:
To find the current process: look at arch/x86/include/asm/current.h or for simple use macro current (current -> pid).
To find info about each process, look at include/linux/sched.h.
To after the trimming process the time to build the kernel is reduced to about 10 minutes but it is till a long time to compile. To make to the development of system call as fast as possible, you can use kernel module to test the system call represented as a module in advance (Appd B).
How to implement this system call?
since I can't help you much about this, let me give you some hints how to do this:
You can get most of the information of each process when look at the task_struct datatype in include/linux/sched.h. "current" is also a pointer of task_struct type, and you can extract some useful information from a task_struct. For example:
current->pid give you the ID of the process
current->parent give you the parent of the process;parent is also a pointer of task_struct type
current->comm give you the name of the process, as an char array
current->children give you a list of children of a process. It's a list_head data type, implemented as a double linklist. You need to find another way to access this data type. Try to find in scripts/kconfig/list.h

How does getpgid() work?

I'm trying to get the pid, the ppid and the pgid
and no matter what I do getpgid(pid) always gives me the pid.
At first, I was using it like this:
printf("PGID: %d", getpgid());
Then I realized, getpgid was taking a pid as argument so I did this:
printf("PGID: %d", getpgid(getpid()));
But this is still giving me the same number as the pid...
So I tried this:
pid_t pid;
pid = getpid();
printf("PGID: %d", getpgid(pid));
And this still doesn't work... Any idea why?
PS: I'm a beginner in c.
The process group leader is always the one that has pid == pgid, so perhaps you are making always the same test (on a process group leader) and this is the reason of getting always the same pgid as the pid of the process. When a process becomes a group leader, the kernel assigns it it's own pid as the pgid, so perhaps you are always getting that if you are checking in only one process. Bash uses process groups to distinguish background jobs and do job control, so every command you execute from a bash(1) shell will have a new process group and one of these processes (the only one if you only launched one process) will have the same the pgid and the pid of one of the processes of the job you are requesting.
The reason of this logic (to use the pid of the process group leader as the pgid) is to not have to deal with active process groups as no more groups than processed can be in the system... so when a new group id is needed the nearest process available is the own process that triggers the new process group creation, so assigning its own pid as pgid is no harmful.
For a simple example... just try the same program you used to demonstrate the pid and pgid values in a long pipe by piping them (you should try to print the output to stderr instead of stdout or all the outputs will get lost in the input buffer of the next process in the pipe):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int pid = getpid();
fprintf(stderr, "pid=%d; pgid=%d\n", pid, getpgid(pid));
exit(EXIT_SUCCESS);
}
and then
$ testpgid | testpgid | testpgid
pid=3819; pgid=3819
pid=3820; pgid=3819
pid=3821; pgid=3819
$ testpgid | testpgid | testpgid
pid=3833; pgid=3833
pid=3835; pgid=3833
pid=3834; pgid=3833
getpid() returns the process ID of the current process.
When a process is running, the kernel schedules its runtime - especially it assigns a PID to it - such information is stored inside the kernel address space, in data structures (e.g. inside a task struct).
Thus, when a process calls the getpid() system call, the kernel just has to look in the task structure of the calling process.
It is a group ID of the process specified by pid.
Suppose if we consider pid as zero then the ID of the current process is used in it. getpgrp() and getpgid(0) are equivalent to each other.
e.g. pid_t getpgid(pid_t pid);

Determining if a process is a child or parent process (not using return value of fork)

How to write a programm to show whether it's a child or parent process after the fork() is used?
I need to find other way then checking the return value of fork() or getpid() function.
I know e.g. that process resource utilizations (getrusage(2)) and CPU time counters (times(2)) are reset to zero in the child. How i can use for example that knowledge (or other child-parents differences) to determine my problem?
Thank you for your help!
Setup a signal handler for SIGCHLD in one of the processes and end the other one. If the SIGCHLD handler gets called you know the child died. If not the parent died.
Another (less distructive) way it to call wait(). If it returns ECHLD no child is around, thus the calling process is the child. If it blocks, at least one child is around, thus the calling process is the parent.
Or call waitpid() with PID of the other process. The same logic on the result as for wait() applies.
You could exploit the fact that the parent will be a process group leader (and thus its pid will be the same as its process group id) while the child will be a member of that process group and thus its pid will be different from the process group id:
#include <stdio.h>
#include <unistd.h>
main(int argc, char **argv) {
char *self = NULL;
fork(); /* looking at return value would be cheating */
int pid = getpid();
int pgid = getpgid(0);
if (pid == pgid)
self = "Parent";
else
self = "Child";
printf("%s pid = %d pgid = %d\n", self, pid, pgid);
}
Running yields:
$ ./pgid
Parent pid = 29400 pgid = 29400
Child pid = 29401 pgid = 29400
This does of course still use getpid() but not in the same way you describe above.
On Linux, you might also use proc(5). The process of pid 1234 is described by the directory /proc/1234/ and you could read sequentially and parse the /proc/1234/status pseudo-file to get all that information.
To understand a bit more, read the proc(5) man page, then type
cat /proc/self/status
cat /proc/$$/status
cat /proc/self/maps
cat /proc/$$/maps
in a terminal, and try to understand the output. You might parse it programmatically (e.g. with  FILE*f = fopen("/proc/1234/status","r"); then do some fgets or fscanf on f; then fclose(f);)

C/C++ program to kill all child processes of a parent process in UNIX?

I have a function which takes input parameter as PID.
e.g .
bool KillProcessTree (int ParentPID)
{
}
Now I want to write the definition of the above function, which will 1st get all the child processes and then kill them.
Is there any API in Unix which will take parent PID and will return the number of child processes created by the parent process?
There is no standard Unix API to retrieve the list of child processes of a given process.
You can list all the processes on the system with their parent process, and build the process tree from that. The portable way to do this is to run the command
ps -e -o ppid= -o pid=
and parse the output (popen followed by a loop of scanf("%ld %ld\n") will do). Store the data as a finite map from PPID to PID, then walk the tree to collect the list of descendants of the process you're interested in.
If any of the processes concerned forks or exits during your processing, you may miss it. If you're unlucky, a process may exit and its PID may get reused while you're doing all this. Also, if process P forks a child process Q which forks a grandchild R, and then Q exits, R's PPID will be set to 1, so you won't detect that R was originally a descendant of P.
In a nutshell: whatever your problem is, this is very probably the wrong approach.
Unix has a feature to deal with this: process groups. There's a good chance that process groups are the answer to the problem you're trying to solve. You can atomically send signal signal_number to all the processes in a process group with kill(-pgid, signal_number).
You should arrange for all the processes you want to kill to belong to the same process group, and for the processes you don't want to kill not to belong to that process group. Make the parent process call setsid or setpgid, then kill the process group.
I would simply store all the child pids when fork(), in an array of pid_t in the parent process.
after then, kill all by looping that array.
pid_t all_child[10]; // you should not define a fixed length array, you can use pointer.
if((pid = fork()) == 0)
{
//child processes
}
else
{
//parent process
all_pid[counter] = pid;
}
When killing,
for( i = 0; i < counter; i++)
{
kill(all_pid[i], SIGTERM);
}

Using fork() in C?

I have been asked this question for homework, and am having trouble figuring it out. If anyone can help me i would really appreciate it.
What Linux library function is like a fork(), but the parent process is terminated?
I'm fairly certain that whoever assigned you this homework is looking for the exec() family of functions, from the POSIX API header <unistd.h>, because there is nothing else that more closely resembles the sort of functionality you describe.
The exec() family of functions executes a new process and replaces the currently running process address space with the newly executed process.
From the man page:
The exec() family of functions replaces the current process image with
a new process image.
It's not exactly the same as "terminating" the parent process, but in practice it results in a similar situation where the parent process address space is erased (replaced) with the address space of the child process.
What Linux library function is like a fork(), but the parent process
is terminated?
The parent process should not terminate because , it must wait for the child processes to finish executing , after which they will be in a state called "zombie state", now it is the responsibility of the parent to clean up the leftovers of the child process. The parent process can terminate without cleaning up the child processes, but then, it is not a proper way to do it, as the exit status of the child processes should be collected and checked by the parent process.
Here is an example, to demonstrate , what i just said...
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
pid_t cpid = 1 ;
int status;
cpid = fork();
// Load a application to the child using execl() , and finish the job
printf("Parent waiting for child to terminate\n");
int wait_stat = waitpid(-1,&status,0); // Parent will hang here till all child processes finish executing..
if (wait_stat < 0)
{
perror("waitpid error");
exit(-1);
}
// WIFEXITED and WEXITSTATUS are macros to get exit status information, of the child process
if (WIFEXITED (status))
{
printf("Child of id %u cleaned up\n",wait_stat);
printf("Exit status of application = %u\n",WEXITSTATUS(status));
}
}

Resources