Linus Torvalds (torvalds@cs.helsinki.fi)
Martedì 6 agosto 1996 12:47:31 +0300 (EET DST)
Messaggi ordinati per: [data] [discussione] [oggetto] [autore]
Messaggio successivo: Bernd P. Ziller: "Ri: Oops in get_hash_table"
Messaggio precedente: Linus Torvalds: "Ri: ordinazione richiesta I / O"
Il lunedì 5 agosto 1996, Peter P. Eiserloh scrisse:
Dobbiamo mantenere chiaro il concetto di thread. Troppe persone sembrano confondere un thread con un processo. La seguente discussione non riflette lo stato attuale di Linux, ma piuttosto è un tentativo di rimanere su una discussione di alto livello.
NO!
Non c'è motivo di pensare che "thread" e "processi" siano entità separate. È così che viene fatto tradizionalmente, ma personalmente penso che sia un grosso errore pensare in quel modo. L'unico motivo per pensare in quel modo è il bagaglio storico.
Sia i thread che i processi sono in realtà solo una cosa: un "contesto di esecuzione". Cercare di distinguere artificialmente casi diversi è auto-limitante.
Un "contesto di esecuzione", qui denominato COE, è solo il conglomerato di tutto lo stato di quel COE. Tale stato include elementi quali stato della CPU (registri, ecc.), Stato della MMU (mappatura delle pagine), stato delle autorizzazioni (uid, gid) e vari "stati di comunicazione" (file aperti, gestori di segnali, ecc.). Tradizionalmente, la differenza tra un "thread" e un "processo" è stata principalmente che un thread ha stato CPU (+ forse qualche altro stato minimo), mentre tutto il resto del contesto deriva dal processo. Tuttavia, questo è solo
un modo per dividere lo stato totale del COE, e non c'è nulla che dica che è il modo giusto di farlo. Limitare te stesso a quel tipo di immagine è semplicemente stupido.
Il modo in cui Linux pensa questo (e il modo in cui voglio le cose al lavoro) è che non v'è alcuna cosa come un "processo" o di un "filo". Esiste solo la totalità del COE (chiamato "task" da Linux). Diversi COE possono condividere parti del loro contesto l'una con l'altra e un sottoinsieme di quella condivisione è la tradizionale configurazione "thread" / "processo", ma questo dovrebbe davvero essere visto SOLO come un sottoinsieme (è un sottoinsieme importante, ma quell'importanza viene non dal design, ma dagli standard: vogliamo ovviamente eseguire programmi di thread conformi agli standard anche su Linux).
In breve: NON progettare attorno al modo di pensare il thread / processo. Il kernel dovrebbe essere progettato attorno al modo di pensare COE, e quindi la libreria pthreads può esportare l'interfaccia pthreads limitata per gli utenti che vogliono usare quel modo di vedere i COE.
Proprio come un esempio di ciò che diventa possibile quando pensi a COE invece di thread / processo:
- Puoi fare un programma "cd" esterno, qualcosa che è tradizionalmente impossibile in UNIX e / o process / thread (esempio sciocco, ma l'idea è che puoi avere questo tipo di "moduli" che non sono limitati al tradizionale UNIX / thread setup). Fai un:
clone (CLONE_VM | CLONE_FS);
child: execve ("cd-esterno");
/ * "execve ()" disassocerà la VM, quindi l'unica ragione per cui abbiamo usato CLONE_VM è stata quella di rendere più veloce l'atto di clonazione * /
- Puoi fare "vfork ()" naturalmente (soddisfa il minimo supporto del kernel, ma quel supporto si adatta perfettamente al modo di pensare CUA):
clone (CLONE_VM);
figlio: continua a funzionare, eventualmente execve ()
madre: aspetta l'esecuzione
- puoi fare "IO deamon" esterni:
clone (CLONE_FILES);
figlio: descrittori di file aperti ecc
madre: usa la fd che il bambino ha aperto e vv.
Tutto quanto sopra funziona perché non sei legato al modo di pensare thread / processo. Pensa ad un web server, ad esempio, in cui gli script CGI vengono eseguiti come "thread di esecuzione". Non puoi farlo con i thread tradizionali, perché i thread tradizionali devono sempre condividere l'intero spazio degli indirizzi, quindi dovresti collegarti a tutto ciò che avresti sempre voluto fare sul server web stesso (un "thread" non può essere eseguito un altro eseguibile).
Considerando invece questo come un problema di "contesto di esecuzione", le attività possono ora scegliere di eseguire programmi esterni (= separare lo spazio degli indirizzi dal genitore) ecc., Se lo desiderano, oppure possono ad esempio condividere tutto con il genitore ad eccezione di i descrittori di file (in modo che i "thread" secondari possano aprire molti file senza che il genitore debba preoccuparsi di loro: si chiudono automaticamente quando il sottotitolo "thread" viene chiuso e non utilizza i file fd nel genitore) .
Pensa ad un thread "inetd", per esempio. Vuoi un overhead fork + exec, quindi con il modo Linux puoi invece di usare un "fork ()" scrivi un inetd multi-thread in cui ogni thread viene creato con solo CLONE_VM (condividi lo spazio degli indirizzi, ma non condividi il file descrittori ecc.). Quindi il bambino può eseguire se era un servizio esterno (rlogind, per esempio), o forse era uno dei servizi interni inetd (eco, timeofday) nel qual caso fa semplicemente la sua cosa ed esce.
Non puoi farlo con "thread" / "process".
Linus