Qual è lo scopo di fork ()?


88

In molti programmi e pagine man di Linux, ho visto usare del codice fork(). Perché dobbiamo usarlo fork()e qual è il suo scopo?


151
In modo che tutti quei filosofi a tavola non muoiano di fame.
kenj0418

Risposte:


109

fork()è il modo in cui crei nuovi processi in Unix. Quando chiami fork, stai creando una copia del tuo processo che ha il proprio spazio degli indirizzi . Ciò consente a più attività di essere eseguite indipendentemente l'una dall'altra come se ognuna di esse avesse tutta la memoria della macchina per sé.

Ecco alcuni esempi di utilizzo di fork:

  1. La tua shell usa forkper eseguire i programmi che invochi dalla riga di comando.
  2. I server Web come Apache vengono utilizzati forkper creare più processi server, ognuno dei quali gestisce le richieste nel proprio spazio degli indirizzi. Se uno muore o perde memoria, gli altri non vengono influenzati, quindi funziona come un meccanismo per la tolleranza ai guasti.
  3. Google Chrome utilizza forkper gestire ogni pagina all'interno di un processo separato. Ciò impedirà al codice lato client su una pagina di portare inattivo l'intero browser.
  4. forkviene utilizzato per generare processi in alcuni programmi paralleli (come quelli scritti utilizzando MPI ). Nota che questo è diverso dall'uso dei thread , che non hanno il proprio spazio degli indirizzi ed esistono all'interno di un processo.
  5. I linguaggi di scripting vengono utilizzati forkindirettamente per avviare i processi figlio. Ad esempio, ogni volta che usi un comando come subprocess.Popenin Python, sei forkun processo figlio e leggi il suo output. Ciò consente ai programmi di lavorare insieme.

L'utilizzo tipico di forkin una shell potrebbe essere simile a questo:

La shell genera un processo figlio utilizzando exece attende che venga completato, quindi continua con la propria esecuzione. Nota che non devi usare fork in questo modo. Puoi sempre generare molti processi figli, come potrebbe fare un programma parallelo, e ognuno potrebbe eseguire un programma contemporaneamente. Fondamentalmente, ogni volta che stai creando nuovi processi in un sistema Unix, stai usando fork(). Per l'equivalente di Windows, dai un'occhiata a CreateProcess.

Se vuoi più esempi e una spiegazione più lunga, Wikipedia ha un sommario decente. E qui ci sono alcune diapositive su come funzionano i processi, i thread e la concorrenza nei sistemi operativi moderni.


Punto 5: "spesso"? Solo "spesso"? Quali non lo usano, o in quali circostanze fork () non viene usato - su sistemi che supportano fork (), cioè.
Jonathan Leffler

19
Stranamente, si chiama CreateProcess () - quei pazzi ragazzi di Windows :-)
paxdiablo

2
mai realizzato fino ad ora che "la shell usa fork per eseguire i programmi che invocate dalla riga di comando"!
Lazer

1
Il collegamento di Slides è interrotto
piertoni

1
Tutte le risposte dicono che fork()è il modo per creare un nuovo processo in UNIX, ma per essere pedanti, c'è almeno un altro: posix_spawn().
Davislor

15

fork () è il modo in cui Unix crea nuovi processi. Nel punto in cui hai chiamato fork (), il tuo processo viene clonato e due diversi processi continuano l'esecuzione da lì. Uno di loro, il figlio, avrà fork () return 0. L'altro, il genitore, farà fork () restituendo il PID (ID processo) del figlio.

Ad esempio, se digiti quanto segue in una shell, il programma della shell chiamerà fork (), quindi eseguirà il comando che hai passato (telnetd, in questo caso) nel figlio, mentre il genitore mostrerà di nuovo il prompt, pure come messaggio che indica il PID del processo in background.

Per quanto riguarda il motivo per cui crei nuovi processi, è così che il tuo sistema operativo può fare molte cose allo stesso tempo. È per questo che puoi eseguire un programma e, mentre è in esecuzione, passare a un'altra finestra e fare qualcos'altro.


