Ходьба по дереву процессов в ядре Linux - PullRequest
1 голос
/ 21 ноября 2011

У меня есть следующий код в модуле ядра, который просматривает дерево процессов и печатает имена процессов и идентификаторы вплоть до процесса инициализации:

// 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) использовать какой-то другой нерекурсивный метод, который вы сформулируетедля меня

Это происходит в пространстве ядра, поэтому не самая гостеприимная среда.Кто-нибудь может дать какие-либо указания относительно наилучшего подхода для этого?

1 Ответ

5 голосов
/ 22 ноября 2011

Действительно, у вас ядро ​​может произойти сбой, потому что вы используете рекурсивную функцию.

Вы можете просто использовать очень простой цикл вместо рекурсивной функции ... Вы из мира функционального программирования?Цикл 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;
    }

}
...