我在一个内核模块中有以下代码,它遍历进程树并打印进程名称和uids,直到init进程:
// recursivly walk the task's parent until we reach init
void parent_task_walk(struct task_struct *task) {
struct task_struct *parent;
char filename[MAX_FILE_LEN];
if (task && task->mm) {
parent = get_task_parent(task);
printk("%s (uid:%d)", exe_from_mm(task->mm, filename, MAX_FILE_LEN),
get_task_uid(task));
if (parent && task->pid != 1) {
printk(", ");
parent_task_walk(parent);
}
}
}注意:我使用了一些引用真实内核函数的宏,因为这是一个跨越多个版本的内核模块。源代码在这个文件中:https://github.com/cormander/tpe-lkm/blob/319e1e29ea23055cca1c0a3bce3c865def14d3d2/core.c#L61
输出结果如下所示:
/bin/bash (uid:500), /usr/sbin/sshd (uid:500), /usr/sbin/sshd (uid:0), /usr/sbin/sshd (uid:0), /sbin/init (uid:0)
这是一个递归函数。正如您可以想象的那样,当您启动200个bash shell并触发事件时,事情会变得很糟糕。我不确定到底发生了什么,但是机器死机了。内核耗尽了堆栈空间,我猜是不是发生了OOM,然后自己射杀了自己?
我想知道处理这个案子最好的方法是什么。我看到了几个选项:
1)在N个进程后停止遍历进程树
2)在某个字符数组(最终将被打印)已满后停止遍历
3)使用goto而不是递归函数,但仍然遵循选项#1和#2中的新规则
4)使用其他一些非递归方法,您将为我阐述这些方法
这是在内核空间发生的,所以不是最友好的环境。有没有人能给出一些建议,说明解决这个问题的最佳方法?
发布于 2011-11-22 05:51:05
实际上,您的内核崩溃很可能是因为您正在使用递归函数。
你可以使用一个非常简单的循环来代替你的递归函数。你来自函数式编程的世界吗?while循环在C中是标准的,但是如果你真的想使用goto,你可以...;)这里是使用循环的代码。
void parent_task_walk(struct task_struct* task)
{
struct task_struct *parent = NULL;
char filename[MAX_FILE_LEN];
while (task && task->mm) {
parent = get_task_parent(task);
printk("%s (uid:%d)",
exe_from_mm(task->mm, filename, MAX_FILE_LEN),
get_task_uid(task));
if (parent && task->pid != 1)
printk(", ");
task = parent;
}
}https://stackoverflow.com/questions/8207833
复制相似问题