Discussioni vs processi (fork)


9

Le applicazioni Linux generalmente eseguono il fork, quindi exec (con execve ()), ma le applicazioni Java e alcuni MPM Apache usano il threading. Se biforcando, usa fork + exec per generare un processo, qual è la versione di alto livello per il threading? In che modo vengono generati i thread JVM o Worker MPM?


2
Dai un'occhiata a StackOverflow. Ci sono diverse domande e risposte che hanno spiegato una parte di questo.
Henk Langeveld,

Risposte:


13

L'idea alla base di thread e processi è la stessa: biforcate il percorso di esecuzione. Altrimenti thread e processi differiscono in cose come la memoria. Vale a dire i processi hanno uno spazio VM diverso mentre i thread condividono tutto ciò che esisteva prima della divisione.

Alla base sia del threading che del fork si lavora usando la chiamata clone () (man 2 clone):

A differenza di fork (2), clone () consente al processo figlio di condividere parti del suo contesto di esecuzione con il processo chiamante, come lo spazio di memoria, la tabella dei descrittori di file e la tabella dei gestori di segnale. (Notare che in questa pagina di manuale, "processo di chiamata" normalmente corrisponde a "processo padre". Vedere la descrizione di CLONE_PARENT di seguito.)

L'uso principale di clone () è quello di implementare thread: più thread di controllo in un programma che vengono eseguiti contemporaneamente in uno spazio di memoria condivisa.

Le differenze derivano dalle bandiere che vengono passate a clone (). Come puoi vedere dalla pagina man, fork e threading sono solo un insieme di parametri predefiniti per clone (). Tuttavia si può anche fare cose personalizzate con esso.


1
Uhm? Che cosa? Si prega di rileggere quasi ogni libro sull'argomento, perché lo spazio di memoria separato per i processi è un po 'un grosso problema. Aiuta anche a "catturare" il codice che si arresta in modo anomalo, mentre il kernel semplicemente ucciderà un processo in cui un singolo thread va in tilt / trasgredisce.
0xC0000022L

3
@ 0xC0000022L il tuo argomento non contraddice la risposta, come mi sembra.
Ruslan,

1
@Ruslan: mi permetto di dissentire: "L'idea [...] è più o meno la stessa"? L'idea alla base dei thread è in effetti la concorrenza, ma per i processi questa è una storia completamente diversa.
0xC0000022L

4
@ 0xC0000022L Ti sei perso la parte importante della risposta di V13: "Stai biforcando il percorso di esecuzione" - la domanda è su come vengono generati i thread, non quale sia la differenza tra thread e processi
Izkata,

@Izkata: niente affatto. Ritengo che questa non sia un'affermazione corretta.
0xC0000022L

8

La maggior parte dei sistemi operativi (SO) multiprocessore non Unix utilizza una chiamata "spawn ()" o qualcosa di simile per generare un nuovo processo del sistema operativo o flusso di controllo. Spawn () tende ad essere una chiamata molto complessa, con molte opzioni e molte spese generali. Una delle innovazioni di Unix è stata quella di fornire un modo molto più basso di creare processi - fork (). Unix si è preso cura delle molte opzioni necessarie per spawn () consentendo quantità arbitrarie di elaborazione prima dell'altra metà di spawn (), con exec ().

Man mano che Unix e le sue varianti venivano sempre più utilizzate, la creazione di processi a basso costo risultava utile e veniva utilizzata. In effetti, è stato usato così tanto che la gente voleva modi ancora più bassi per creare processi, e così è nata l'idea di "thread". Inizialmente, i thread venivano gestiti completamente dal processo di origine (e programmi come JVM potevano farlo con "thread verdi"); ma gestire la pianificazione multi-thread è complicato e spesso è stato eseguito in modo errato. Quindi esiste un modo più semplice e intermedio di eseguire thread, in cui il sistema operativo gestisce la pianificazione ma un certo overhead viene salvato condividendo (in genere) lo spazio degli indirizzi tra i thread.

Alla tua domanda è difficile rispondere perché ci sono molti concetti diversi ma correlati che sono tutti "thread" e per i dettagli hai bisogno di un aggettivo per descrivere quale ti stai riferendo. D'altra parte, capire le differenze probabilmente ti porterà alla risposta specifica che desideri. Cerca cose come "processi leggeri", "thread utente" e "rfork ()" per maggiori informazioni.


1
"La gestione della pianificazione multi-thread è complicata ed è stata spesso eseguita in modo errato" è necessaria la citazione. L'implementazione dei thread dello spazio utente non è un problema. Il problema con i thread dello spazio utente è che se un thread esegue un blocco di tutti i thread viene bloccato. L'unico modo per evitarlo è utilizzare i thread a livello di sistema.
Bakuriu,

1
È interessante notare che Windows non ha incluso questa innovazione di Unix: non ha CreateProcess()nulla di simile fork().
Ruslan,

