GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Effiziente Möglichkeit, task_struct nach PID zu finden

Es gibt einen besseren Weg, um die Instanz von task_struct aus einem Modul zu erhalten. 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 müssen "rcu_read_lock() nicht verwenden " und "rcu_read_unlock() " beim Aufrufen dieser APIs, weil "get_pid_task() " ruft intern rcu_read_lock(), rcu_read_unlock() auf, bevor "pid_task() aufgerufen wird " und handhabt die Nebenläufigkeit 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


Wenn Sie den task_struct finden möchten 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);

Niemand hat erwähnt, dass die pid_task() Funktion und den Zeiger (die Sie daraus erhalten) sollte innerhalb des kritischen Abschnitts der RCU verwendet werden (weil es eine RCU-geschützte Datenstruktur verwendet). Ansonsten es kann einen use-after-free BUG geben .
Es gibt viele Fälle, in denen pid_task() verwendet wird in Linux-Kernel-Quellen (z. B. 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 von Kernel.org

P.S. Sie können auch einfach die speziellen API-Funktionen wie find_task_by_pid_ns() verwenden und find_task_by_vpid() unter 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.


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);

Linux
  1. Wie finde ich die Prozess-ID in Ubuntu?

  2. Effiziente Designbeispiele für Netzwerkserver, geschrieben in C

  3. Gibt es eine Möglichkeit, die Laufzeit des zuletzt ausgeführten Befehls in der Shell zu finden?

  4. Suchen und entfernen Sie Dateien mit Leerzeichen mit dem Befehl find unter Linux

  5. Schnellere Möglichkeit, eine große Anzahl von Dateien zu löschen

So finden Sie einen Prozessnamen mithilfe der PID-Nummer in Linux

So finden Sie den Prozessnamen anhand seiner PID

So finden Sie die PID und PPID eines Prozesses in Linux

Gibt es eine Möglichkeit zu überprüfen, ob symbolische Links auf ein Verzeichnis verweisen?

Die effizienteste Methode zum Kopieren einer Datei unter Linux

adb:Finden Sie PID aus der Adb-Shell