J'ai une requête liée à l'implémentation de threads sous Linux.
Linux n'a pas de support de thread explicite. Dans l'espace utilisateur, nous pouvons utiliser une bibliothèque de threads (comme NPTL) pour créer des threads. Maintenant, si nous utilisons NPTL, il prend en charge le mappage 1: 1.
Le noyau utilisera la fonction clone()
pour implémenter les threads.
Supposons que j'ai créé 4 threads. Cela signifierait alors que:
task_struct
.task_struct
, des ressources de partage seront fournies conformément aux arguments pour cloner (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
.Maintenant, j'ai la requête suivante:
Les quatre threads auront le même PID mais uniquement lorsqu'ils sont vus de ci-dessus. Ce que vous (en tant qu'utilisateur) appelez un PID n'est pas ce que le noyau (en regardant d'en bas) appelle un PID.
Dans le noyau, chaque thread a son propre ID, appelé PID (bien qu'il serait peut-être plus logique d'appeler cela un TID ou ID de thread) et ils ont également un TGID (ID de groupe de threads) qui est le PID du thread qui a démarré tout le processus.
Simplement, quand un nouveau processus est créé, il apparaît comme un thread où le PID et le TGID sont tous les deux le même (nouveau) numéro.
Lorsqu'un thread démarre un autre thread, ce thread démarré obtient son propre PID (afin que le planificateur puisse le planifier indépendamment) mais il hérite du TGID du thread d'origine.
De cette façon, le noyau peut facilement planifier des threads indépendamment du processus auquel ils appartiennent, tandis que les processus (ID de groupe de threads) vous sont signalés.
La hiérarchie de threads suivante peut aider(une):
USER VIEW
<-- PID 43 --> <----------------- PID 42 ----------------->
+---------+
| process |
_| pid=42 |_
_/ | tgid=42 | \_ (new thread) _
_ (fork) _/ +---------+ \
/ +---------+
+---------+ | process |
| process | | pid=44 |
| pid=43 | | tgid=42 |
| tgid=43 | +---------+
+---------+
<-- PID 43 --> <--------- PID 42 --------> <--- PID 44 --->
KERNEL VIEW
Vous pouvez voir que le démarrage d'un nouveau processus (à gauche) vous donne un nouveau PID et un nouveau TGID (tous deux définis sur la même valeur), tout en démarrant un nouveau - thread (à droite) vous donne un nouveau PID tout en conservant le même TGID que le thread qui l'a démarré.
(une) Tremble en admiration à mes impressionnantes compétences graphiques :-)
Les threads sont identifiés à l'aide de PID et de TGID (Thread group id). Ils savent également quel thread est le parent de qui si essentiellement un processus partage son PID avec tous les threads qu'il démarre. Les ID de threads sont généralement gérés par la bibliothèque de threads elle-même (comme pthread, etc ...). Si les 4 threads sont démarrés, ils doivent avoir le même PID. Le noyau lui-même gérera la planification des threads et autres, mais la bibliothèque est celle qui va gérer les threads (qu'ils puissent s'exécuter ou non selon votre utilisation des méthodes de jointure de thread et d'attente).
Remarque: cela vient de mon souvenir du noyau 2.6.36. Mon travail dans les versions actuelles du noyau est dans la couche d'E/S, donc je ne sais pas si cela a changé depuis.