Wie können Threads identifiziert werden, die dieselbe PID haben?

97

Ich habe eine Abfrage zur Implementierung von Threads unter Linux.

Linux hat keine explizite Thread-Unterstützung. Im Userspace verwenden wir möglicherweise eine Thread-Bibliothek (wie NPTL) zum Erstellen von Threads. Wenn wir jetzt NPTL verwenden, unterstützt es 1: 1-Mapping.

Der Kernel verwendet die clone()Funktion, um Threads zu implementieren.

Angenommen, ich habe 4 Threads erstellt. Dann würde es bedeuten, dass:

  • Es wird 4 geben task_struct.
  • Innerhalb des task_structwird die gemeinsame Nutzung von Ressourcen gemäß den zu klonenden Argumenten bereitgestellt (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND).

Jetzt habe ich folgende Abfrage:

  1. Haben die 4 Threads die gleiche PID? Wenn jemand näher darauf eingehen kann, wie die PIDs geteilt werden.
  2. Wie werden die verschiedenen Threads identifiziert? Gibt es ein TID-Konzept (Thread ID)?
SPSN
quelle

Antworten:

272

Die vier Threads haben dieselbe PID, jedoch nur von oben gesehen. Was Sie (als Benutzer) eine PID nennen, ist nicht das, was der Kernel (von unten gesehen) eine PID nennt.

Im Kernel hat jeder Thread eine eigene ID, die als PID bezeichnet wird (obwohl es möglicherweise sinnvoller wäre, dies als TID oder Thread-ID zu bezeichnen), und sie haben auch eine TGID (Thread-Gruppen-ID), die die PID des Threads ist das hat den ganzen Prozess gestartet.

Wenn ein neuer Prozess erstellt wird, wird er vereinfacht als Thread angezeigt, in dem sowohl die PID als auch die TGID dieselbe (neue) Nummer haben.

Wenn ein Thread einen anderen Thread startet , erhält dieser gestartete Thread eine eigene PID (damit der Scheduler sie unabhängig planen kann), erbt jedoch die TGID vom ursprünglichen Thread.

Auf diese Weise kann der Kernel Threads unabhängig davon planen, zu welchem ​​Prozess sie gehören, während Prozesse (Threadgruppen-IDs) an Sie gemeldet werden.

Die folgende Hierarchie von Threads kann (a) helfen :

                      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

Sie können sehen, dass Sie durch Starten eines neuen Prozesses (links) eine neue PID und eine neue TGID (beide auf denselben Wert gesetzt) ​​erhalten, während Sie durch Starten eines neuen Threads (rechts) eine neue PID erhalten, während Sie dieselbe beibehalten TGID als Thread, der es gestartet hat.


(a) Zittern Sie vor Ehrfurcht vor meinen beeindruckenden grafischen Fähigkeiten :-)

paxdiablo
quelle
20
Zu getpid()Ihrer Information , gibt tgid zurück:, asmlinkage long sys_getpid(void) { return current->tgid;}wie in www.makelinux.com/
Duke
6
@Duke - wow, deshalb konnte ich keine gettgid(2)Funktion finden. Und die getpid()TID (die "PID" des Threads) wird nicht zurückgegeben, und da gettid(2)kommt sie ins Spiel . Auf diese Weise kann ich feststellen, ob wir im Haupt-Thread sind oder nicht.
Tomasz Gandor
2
Dies führt zu einem weiteren interessanten Punkt: Wenn also Threads und Prozesse innerhalb des Kernels (abgesehen von der tgid) gleich behandelt werden, erhält ein Multithread-Prozess abschließend mehr CPU-Zeit als ein Single-Thread-Prozess, vorausgesetzt, beide haben dieselbe Priorität und keiner der Threads wird aus irgendeinem Grund angehalten (z. B. Warten auf einen Mutex).
Aconcagua
1
@Aconcagua, CFS (der vollständig faire Scheduler unter Linux) funktioniert im Allgemeinen auf diese Weise, ermöglicht jedoch auch die Verwendung von Gruppenplaner-Erweiterungen, damit die Fairness über bestimmte Aufgabengruppen hinweg und nicht über einzelne Aufgaben hinweg funktioniert. Ich habe mich nie wirklich damit befasst, außer einem flüchtigen Blick.
Paxdiablo
'' getpgrp '' um die Gruppen-ID zu erhalten
Pengcheng
2

Threads werden anhand von PIDs und TGID (Thread Group ID) identifiziert. Sie wissen auch, welcher Thread ein übergeordneter Thread ist, von dem ein Prozess im Wesentlichen seine PID mit allen von ihm gestarteten Threads teilt. Thread-IDs werden normalerweise von der Thread-Bibliothek selbst verwaltet (z. B. pthread usw.). Wenn die 4 Threads gestartet werden, sollten sie dieselbe PID haben. Der Kernel selbst übernimmt die Thread-Planung und dergleichen, aber die Bibliothek ist diejenige, die die Threads verwaltet (ob sie ausgeführt werden können oder nicht, abhängig von Ihrer Verwendung der Thread-Join- und Wartemethoden).

Hinweis: Dies ist aus meiner Erinnerung an Kernel 2.6.36. Meine Arbeit in aktuellen Kernelversionen befindet sich in der E / A-Ebene, daher weiß ich nicht, ob sich dies seitdem geändert hat.

Jesus Ramos
quelle
-6

Linux bietet dem fork()Systemaufruf die traditionelle Funktionalität, einen Prozess zu duplizieren. Linux bietet auch die Möglichkeit, Threads mithilfe des clone()Systemaufrufs zu erstellen. Linux unterscheidet jedoch nicht zwischen Prozessen und Threads.

SAUNDARYA KUMAR GUPTA
quelle