GNU/Linux >> Tutoriels Linux >  >> Linux

Un moyen efficace de trouver task_struct par pid

Il existe un meilleur moyen d'obtenir l'instance de task_struct à partir d'un module. Essayez toujours d'utiliser des routines de fonction/d'assistance wrapper car elles sont conçues de telle manière que si le programmeur du pilote a manqué quelque chose, le noyau peut s'en charger lui-même. Par exemple - gestion des erreurs, vérification des conditions, etc.

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

taskp = get_pid_task(pid, PIDTYPE_PID);

et pour obtenir le PID de type pid_t. vous devez utiliser l'API ci-dessous -

find_get_pid(pid_no);

Vous n'avez pas besoin d'utiliser "rcu_read_lock() " et "rcu_read_unlock() " tout en appelant ces API parce que "get_pid_task() " appelle en interne rcu_read_lock(), rcu_read_unlock() avant d'appeler "pid_task() " et gère correctement la simultanéité. C'est pourquoi j'ai dit ci-dessus de toujours utiliser ce type d'emballage.

Extrait de la fonction get_pid_task() et find_get_pid() ci-dessous :-

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

Dans un module du noyau, vous pouvez également utiliser la fonction wrapper de la manière suivante -

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

PS :pour plus d'informations sur les API, vous pouvez consulter kernel/pid.c


Si vous voulez trouver le task_struct d'un module, find_task_by_vpid(pid_t nr) etc. ne fonctionneront pas car ces fonctions ne sont pas exportées.

Dans un module, vous pouvez utiliser la fonction suivante à la place :

pid_task(find_vpid(pid), PIDTYPE_PID);

Personne n'a mentionné que le pid_task() fonction et le pointeur (que vous obtenez à partir de celui-ci) doit être utilisé dans la section critique RCU (car il utilise une structure de données protégée par RCU). Sinon il peut y avoir un BUG use-after-free .
Il existe de nombreux cas d'utilisation de pid_task() dans les sources du noyau Linux (par exemple dans posix_timer_event() ).
Par exemple :

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

En savoir plus sur l'API RCU sur Kernel.org

PS vous pouvez également simplement utiliser les fonctions spéciales de l'API comme find_task_by_pid_ns() et find_task_by_vpid() sous le rcu_read_lock() .

Le premier est pour rechercher dans l'espace de noms particulier :

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

Le second est pour rechercher dans l'espace de noms de current tâche.


Qu'y a-t-il de mal à utiliser l'un des éléments suivants ?

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. Existe-t-il un moyen de vérifier s'il existe des liens symboliques pointant vers un répertoire ?

  2. Le moyen le plus efficace de copier un fichier sous Linux

  3. adb :trouver le PID à partir du shell adb

  4. Un moyen plus rapide de supprimer un grand nombre de fichiers

  5. Quelle est la manière la plus efficace de déplacer un grand nombre de fichiers qui résident dans un seul répertoire ?

Comment trouver un nom de processus à l'aide d'un numéro PID sous Linux

Grep récursif Vs Find / -type F -exec Grep {} ; Lequel est le plus efficace/rapide ?

Quelle est la meilleure façon de compter le nombre de fichiers dans un répertoire ?

N moyen facile de remplacer les fichiers en double par des liens physiques ?

Comment trouver le nom du processus à partir de son PID

Comment trouver le PID et le PPID d'un processus sous Linux