GNU/Linux >> Linux Esercitazione >  >> Linux

I thread sono implementati come processi su Linux?

Penso che questa parte del clone(2) la pagina man può chiarire la differenza re. il PID:

CLONE_THREAD (a partire da Linux 2.4.0-test8)
Se CLONE_THREAD è impostato, il figlio viene inserito nello stesso threadgroup del processo chiamante.
I gruppi di thread erano una funzionalità aggiunta in Linux 2.4 per supportare la nozione di thread POSIX di un insieme di thread che condividono un singolo PID. Internamente, questo PID condiviso è il cosiddetto identificatore di threadgroup (TGID) per il gruppo di thread. Da Linux 2.4, le chiamate a getpid(2) restituiscono il TGID del chiamante.

La frase "i thread sono implementati come processi" si riferisce al problema dei thread che hanno avuto PID separati in passato. Fondamentalmente, Linux originariamente non aveva thread all'interno di un processo, solo processi separati (con PID separati) che avrebbero potuto avere alcune risorse condivise, come memoria virtuale o descrittori di file. CLONE_THREAD e la separazione dell'ID del processo e dell'ID del thread rende il comportamento di Linux più simile ad altri sistemi e più simile ai requisiti POSIX in questo senso. Sebbene tecnicamente il sistema operativo non abbia ancora implementazioni separate per thread e processi.

La gestione del segnale era un'altra area problematica con la vecchia implementazione, questo è descritto più dettagliatamente nel documento a cui @FooF fa riferimento nella loro risposta.

Come notato nei commenti, anche Linux 2.4 è stato rilasciato nel 2001, lo stesso anno del libro, quindi non sorprende che la notizia non sia arrivata a quella stampa.


Hai ragione, anzi "qualcosa deve essere cambiato dal 2001 ad oggi". Il libro che stai leggendo descrive il mondo secondo la prima storica implementazione dei thread POSIX su Linux, chiamati LinuxThreads (vedi anche l'articolo di Wikipedia per alcuni).

LinuxThreads presentava alcuni problemi di compatibilità con lo standard POSIX, ad esempio thread che non condividevano PID, e alcuni altri seri problemi. Per correggere questi difetti, un'altra implementazione chiamata NPTL (Native POSIX Thread Library) è stata guidata da Red Hat per aggiungere il necessario supporto della libreria dello spazio utente e del kernel per raggiungere una migliore conformità POSIX (prendendo parti buone da un altro progetto di reimplementazione concorrente di IBM chiamato NGPT (" Next Generation Posix Threads"), vedere l'articolo di Wikipedia su NPTL). I flag aggiuntivi aggiunti al clone(2) chiamata di sistema (in particolare CLONE_THREAD quel @ikkkachu sottolinea nella sua risposta) è probabilmente la parte più evidente delle modifiche del kernel. La parte del lavoro relativa allo spazio utente alla fine è stata incorporata nella GNU C Library.

Ancora oggi alcuni SDK Linux incorporati usano la vecchia implementazione di LinuxThreads perché usano una versione di footprint di memoria più piccola di LibC chiamata uClibc (chiamata anche µClibc), e ci sono voluti un gran numero di anni prima che l'implementazione dello spazio utente NPTL da GNU LibC fosse portata e assunto come implementazione predefinita del threading POSIX, poiché in generale queste piattaforme speciali non si sforzano di seguire le mode più recenti alla velocità della luce. L'uso dell'implementazione di LinuxThreads in funzione può essere osservato notando che, in effetti, i PID per diversi thread su quelle piattaforme sono diversi a differenza di quanto specificato dallo standard POSIX, proprio come descrive il libro che stai leggendo. In realtà, una volta che hai chiamato pthread_create() , improvvisamente avevi aumentato il conteggio dei processi da uno a tre poiché era necessario un processo aggiuntivo per tenere insieme il caos.

La pagina man di Linux pthreads(7) fornisce una panoramica completa e interessante delle differenze tra i due. Un'altra descrizione illuminante, anche se obsoleta, delle differenze è questo documento di Ulrich Depper e Ingo Molnar sulla progettazione di NPTL.

Ti consiglio di non prendere troppo sul serio quella parte del libro. Raccomando invece i thread Programming POSIX di Butenhof e le pagine di manuale POSIX e Linux sull'argomento. Molti tutorial sull'argomento sono imprecisi.


I thread (spazio utente) non sono implementati come processi in quanto tali su Linux, in quanto non hanno il proprio spazio di indirizzi privato, condividono comunque lo spazio di indirizzi del processo padre.

Tuttavia, questi thread sono implementati per utilizzare il sistema di contabilità del processo del kernel, quindi viene assegnato il proprio ID thread (TID), ma viene assegnato lo stesso PID e 'ID gruppo thread' (TGID) del processo padre - questo è in contrasto con un fork, in cui vengono creati un nuovo TGID e PID e il TID è uguale al PID.

Quindi sembra che i kernel recenti avessero un TID separato che può essere interrogato, è questo che è diverso per i thread, uno snippet di codice adatto per mostrarlo in ciascuno dei main() thread_function() sopra è:

    long tid = syscall(SYS_gettid);
    printf("%ld\n", tid);

Quindi l'intero codice con questo sarebbe:

#include <pthread.h>                                                                                                                                          
#include <stdio.h>                                                                                                                                            
#include <unistd.h>                                                                                                                                           
#include <syscall.h>                                                                                                                                          

void* thread_function (void* arg)                                                                                                                             
{                                                                                                                                                             
    long tid = syscall(SYS_gettid);                                                                                                                           
    printf("child thread TID is %ld\n", tid);                                                                                                                 
    fprintf (stderr, "child thread pid is %d\n", (int) getpid ());                                                                                            
    /* Spin forever. */                                                                                                                                       
    while (1);                                                                                                                                                
    return NULL;                                                                                                                                              
}                                                                                                                                                             

int main ()                                                                                                                                                   
{                                                                                                                                               
    pthread_t thread;                                                                               
    long tid = syscall(SYS_gettid);     
    printf("main TID is %ld\n", tid);                                                                                             
    fprintf (stderr, "main thread pid is %d\n", (int) getpid ());                                                    
    pthread_create (&thread, NULL, &thread_function, NULL);                                           
    /* Spin forever. */                                                                                                                                       
    while (1);                                                                                                                                                
    return 0;                                                                                                                                                 
} 

Fornire un output di esempio di:

main TID is 17963
main thread pid is 17963
thread TID is 17964
child thread pid is 17963

Linux
  1. Linux:registro dei thread passati che ora sono chiusi?

  2. comando Linux ps

  3. Introduzione ai thread di Linux – Parte I

  4. Cosa sono i processi Linux, i thread, i processi leggeri e lo stato del processo

  5. I thread del kernel di Linux sono davvero processi del kernel?

Comando Ps in Linux (Elenca processi)

Comando Pgrep in Linux

Comando PS Linux con esempi

Scopri quali processi sono in ascolto su una porta particolare in Linux

Monitoraggio dei processi su Linux

Comprensione dei processi su Linux