Gibt es eine effiziente Möglichkeit, die zu finden task_struct
für eine angegebene PID, ohne Iteration durch die task_struct
aufführen?
Effiziente Möglichkeit, task_struct nach PID zu finden
zer0stimulus
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
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
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.