@varDumper Buona cattura!
Daniel C. Sobral

9

fork () viene utilizzato per creare un processo figlio. Quando viene chiamata una funzione fork (), verrà generato un nuovo processo e la chiamata della funzione fork () restituirà un valore diverso per il figlio e il genitore.

Se il valore di ritorno è 0, sai di essere il processo figlio e se il valore di ritorno è un numero (che sembra essere l'id del processo figlio), sai di essere il genitore. (e se è un numero negativo, il fork non è riuscito e non è stato creato alcun processo figlio)

http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html


1
A meno che il valore restituito non sia -1, nel qual caso fork () non è riuscito.
Jonathan Leffler

8

fork () è fondamentalmente usato per creare un processo figlio per il processo in cui stai chiamando questa funzione. Ogni volta che chiami un fork (), restituisce uno zero per l'id figlio.

in questo modo è possibile fornire azioni diverse per il genitore e il bambino e utilizzare la funzionalità di multithreading.


6

fork () creerà un nuovo processo figlio identico al genitore. Quindi tutto ciò che esegui nel codice dopo verrà eseguito da entrambi i processi, molto utile se ad esempio hai un server e desideri gestire più richieste.


perché crei un figlio identico al genitore a che serve?

1
È proprio come costruire un esercito contro un singolo soldato. Esegui il fork in modo che il tuo programma possa gestire più richieste contemporaneamente, invece di una per una.
Cloudhead

fork () restituisce 0 sul bambino e il pid del bambino sul genitore. Il bambino può quindi usare una chiamata come exec () per sostituire il suo stato con un nuovo programma. Ecco come vengono lanciati i programmi.
Todd Gamblin

I processi sono molto vicini all'identico, ma ci sono molte sottili differenze. Le differenze evidenti sono il PID corrente e il PID genitore. Ci sono problemi relativi ai blocchi e ai semafori tenuti. La pagina di manuale di fork () per POSIX elenca 25 differenze tra il genitore e il figlio.
Jonathan Leffler

2
@kar: Una volta che hai due processi, possono continuare separatamente da lì e uno di essi potrebbe sostituire se stesso (exex ()) con un altro programma completamente.
Vatine

4

Probabilmente non è necessario utilizzare fork nella programmazione quotidiana se si scrivono applicazioni.

Anche se vuoi che il tuo programma avvii un altro programma per fare qualche operazione, ci sono altre interfacce più semplici che usano il fork dietro le quinte, come "system" in C e perl.

Ad esempio, se desideri che la tua applicazione avvii un altro programma come bc per eseguire dei calcoli, potresti usare "system" per eseguirlo. Il sistema fa un "fork" per creare un nuovo processo, quindi un "exec" per trasformare quel processo in bc. Al termine di bc, il sistema restituisce il controllo al programma.

Puoi anche eseguire altri programmi in modo asincrono, ma non ricordo come.

Se stai scrivendo server, shell, virus o sistemi operativi, è più probabile che tu voglia utilizzare fork.


Grazie per system(). Stavo leggendo fork()perché voglio che il mio codice C esegua uno script Python.
Bean Taxi

4

Fork crea nuovi processi. Senza fork avresti un sistema unix che potrebbe eseguire solo init.


4

La chiamata di sistema fork () viene utilizzata per creare processi. Non richiede argomenti e restituisce un ID di processo. Lo scopo di fork () è creare un nuovo processo, che diventa il processo figlio del chiamante. Dopo aver creato un nuovo processo figlio, entrambi i processi eseguiranno l'istruzione successiva che segue la chiamata di sistema fork (). Pertanto, dobbiamo distinguere il genitore dal bambino. Questo può essere fatto testando il valore restituito da fork ():

Se fork () restituisce un valore negativo, la creazione di un processo figlio non ha avuto successo. fork () restituisce uno zero al processo figlio appena creato. fork () restituisce un valore positivo, l'ID di processo del processo figlio, al genitore. L'ID processo restituito è di tipo pid_t definito in sys / types.h. Normalmente, l'ID del processo è un numero intero. Inoltre, un processo può utilizzare la funzione getpid () per recuperare l'ID di processo assegnato a questo processo. Pertanto, dopo la chiamata di sistema a fork (), un semplice test può dire quale processo è il figlio. Si noti che Unix farà una copia esatta dello spazio degli indirizzi del genitore e la darà al bambino. Pertanto, i processi padre e figlio hanno spazi di indirizzi separati.

Comprendiamolo con un esempio per chiarire i punti precedenti. Questo esempio non distingue i processi padre e figlio.

Supponiamo che il programma precedente venga eseguito fino al punto della chiamata a fork ().

Se la chiamata a fork () viene eseguita con successo, Unix creerà due copie identiche degli spazi degli indirizzi, una per il genitore e l'altra per il figlio. Entrambi i processi inizieranno la loro esecuzione all'istruzione successiva che segue la chiamata fork (). In questo caso, entrambi i processi inizieranno la loro esecuzione al momento dell'assegnazione

Entrambi i processi iniziano la loro esecuzione subito dopo la chiamata di sistema fork (). Poiché entrambi i processi hanno spazi degli indirizzi identici ma separati, quelle variabili inizializzate prima della chiamata fork () hanno gli stessi valori in entrambi gli spazi degli indirizzi. Poiché ogni processo ha il proprio spazio di indirizzi, qualsiasi modifica sarà indipendente dalle altre. In altre parole, se il genitore cambia il valore della sua variabile, la modifica interesserà solo la variabile nello spazio degli indirizzi del processo genitore. Gli altri spazi di indirizzi creati dalle chiamate fork () non saranno influenzati anche se hanno nomi di variabili identici.

Qual è il motivo dell'utilizzo di write anziché printf? È perché printf () è "bufferizzato", il che significa che printf () raggrupperà insieme l'output di un processo. Durante il buffering dell'output per il processo genitore, il figlio può anche usare printf per stampare alcune informazioni, che verranno anch'esse memorizzate nel buffer. Di conseguenza, poiché l'output non verrà inviato immediatamente allo schermo, potresti non ottenere l'ordine corretto del risultato atteso. Peggio ancora, l'output dei due processi può essere mescolato in modi strani. Per superare questo problema, potresti considerare di utilizzare la scrittura "senza buffer".

Se esegui questo programma, potresti vedere quanto segue sullo schermo:

L'ID processo 3456 può essere quello assegnato al genitore o al figlio. A causa del fatto che questi processi vengono eseguiti contemporaneamente, le loro linee di output sono mescolate in un modo piuttosto imprevedibile. Inoltre, l'ordine di queste righe è determinato dallo scheduler della CPU. Quindi, se esegui di nuovo questo programma, potresti ottenere un risultato completamente diverso.


4
Invece di copiare e incollare il testo avresti potuto commentare un link: csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/create.html
chaitanya lakkundi

3

Il multiprocessing è fondamentale per il computing. Ad esempio, il tuo IE o Firefox possono creare un processo per scaricare un file per te mentre stai ancora navigando in Internet. Oppure, mentre stampi un documento con un elaboratore di testi, puoi comunque guardare pagine diverse e apportare ancora alcune modifiche.


3

Fork () viene utilizzato per creare nuovi processi come ogni corpo ha scritto.

Ecco il mio codice che crea processi sotto forma di albero binario ....... Chiederà di scansionare il numero di livelli fino a cui vuoi creare processi in albero binario

PRODUZIONE


2

Per prima cosa bisogna capire cos'è la chiamata di sistema fork (). Lasciatemi spiegare

  1. La chiamata di sistema fork () crea il duplicato esatto del processo genitore, crea il duplicato di stack genitore, heap, dati inizializzati, dati non inizializzati e condivide il codice in modalità di sola lettura con il processo genitore.

  2. La chiamata di sistema Fork copia la memoria sulla base della copia su scrittura, significa che il bambino crea una pagina di memoria virtuale quando è necessario copiare.

Ora Scopo della forcella ():

  1. Fork () può essere utilizzato nel luogo in cui vi è divisione del lavoro come un server deve gestire più client, quindi il genitore deve accettare la connessione su base regolare, quindi il server esegue il fork per ogni client per eseguire la lettura-scrittura.

1

fork()viene utilizzato per generare un processo figlio. In genere viene utilizzato in tipi di situazioni simili al threading, ma ci sono differenze. A differenza dei thread, fork()crea interi processi separati, il che significa che il bambino e il genitore mentre sono copie dirette l'uno dell'altro nel punto in cuifork() viene chiamato, sono completamente separati, nessuno dei due può accedere allo spazio di memoria dell'altro (senza andare ai normali guai vai per accedere alla memoria di un altro programma).

fork()è ancora utilizzato da alcune applicazioni server, principalmente da quelle eseguite come root su una macchina * NIX che rilascia i permessi prima di elaborare le richieste degli utenti. Ci sono ancora altri casi d'uso, ma ora la maggior parte delle persone è passata al multithreading.


2
Non capisco la percezione che "la maggior parte delle persone" sia passata al multithreading. I processi sono qui per restare, e così sono i thread. Nessuno è "andato avanti" da nessuno dei due. Nella programmazione parallela, i codici più grandi e concorrenti sono programmi multi-processo a memoria distribuita (ad esempio MapReduce e MPI). Tuttavia, la maggior parte delle persone opterebbe per OpenMP o un paradigma di memoria condivisa per una macchina multicore e le GPU utilizzano i thread in questi giorni, ma c'è molto oltre. Scommetto, tuttavia, che più programmatori su questo sito incontrano il parallelismo dei processi sul lato server rispetto a qualsiasi altro multithread.
Todd Gamblin,

1

La logica alla base di fork () rispetto al solo fatto di avere una funzione exec () per avviare un nuovo processo è spiegata in una risposta a una domanda simile sullo scambio di stack unix .

Essenzialmente, poiché fork copia il processo corrente, tutte le varie opzioni possibili per un processo sono stabilite di default, quindi il programmatore non le deve fornire.

Nel sistema operativo Windows, al contrario, i programmatori devono utilizzare la funzione CreateProcess che è MOLTO più complicata e richiede di popolare una struttura multiforme per definire i parametri del nuovo processo.

Quindi, per riassumere, la ragione per il fork (rispetto all'esecuzione) è la semplicità nella creazione di nuovi processi.


0

La chiamata di sistema Fork () viene utilizzata per creare un processo figlio. È il duplicato esatto del processo genitore. Fork copia la sezione stack, la sezione heap, la sezione dati, la variabile di ambiente, gli argomenti della riga di comando dal genitore.

fare riferimento a: http://man7.org/linux/man-pages/man2/fork.2.html


0

La funzione fork () viene utilizzata per creare un nuovo processo duplicando il processo esistente da cui viene chiamato. Il processo esistente da cui viene chiamata questa funzione diventa il processo padre e il processo appena creato diventa il processo figlio. Come già affermato, il bambino è una copia duplicata del genitore ma ci sono alcune eccezioni.

  • Il bambino ha un PID univoco come qualsiasi altro processo in esecuzione nel sistema operativo.

  • Il bambino ha un ID processo genitore che è lo stesso del PID del
    processo che lo ha creato.

  • L'utilizzo delle risorse e i contatori del tempo della CPU vengono azzerati nel processo figlio.

  • Il set di segnali in sospeso nel bambino è vuoto.

  • Il bambino non eredita alcun timer dal genitore

Esempio :

Ora, quando il codice sopra viene compilato ed eseguito:

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.