Effiziente Möglichkeit, task_struct nach PID zu finden

Lesezeit: 4 Minuten

Benutzeravatar von zer0stimulus
zer0stimulus

Gibt es eine effiziente Möglichkeit, die zu finden task_struct für eine angegebene PID, ohne Iteration durch die task_struct aufführen?

Was ist falsch daran, eines der folgenden zu verwenden?

extern struct task_struct *find_task_by_vpid(pid_t nr);
extern struct task_struct *find_task_by_pid_ns(pid_t nr,
            struct pid_namespace *ns);

  • Können Sie mir die Bedeutung von v in vpid sagen?

    – Firo

    10. Dezember 2014 um 10:26 Uhr

  • v bedeutet virtuell. es wird in include/linux/sched.h erklärt. Es sieht so aus, als ob es wegen der Sache mit dem “Container” so genannt wurde. (lwn.net/Articles/168093)

    – Chan-Kim

    3. September 2020 um 5:08 Uhr

  • Sie werden nicht mehr zur Verwendung exportiert, denke ich.

    – Roi

    5. Juli um 11:11 Uhr


Wenn Sie die finden möchten task_struct aus einem Modul, find_task_by_vpid(pid_t nr) usw. funktionieren nicht, da diese Funktionen nicht exportiert werden.

In einem Modul können Sie stattdessen die folgende Funktion verwenden:

pid_task(find_vpid(pid), PIDTYPE_PID);

  • Ich habe die obige Funktion getestet und die Kernel-Panik

    – Abdullah

    17. September 2015 um 10:29 Uhr

  • Ich verwende diese Funktion erfolgreich auf Kernel 3.8/x86_64. Könnten Sie eine neue Frage öffnen und weitere Details hinzufügen, wie die Panikmeldung usw.?

    – mdd

    17. September 2015 um 17:45 Uhr

  • schön – das ist die Funktion, die ich gesucht habe! 🙂

    – Chris

    22. Juni 2019 um 12:06 Uhr

Benutzeravatar von shashank arora
shashank arora

Es gibt einen besseren Weg, um die Instanz von task_struct aus einem Modul abzurufen. Versuchen Sie immer, Wrapper-Funktionen/Hilfsroutinen zu verwenden, da sie so konzipiert sind, dass der Kernel sich selbst darum kümmern kann, wenn der Treiberprogrammierer etwas übersehen hat. Für zB – Fehlerbehandlung, Zustandsprüfungen etc.

/* Use below API and you will get a pointer of (struct task_struct *) */

taskp = get_pid_task(pid, PIDTYPE_PID);

und um die PID vom Typ pid_t zu erhalten. Sie müssen die folgende API verwenden –

find_get_pid(pid_no);

Sie brauchen nicht “rcu_read_lock()” und “rcu_read_unlock()” beim Aufrufen dieser APIs, weil “get_pid_task()” ruft intern rcu_read_lock(), rcu_read_unlock() vor dem Aufruf auf “pid_task()” und handhabt Parallelität richtig. Deshalb habe ich oben gesagt, verwenden Sie immer diese Art von Wrapper.

Ausschnitt der Funktion get_pid_task() und find_get_pid() unten:-

struct task_struct *get_pid_task(struct pid *pid, enum pid_type type)
{
    struct task_struct *result;
    rcu_read_lock();
    result = pid_task(pid, type);
    if (result)
        get_task_struct(result);
    rcu_read_unlock();
    return result;
}
EXPORT_SYMBOL_GPL(get_pid_task);

struct pid *find_get_pid(pid_t nr)
{
    struct pid *pid;

    rcu_read_lock();
    pid = get_pid(find_vpid(nr));
    rcu_read_unlock();

    return pid;
}
EXPORT_SYMBOL_GPL(find_get_pid);

In einem Kernel-Modul können Sie die Wrapper-Funktion auch auf folgende Weise verwenden –

taskp = get_pid_task(find_get_pid(PID),PIDTYPE_PID);

PS: Weitere Informationen zu APIs finden Sie unter kernel/pid.c

  • Woher wissen Sie, dass es eine Hilfsfunktion gibt und mehrere Hilfsfunktionen zusammengefügt werden (in Ihrem Beispiel find_get_pid)? get_pid_task(find_get_pid(PID),PIDTYPE_PID);. Ich finde keine Unterlagen dazu.

    – Tan Nguyen

    5. Oktober 2021 um 22:14 Uhr


  • Stattdessen finde ich so etwas wie ps -p $PID, ps -p $PID -o pid,vsz=MEMORY -o user,group=GROUP -o comm,args=ARGS. Was ist das übrigens?

    – Tan Nguyen

    5. Oktober 2021 um 22:19 Uhr

  • da es get_task_struct gibt, das die Nutzung der Aufgabe in get_pid_task erhöht. Es kann erforderlich sein, put_task_struct zu verwenden, um dies wie zuvor zu setzen.

    – Kevin Chan

    11. Juli um 9:23 Uhr

Benutzeravatar von red0ct
red0ct

Niemand hat erwähnt, dass die pid_task() Funktion und die Zeiger (die Sie daraus erhalten) verwendet werden im kritischen Abschnitt der RCU (weil es eine RCU-geschützte Datenstruktur verwendet). Andernfalls Es kann geben Use-after-free BUG.
Es gibt viele Anwendungsfälle pid_task() in Linux-Kernel-Quellen (zB in posix_timer_event()).
Zum Beispiel:

rcu_read_lock();
/* search through the global namespace */
task = pid_task(find_pid_ns(pid_num, &init_pid_ns), PIDTYPE_PID);
if (task)
    printk(KERN_INFO "1. pid: %d, state: %#lx\n",
           pid_num, task->state); /* valid task dereference */
rcu_read_unlock(); /* after it returns - task pointer becomes invalid! */

if (task)
    printk(KERN_INFO "2. pid: %d, state: %#lx\n",
           pid_num, task->state); /* may be successful,
                                   * but is buggy (task dereference is INVALID!) */

Erfahren Sie mehr über die RCU-API unter Kernel.org


PS auch Sie können einfach die speziellen API-Funktionen wie verwenden find_task_by_pid_ns() und find_task_by_vpid() unter dem rcu_read_lock().

Der erste dient zum Durchsuchen des jeweiligen Namensraums:

task = find_task_by_pid_ns(pid_num, &init_pid_ns); /* e.g. init namespace */

Der zweite dient zum Durchsuchen des Namensraums von current Aufgabe.

1432860cookie-checkEffiziente Möglichkeit, task_struct nach PID zu finden

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy