【问题标题】:Linux how to convert task_list to list_head? [closed]Linux如何将task_list转换为list_head? [关闭]
【发布时间】:2021-07-31 21:24:21
【问题描述】:

我正在尝试编写一个函数,对除主进程之外的子进程的 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, &current->children)
    {
        result+=pos->pid;
    }
    return result;
}

asmlinkage int get_children_sum(void) {
    if (list_empty(&current->children))
    {
        return;
    }
    return get_children_sum_internal(current);
}

但我收到一个错误,因为 current 来自 task_list 类型,而 pos 来自 list_head 类型。我该如何解决这个问题?

【问题讨论】:

  • 我认为这不能解决您的问题,您仍然需要在 list_entry 函数中使用 sibling 而不是 children。但是当你运行代码时会发生什么?它是否有效或您是否发现任何错误?
  • 我没有发现任何问题,为什么这仍然是错误的?我正在使用 list_entry
  • @mr_calc 我认为您误解了list_head 结构在内核中的工作方式。有两种思考方式。 1)概念上list_head是什么?它是列表中的一个条目。因此,当您从父进程中获取children 变量时,您实际上是在获取列表中第一个子进程的条目。那么如何从第一个条目中获取列表中的下一个条目? list_for_each 函数集只是通过执行 pos= pos->next 将当前条目 pos 向前移动。但这些只是条目(指针),而不是实际的对象(在本例中为 task_structs)本身。
  • @mr_calc 也尽量不要以显着改变原始问题的方式编辑您的原始帖子。否则,标题、问题和答案会让其他不了解您所做更新的第一次阅读本文的人感到困惑。

标签: c linux process linux-kernel operating-system


【解决方案1】:

您遇到的一个问题(可能是也可能不是唯一的问题)是,在您的 list_for_each 中,pos 的类型为 list_head,但您通过访问 @ 将其用作 task_struct 987654330@。您需要首先使用container_of() 函数获取包含pos 的封装子task_struct

从定义container_of()include/linux/kernel.h

/**
 * 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->pidlist_entry 函数是获取封装对象的另一种有效方法。无论如何Behind the sceneslist_entry 调用container_of

【讨论】:

  • 另外我认为你犯了一个错误,应该是孩子。我正在向父亲发送一个指针,然后遍历它的孩子(为什么我需要它的兄弟姐妹)?
  • @mr_calc children 是任务子级列表的前哨(头)节点。 sibling 是父级子级列表中的非哨兵节点。所以parent_task->children->next 指向第一个孩子的child_task->sibling 节点(如果列表非空)。所以sibling 是传递给container_of 的正确成员。在处理struct list_head 时,使用list_entry() 宏而不是container_of() 宏更为常见,但它们的作用相同。
  • @IanAbbott 我的意思是this one,但我也喜欢你的! :P
  • @mr_calc 兄弟姐妹是他们共同父母的孩子。
  • 与其删除您的问题,您应该在此处投票并回答然后回答提供者
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-24
  • 2017-07-24
  • 2011-04-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多