我看到接受的答案是使用递归。即使代码更简单,在内核代码中编写递归函数仍然是一个非常糟糕的主意。内核的可用堆栈大小有限,递归函数很容易溢出并使一切崩溃。您应该迭代地实现 DFS/BFS:维基百科页面(DFS,BFS)有解释和代码示例。
struct
这是一个使用支持作为队列的简单 DFS 和 BFS 实现(在内核 5.10 上测试)。由于迭代 DFS 和 BFS 之间的唯一区别是分别将新元素推送到队列的头部或尾部,我只是实现了两者,您可以通过简单地添加#define BFS
.
// Uncomment to use BFS instead of DFS
// #define BFS
static void dump_children_tree(struct task_struct *task) {
struct task_struct *child;
struct list_head *list;
struct queue *q, *tmp;
#ifdef BFS
struct queue **tail;
#endif
pid_t ppid;
q = kmalloc(sizeof *q, GFP_KERNEL);
if (!q)
goto out_nomem;
q->task = task;
q->next = NULL;
#ifdef BFS
tail = &q->next;
#endif
while (q) {
task = q->task;
#ifndef BFS
tmp = q;
q = q->next;
kfree(tmp);
#endif
rcu_read_lock();
ppid = rcu_dereference(task->real_parent)->pid;
rcu_read_unlock();
pr_info("Name: %-20s State: %ld\tPID: %d\tPPID: %d\n",
task->comm,
task->state,
task->pid,
ppid
);
list_for_each(list, &task->children) {
child = list_entry(list, struct task_struct, sibling);
get_task_struct(child);
tmp = kmalloc(sizeof *tmp, GFP_KERNEL);
if (!tmp)
goto out_nomem;
tmp->task = child;
#ifdef BFS
tmp->next = NULL;
*tail = tmp;
tail = &tmp->next;
#else // DFS
tmp->next = q;
q = tmp;
#endif
}
put_task_struct(task);
#ifdef BFS
tmp = q;
q = q->next;
kfree(tmp);
#endif
}
return;
out_nomem:
while (q) {
tmp = q;
q = q->next;
kfree(tmp);
}
}
注意:上述函数假定get_task_struct()
已在传递的 上调用,并在返回之前task
自动调用它。put_task_struct()