Linux 通过pid查找task_struct的有效方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8547332/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Efficient way to find task_struct by pid
提问by zer0stimulus
Is there an efficient way of finding the task_struct
for a specified PID, without iterating through the task_struct
list?
是否有一种有效的方法可以找到task_struct
指定 PID 的 ,而无需遍历task_struct
列表?
采纳答案by j?rgensen
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);
回答by mdd
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.
如果你想task_struct
从一个模块中找到,find_task_by_vpid(pid_t nr)
等等都不会工作,因为这些函数没有被导出。
In a module, you can use the following function instead:
在模块中,您可以改用以下函数:
pid_task(find_vpid(pid), PIDTYPE_PID);
回答by red0ct
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). Otherwisethere 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 临界区中使用pid_task()
函数和指针(您从中获得)(因为它使用 RCU 保护的数据结构)。否则会出现use-after-free BUG。
有很多在 Linux 内核源代码中使用的情况(例如在 中)。
例如: pid_task()
posix_timer_event()
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
从Kernel.org了解有关 RCU API 的更多信息
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()
.
PS你也可以只使用特殊的API功能,如find_task_by_pid_ns()
和find_task_by_vpid()
下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.
第二个用于搜索current
任务的命名空间。
回答by shashank arora
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.
有一种更好的方法可以从模块中获取 task_struct 的实例。总是尝试使用包装函数/帮助程序,因为它们的设计方式是如果驱动程序程序员遗漏了什么,内核可以自行处理。例如 - 错误处理、条件检查等。
/* 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 -
并获取 pid_t 类型的 PID。您需要使用以下 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.
在调用这些 API 时,您不需要使用“ rcu_read_lock()”和“ rcu_read_unlock()”,因为“ get_pid_task()”在调用“ pid_task()”之前会在内部调用 rcu_read_lock(),rcu_read_unlock()并正确处理并发。这就是为什么我在上面说过总是使用这种包装器。
Snippet of get_pid_task() and find_get_pid() function below :-
下面的 get_pid_task() 和 find_get_pid() 函数的片段:-
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
PS:有关 API 的更多信息,您可以查看 kernel/pid.c