GNU/Linux >> Znalost Linux >  >> Linux

Efektivní způsob, jak najít task_struct pomocí pid

Existuje lepší způsob, jak získat instanci task_struct z modulu. Vždy se snažte použít funkce wrapper/pomocné rutiny, protože jsou navrženy tak, že pokud programátor ovladačů něco vynechá, jádro se může postarat samo. Např. - zpracování chyb, kontroly podmínek atd.

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

taskp = get_pid_task(pid, PIDTYPE_PID);

a získat PID typu pid_t. musíte použít níže uvedené API -

find_get_pid(pid_no);

Nemusíte používat "rcu_read_lock() “ a „rcu_read_unlock() " při volání těchto rozhraní API, protože "get_pid_task() " interně volá rcu_read_lock(),rcu_read_unlock() před voláním "pid_task() " a správně zpracovává souběžnost. Proto jsem výše řekl, že vždy používejte tento druh obalu.

Úryvek funkce get_pid_task() a find_get_pid() níže :-

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

V modulu jádra můžete použít funkci wrapper také následujícím způsobem -

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

PS:Pro více informací o API se můžete podívat na kernel/pid.c


Pokud chcete najít task_struct z modulu find_task_by_vpid(pid_t nr) atd. nebudou fungovat, protože tyto funkce nejsou exportovány.

V modulu můžete místo toho použít následující funkci:

pid_task(find_vpid(pid), PIDTYPE_PID);

Nikdo nezmínil, že pid_task() funkce a ukazatel (který z něj získáte) by měl být použit v kritické sekci RCU (protože používá datovou strukturu chráněnou RCU). Jinak může existovat CHYBA bez použití po použití .
Existuje mnoho případů použití pid_task() ve zdrojích linuxového jádra (např. v posix_timer_event() ).
Například:

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!) */

Zjistěte více o RCU API na Kernel.org

P.S. můžete také použít speciální funkce API, jako je find_task_by_pid_ns() a find_task_by_vpid() pod rcu_read_lock() .

První je pro vyhledávání v konkrétním jmenném prostoru:

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

Druhý je pro vyhledávání v jmenném prostoru current úkol.


Co je špatného na použití jednoho z následujících?

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. Jak najdu ID procesu v Ubuntu?

  2. Příklady návrhu efektivního síťového serveru, napsané v C

  3. najít a odstranit soubory s mezerou pomocí příkazu find v Linuxu

  1. Rekurzivní Grep vs Find / -type F -exec Grep {}; Co je efektivnější/rychlejší?

  2. Nejúčinnější způsob kopírování souboru v Linuxu

  3. adb:Najděte PID z prostředí adb

  1. Jaký je nejlepší způsob, jak spočítat počet souborů v adresáři?

  2. Jak zjistit, zda systém podporuje Intel Amt?

  3. Existuje způsob, jak zkontrolovat, zda existují symbolické odkazy směřující do adresáře?