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

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

Related

How to Obtain Youngest Child's PID from task_struct

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.

Implementing kernel level threads in xv6

I am trying to implement kernel level threads in xv6.
My main problem at the moment is to understand how the CPU gets its information about the current process and how to modify it to point to the current thread instead.
I know it is somehow linked to this line:
extern struct proc *proc asm("%gs:4");
in proc.h, but I do not fully understand how and why it works.
I found out %gs points to to the line struct cpu *cpu; in the struct cpu (defined at proc.h), and right below that line (+ 4 bytes after the cpu pointer)
the current process of the cpu is stored:
struct proc *proc; // The currently-running process.
so in order to add thread support one should either alter this line to point to the new thread struct instead of process struct or alternatively, add the thread below the "proc" line and perform the following changes:
add in proc.h the following decleration: extern struct thread *thread asm("%gs:8");
change in vm.c, in fucntion "seginit(void)" the line
c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 8, 0); to c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 12, 0); in order to allocate space for the extra thread pointer.

how does current->pid work for linux?

Do I need to include a library?
Can anyone please elaborate in it?
I know is used to get the process id of the current task where is being called from
But I want to printk something with current->pid
printk("My current process id/pid is %d\n", current->pid);
...and is giving me an error
error: dereferencing pointer to incomplete type
You're looking for #include <linux/sched.h>. That's where task_struct is declared.
Your code should work. You are probably missing some header.
current is a per-cpu variable defined in linux/arch/x86/include/asm/current.h (all the code is for the case of x86):
DECLARE_PER_CPU(struct task_struct *, current_task);
static __always_inline struct task_struct *get_current(void)
{
return percpu_read_stable(current_task);
}
#define current get_current()
current points to the task running on a CPU at a given moment. Its type is struct task_struct and it is defined in linux/include/linux/sched.h:
struct task_struct {
...
pid_t pid; // process identifier
pid_t tgid; // process thread group id
...
};
You can browse the code for these files in the Linux Cross Reference:
current.h
sched.h
I think you're looking for the getpid() system call. I don't know what current is though.

I can not understand the kernel internal representation of PID

The Linux kernel uses struct pid to represent PID in kernel space.The C code is below.
struct pid
{
atomic_t count;
/* lists of tasks that use this pid */
struct hlist_head tasks[PIDTYPE_MAX];
int level;
struct upid numbers[1];
};
I can not really understand why the member tasks can represent "the lists of tasks".Since task_struct is the kernel internal representation of task,and one task only uses one task_struct.Why can more than one task share a "struct pid"?
Because more than one task can be part of the same process. Consider, for example, a multi-threaded process using a 1-to-1 threading library like NPTL. It has a single process ID, is a single process, but consists of multiple entities scheduled by the kernel.

Efficient way to find task_struct by pid

Is there an efficient way of finding the task_struct for a specified PID, without iterating through the task_struct list?
What's wrong with using one of the following?
extern struct task_struct *find_task_by_vpid(pid_t nr);
extern struct task_struct *find_task_by_pid_ns(pid_t nr,
struct pid_namespace *ns);
If you want to find the task_struct from a module, find_task_by_vpid(pid_t nr) etc. are not going to work since these functions are not exported.
In a module, you can use the following function instead:
pid_task(find_vpid(pid), PIDTYPE_PID);
There is a better way to get the instance of task_struct from a module.
Always try to use wrapper function/ helper routines because they are designed in such a way if driver programmer missed something, the kernel can take care by own. For eg - error handling, conditions checks etc.
/* Use below API and you will get a pointer of (struct task_struct *) */
taskp = get_pid_task(pid, PIDTYPE_PID);
and to get the PID of type pid_t. you need to use below API -
find_get_pid(pid_no);
You don't need to use "rcu_read_lock()" and "rcu_read_unlock()" while calling these API's because "get_pid_task()" internally calls rcu_read_lock(),rcu_read_unlock() before calling "pid_task()" and handles concurrency properly. That's why I have said above use these kind of wrapper always.
Snippet of get_pid_task() and find_get_pid() function below :-
struct task_struct *get_pid_task(struct pid *pid, enum pid_type type)
{
struct task_struct *result;
rcu_read_lock();
result = pid_task(pid, type);
if (result)
get_task_struct(result);
rcu_read_unlock();
return result;
}
EXPORT_SYMBOL_GPL(get_pid_task);
struct pid *find_get_pid(pid_t nr)
{
struct pid *pid;
rcu_read_lock();
pid = get_pid(find_vpid(nr));
rcu_read_unlock();
return pid;
}
EXPORT_SYMBOL_GPL(find_get_pid);
In a kernel module, you can use wrapper function in the following way as well -
taskp = get_pid_task(find_get_pid(PID),PIDTYPE_PID);
PS: for more information on API's you can look at kernel/pid.c
No one mentioned that the pid_task() function and the pointer (which you obtain from it) should be used inside RCU critical section (because it uses RCU-protected data structure). Otherwise there can be use-after-free BUG.
There are lots of cases of using pid_task() in Linux kernel sources (e.g. in posix_timer_event()).
For example:
rcu_read_lock();
/* search through the global namespace */
task = pid_task(find_pid_ns(pid_num, &init_pid_ns), PIDTYPE_PID);
if (task)
printk(KERN_INFO "1. pid: %d, state: %#lx\n",
pid_num, task->state); /* valid task dereference */
rcu_read_unlock(); /* after it returns - task pointer becomes invalid! */
if (task)
printk(KERN_INFO "2. pid: %d, state: %#lx\n",
pid_num, task->state); /* may be successful,
* but is buggy (task dereference is INVALID!) */
Find out more about RCU API from Kernel.org
P.S. also you can just use the special API functions like find_task_by_pid_ns() and find_task_by_vpid() under the rcu_read_lock().
The first one is for searching through the particular namespace:
task = find_task_by_pid_ns(pid_num, &init_pid_ns); /* e.g. init namespace */
The second one is for searching through the namespace of current task.

Resources