Efficient way to find task_struct by pid
Solution 1:
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);
Solution 2:
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);
Solution 3:
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);
PS: for more information on API's you can look at kernel/pid.c
Note that since get_pid_task()
increases the reference count of the struct task_struct
by one, you need to call put_task_struct()
to reduce the refcount of the task by one.
Also, find_get_pid
calls get_pid
will increment the reference count of the struct pid
by one, so don't forget to put_pid()
when you no longer need it as well.