问题描述
我正在尝试编写一个函数,该函数对除主进程外的子进程的 pid 进行递归求和(如果 C 是 B 的儿子,而 B 是 A 的儿子,那么我想要 pid(B)+pid(C))
所以我写道:
int get_children_sum_internal(const struct task_struct *current) {
int result = current->pid;
struct list_head *pos;
list_for_each(pos,¤t->children)
{
result+=pos->pid;
}
return result;
}
asmlinkage int get_children_sum(void) {
if (list_empty(¤t->children))
{
return;
}
return get_children_sum_internal(current);
}
但是我收到一个错误,因为 current 来自 task_list 类型而 pos 来自 list_head 类型。我该如何解决这个问题?
解决方法
您遇到的一个问题(可能是也可能不是唯一的问题)是,在您的 list_for_each
中,pos
的类型是 list_head
,但随后您将其用作task_struct
通过访问 pos->pid
。您需要首先使用 task_struct
函数获取包含 pos
的封装子 container_of()
。
从定义 include/linux/kernel.h
的 container_of()
开始:
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*
*/
#define container_of(ptr,type,member) ({
因此,在您的情况下,我认为执行 container_of(pos,task_struct,sibling)
将返回孩子的 task_struct
,然后您可以访问其 pid
。请注意,我使用了 sibling
而不是 children
,因为在这一步,观点是从孩子的角度来看的。从孩子的角度来看,它位于兄弟列表中,从父母的角度来看,它是它的孩子列表。 (有关更多说明,请参阅 this)。
更新:OP 编辑了帖子中的代码以使用 list_entry
,而之前使用 pid 访问
pos->pid
。 list_entry
函数是另一种获取封装对象的有效方法。 Behind the scenes,list_entry
无论如何都会调用 container_of
。