SAC*_*YAL 5 c linux linux-kernel
内核task_struct如下所示。我对两个成员(子级和同级成员)更感兴趣,因此我从此内核结构中删除了其他元素。
struct task_struct{
// some data elements .
struct list_head children;
/* list of my children */
struct list_head sibling;
/* linkage in my parent's children list */
//some data members
};
Run Code Online (Sandbox Code Playgroud)
“子项”是进程子项的task_struct的双向循环链接列表。如果要从当前进程访问子项,则必须使用宏“ list_for_each”遍历“子项”列表,如下所示:
struct task_struct *task;
struct list_head *list;
list_for_each(list, ¤t->children) {
task = list_entry(list, struct task_struct, sibling); /* task now points to one of current’s children */
}
Run Code Online (Sandbox Code Playgroud)
list_for_each最终将使用下一个子项初始化“ list”。现在,由于我们要遍历子项列表,因此理想情况下,我们应该从“ list”指针中减去“子项”列表的偏移量,以获取当前进程的tast_struct地址。是什么原因导致我们在此处传递“兄弟”,而最终导致具有不同偏移量的另一个列表?。
请注意:这是有效的代码,我要了解的是为什么当应使用children指针计算正确的偏移量并因此计算child的task_struct地址时为什么使用同级。
提前致谢 。
为了使用链接列表来组织数据,struct list_head您必须声明列表根并声明链接的列表条目。根条目和子条目的类型相同 ( struct list_head)。children条目的条目struct task_struct是一个root。sibling的条目struct task_struct是 a list entry。要查看差异,您必须阅读代码,了解使用children和的位置sibling。使用list_for_eachforchildren意味着什么children是 a root。使用list_entryforsibling意味着什么sibling是 a list entry。
您可以在此处阅读有关 Linux 内核列表的更多信息。
问题:我们在这里传递“兄弟”(最终是具有不同偏移量的不同列表)的原因是什么?
回答:
如果列表是这样创建的:
list_add(&subtask->sibling, ¤t->children);
Run Code Online (Sandbox Code Playgroud)
然后
list_for_each(list, ¤t->children)
Run Code Online (Sandbox Code Playgroud)
将初始化列表指针sibling,因此您必须将其用作siblinglist_entry 的参数。这就是linux内核列出API设计的方式。
但是,如果列表是以另一种(错误)方式创建的:
list_add(&subtask->children, ¤t->sibling);
Run Code Online (Sandbox Code Playgroud)
然后你必须以这种(错误的)方式迭代列表:
list_for_each(list, ¤t->sibling)
Run Code Online (Sandbox Code Playgroud)
现在你必须使用children作为参数list_entry。
希望这可以帮助。