Se i thread condividono lo stesso PID, come possono essere identificati?


98

Ho una domanda relativa all'implementazione dei thread in Linux.

Linux non ha un supporto esplicito per i thread. Nello spazio utente, potremmo usare una libreria di thread (come NPTL) per creare thread. Ora, se usiamo NPTL, supporta la mappatura 1: 1.

Il kernel utilizzerà l'estensione clone() funzione per implementare i thread.

Supponiamo di aver creato 4 thread. Allora significherebbe che:

  • Ce ne saranno 4 task_struct .
  • All'interno di task_struct, ci sarà la possibilità di condividere le risorse secondo gli argomenti da clonare (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND).

Ora ho la seguente domanda:

  1. I 4 thread avranno lo stesso PID? Se qualcuno può elaborare, come vengono condivisi i PID.
  2. Come vengono identificati i diversi fili? c'è qualche concetto di TID (ID thread)?

Risposte:


274

I quattro thread avranno lo stesso PID ma solo se visti dall'alto. Quello che tu (come utente) chiami PID non è quello che il kernel (guardando dal basso) chiama PID.

Nel kernel, ogni thread ha il proprio ID, chiamato PID (anche se forse avrebbe più senso chiamarlo TID o ID thread) e hanno anche un TGID (thread group ID) che è il PID del thread che ha dato inizio all'intero processo.

Semplicisticamente, quando viene creato un nuovo processo , appare come un thread in cui sia il PID che il TGID hanno lo stesso (nuovo) numero.

Quando un thread avvia un altro thread, quel thread avviato ottiene il proprio PID (in modo che lo scheduler possa pianificarlo in modo indipendente) ma eredita il TGID dal thread originale.

In questo modo, il kernel può tranquillamente programmare i thread indipendentemente dal processo a cui appartengono, mentre i processi (ID del gruppo di thread) vengono segnalati all'utente.

La seguente gerarchia di thread può aiutare (a) :

                      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

Puoi vedere che l'avvio di un nuovo processo (a sinistra) ti dà un nuovo PID e un nuovo TGID (entrambi impostati sullo stesso valore), mentre l'avvio di un nuovo thread (a destra) ti dà un nuovo PID mantenendo lo stesso TGID come thread che lo ha avviato.


(a) Trema in soggezione per le mie impressionanti capacità grafiche :-)


20
Cordiali saluti, getpid()restituisce tgid:, asmlinkage long sys_getpid(void) { return current->tgid;}come mostrato in www.makelinux.com/
Duke

6
@Duke - wow, ecco perché non sono riuscito a trovare una gettgid(2)funzione. E getpid()non restituirà il TID (il "PID" del thread), ed è qui che gettid(2)entra in gioco. In questo modo posso dire se siamo nel thread principale o meno.
Tomasz Gandor

2
Questo porta ad un altro punto interessante: quindi se thread e processi sono gestiti allo stesso modo all'interno del kernel (a parte il tgid), un processo multi-thread in conclusione otterrà più tempo CPU di uno a thread singolo, a condizione che entrambi abbiano lo stesso priorità e nessuno dei thread viene interrotto per qualsiasi motivo (come l'attesa di un mutex).
Aconcagua,

1
@Aconcagua, CFS (lo scheduler completamente equo in Linux) generalmente funziona in questo modo, ma consente anche l'uso di estensioni dello scheduler di gruppo per far sì che l'equità operi su determinati gruppi di attività piuttosto che su singole attività. Non l'ho mai veramente esaminato se non una rapida occhiata.
paxdiablo

'' getpgrp '' per ottenere l'ID del gruppo
Pengcheng

2

I thread vengono identificati utilizzando PID e TGID (Thread group id). Sanno anche quale thread è un genitore di chi quindi essenzialmente un processo condivide il suo PID con tutti i thread che inizia. Gli ID thread sono generalmente gestiti dalla libreria thread stessa (come pthread, ecc ...). Se i 4 thread vengono avviati, dovrebbero avere lo stesso PID. Il kernel stesso gestirà la pianificazione dei thread e simili, ma la libreria è quella che gestirà i thread (indipendentemente dal fatto che possano essere eseguiti o meno a seconda dell'uso dei metodi di join e attesa del thread).

Nota: questo è dal mio ricordo del kernel 2.6.36. Il mio lavoro nelle attuali versioni del kernel è nel livello I / O, quindi non so se da allora sia cambiato.


-6

Linux fornisce alla fork()chiamata di sistema la tradizionale funzionalità di duplicazione di un processo. Linux fornisce anche la possibilità di creare thread usando la clone()chiamata di sistema Tuttavia, linux non distingue tra processi e thread.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.