У меня есть следующий код в модуле ядра, который просматривает дерево процессов и печатает имена процессов и идентификаторы вплоть до процесса инициализации:
// 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 и затем запускаете событие.Я не уверен, что именно происходит, но машина зависает.Я предполагаю, что ядру не хватило места в стеке, он вышел из OOM и выстрелил сам?
Мне интересно, как лучше всего справиться с этим делом.Я вижу несколько вариантов:
1) прекратить обход дерева процессов после N процессов
2) прекратить обход после того, как какой-нибудь массив символов (который в конечном итоге будет напечатан) заполнен
3) использовать goto
вместо рекурсивной функции, и все же соблюдать новое правило из опций # 1 и # 2
4) использовать какой-то другой нерекурсивный метод, который вы сформулируетедля меня
Это происходит в пространстве ядра, поэтому не самая гостеприимная среда.Кто-нибудь может дать какие-либо указания относительно наилучшего подхода для этого?