GNU/Linux >> Linux Esercitazione >  >> Linux

Modo efficiente per trovare task_struct tramite pid

C'è un modo migliore per ottenere l'istanza di task_struct da un modulo. Cerca sempre di usare la funzione wrapper/le routine helper perché sono progettate in modo tale che se il programmatore del driver ha perso qualcosa, il kernel può occuparsene da solo. Ad esempio:gestione degli errori, controlli delle condizioni, ecc.

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

taskp = get_pid_task(pid, PIDTYPE_PID);

e per ottenere il PID di tipo pid_t. è necessario utilizzare l'API sottostante -

find_get_pid(pid_no);

Non è necessario utilizzare "rcu_read_lock() " e "rcu_read_unlock() " durante la chiamata di queste API perché "get_pid_task() " chiama internamente rcu_read_lock(),rcu_read_unlock() prima di chiamare "pid_task() " e gestisce correttamente la concorrenza. Ecco perché ho detto sopra usa sempre questo tipo di wrapper.

Frammento della funzione get_pid_task() e find_get_pid() di seguito :-

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 un modulo del kernel, puoi usare la funzione wrapper anche nel modo seguente -

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

PS:per maggiori informazioni sulle API puoi consultare kernel/pid.c


Se vuoi trovare il file task_struct da un modulo, find_task_by_vpid(pid_t nr) ecc. non funzioneranno poiché queste funzioni non vengono esportate.

In un modulo, puoi invece utilizzare la seguente funzione:

pid_task(find_vpid(pid), PIDTYPE_PID);

Nessuno ha detto che il pid_task() funzione e il puntatore (che ottieni da esso) dovrebbe essere usato all'interno della sezione critica RCU (poiché utilizza una struttura dati protetta da RCU). Altrimenti ci possono essere BUG use-after-free .
Ci sono molti casi di utilizzo di pid_task() nei sorgenti del kernel Linux (ad esempio in posix_timer_event() ).
Ad esempio:

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

Scopri di più sull'API RCU da Kernel.org

P.S. inoltre puoi semplicemente utilizzare le funzioni API speciali come find_task_by_pid_ns() e find_task_by_vpid() sotto il rcu_read_lock() .

Il primo è per la ricerca attraverso il particolare spazio dei nomi:

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

Il secondo è per la ricerca nello spazio dei nomi di current compito.


Cosa c'è di sbagliato nell'usare uno dei seguenti?

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. Esempi di progettazione efficiente di server di rete, scritti in C

  2. Modo più veloce per eliminare un gran numero di file

  3. Qual è il modo più efficiente per spostare un gran numero di file che risiedono in una singola directory?

  4. Come trovare il file .pid per un determinato processo

  5. trova il comando dal PID

Come trovare un nome di processo utilizzando il numero PID in Linux

Qual è il modo migliore per contare il numero di file in una directory?

Modo per scoprire se il sistema supporta Intel Amt?

Come trovare il nome del processo dal suo PID

Come trovare il PID e il PPID di un processo in Linux

adb:trova PID dalla shell adb