2
@Bakuriu - cerca uno dei tanti articoli sulla costruzione di programmatori multiprocessore, sul mantenimento dell'equità, sulla prevenzione della fame, sulla gestione delle priorità, ecc. L'implementazione dei thread dello spazio utente non è, come dici tu, un problema. Pianificare esempi non banali è difficile.
mpez0,

@Ruslan: si può borsare su Windows, semplicemente non fa parte dell'API Win32. Leggi "L'API nativa di Windows NT / 2000" di Nebbett. Ha un'implementazione che imita fork().
0xC0000022L

3

Thread e fork sono in realtà due concetti diversi, entrambi presenti nei sistemi Unix / Linux (ed entrambi che possono essere utilizzati in C / C ++).

L'idea di fork () è (in sostanza) una creazione di un processo separato che ha lo stesso codice di esecuzione del processo parent e che inizia l'esecuzione sulla linea fork. Lo scopo dell'uso delle forcelle con le funzioni exec è che le funzioni exec chiudono il processo che le ha chiamate alla fine. Quindi, di solito esegui il fork, ottenendo il PID di ogni processo (quello del figlio è sempre 0) e fai aspettare il genitore finché il figlio non ha finito di eseguire la funzione exec.

I thread sono usati per il parallelismo (ricorda che il genitore aspetta il bambino, di solito, in un programma biforcuto). Un thread, come pthread in C / C ++ (esegui una ricerca su Google), verrà eseguito in parallelo al processo principale e può condividere variabili globali e funzioni globali con il programma originale. Poiché i thread Java si comportano in modo simile, immagino che agiscano più come questi thread che come un processo di fork.

Fondamentalmente, c'è una differenza tra il fork e il threading. Fanno cose nettamente diverse (anche se sembrano simili). Questi concetti possono essere difficili da capire, ma puoi impararli attraverso ricerche (approfondite) se hai un sincero desiderio di capirli.

EDIT # 1

Consulta questi esempi di come è possibile chiamare e utilizzare forchette e thread. Nota il comportamento delle funzioni exec e i loro effetti sul programma principale.

http://www.jdembrun.com:4352/computerScience/forkVSthread.zip


2
Fork (con o senza exec) può essere utilizzato anche per il parallelismo. Non sono sicuro di cosa intendi con "funzioni exec chiudono il processo che li ha chiamati quando finiscono", exec ha finito per essere eseguito alla fine del processo. Inoltre pthreadè un'API, non un'implementazione di thread.
Mat,

Per quanto riguarda il fork, sto citando il mio insegnante OS. Secondo quello che ci ha detto, sì, il fork potrebbe essere usato per correre in parallelo, ma, se usasse una funzione exec, sarebbe l'ultima. Per quanto riguarda pthread, era inteso come esempio.
jaredad7,

Exec sarebbe l'ultima chiamata nel codice del chiamante, non l'ultima istruzione del processo biforcuta. Il processo biforcuto sopravviverebbe nell'esecuzione del codice exec'd.
Mat

I tuoi commenti mi hanno spinto a provare queste cose. Ho scritto alcuni programmi c ++ che dimostrano il comportamento delle funzioni exec e i loro effetti sui programmi quando usati in fork e thread. Si prega di consultare la modifica sopra.
jaredad7,

Temo che molte persone non si preoccupino di scaricarlo. Inoltre, i tuoi esempi non illustrano le interessanti differenze tra i modelli, che sono principalmente legate alla condivisione (o meno) dello spazio degli indirizzi.
Mat

1

Sia JVM che Apache MPM si basano sul kernel per i thread nativi. Cioè, usano il sistema operativo per programmarli. Naturalmente entrambi hanno bisogno della propria API per tenere traccia delle cose.

Stackoverflow ha già diverse domande su questo:

  1. Discussioni native JVM , controlla questa risposta per maggiori dettagli.

  2. Apache ha due tipi di MPM: Prefork, con un processo per thread e Worker, che gestisce più thread: Apache MPM . Dai un'occhiata al riferimento acodebucket


1

Se biforcando, usa fork + exec per generare un processo, qual è la versione di alto livello per il threading? In che modo vengono generati i thread JVM o Worker MPM?

Questo è specifico per la piattaforma, ma su Linux e presumo che molti altri sistemi POSIX compatibili utilizzino l'implementazione locale di pthreads , un'API di threading userland. Per esempio:

#include <pthread.h>

pthread_t tid;
pthread_create(&tid, NULL, somefunc, NULL);

Inizia una nuova discussione chiamando somefunccome primo punto di esecuzione.

Puoi anche creare thread - distinti dalle fork in quanto condividono lo stesso spazio di memoria heap globale del processo genitore, invece di ottenerne una copia duplicata (ma nota che i thread vengono eseguiti ciascuno con una memoria stack indipendente ) - con la clone()chiamata di sistema, che è ciò su cui pthreads è costruito sopra.

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.