2015-09-27 23 views
17

Di seguito è riportato un esempio della funzione Fork in azione. Di seguito è riportato anche l'output. La mia domanda principale ha a che fare con un fork chiamato come i valori sono cambiati. Quindi pid1,2 e 3 partono da 0 e cambiano quando le forche si verificano. Questo perché ogni volta che si verifica un fork, i valori vengono copiati al figlio e il valore specifico viene modificato nel genitore? In pratica come cambiano i valori con le funzioni della forcella?Funzione Fork() in C

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 

int main() { 
    pid_t pid1, pid2, pid3; 
    pid1=0, pid2=0, pid3=0; 
    pid1= fork(); /* A */ 
    if(pid1==0){ 
     pid2=fork(); /* B */ 
     pid3=fork(); /* C */ 
    } else { 
     pid3=fork(); /* D */ 
     if(pid3==0) { 
      pid2=fork(); /* E */ 
     } 
     if((pid1 == 0)&&(pid2 == 0)) 
      printf("Level 1\n"); 
     if(pid1 !=0) 
      printf("Level 2\n"); 
     if(pid2 !=0) 
      printf("Level 3\n"); 
     if(pid3 !=0) 
      printf("Level 4\n"); 
     return 0; 
    } 
} 

Quindi questa è l'esecuzione.

----A----D--------- (pid1!=0, pid2==0(as initialized), pid3!=0, print "Level 2" and "Level 4") 
    | | 
    | +----E---- (pid1!=0, pid2!=0, pid3==0, print "Level 2" and "Level 3") 
    |   | 
    |   +---- (pid1!=0, pid2==0, pid3==0, print "Level 2") 
    | 
    +----B----C---- (pid1==0, pid2!=0, pid3!=0, print nothing) 
     | | 
     | +---- (pid1==0, pid2==0, pid3==0, print nothing) 
     | 
     +----C---- (pid1==0, pid2==0, pid3!=0, print nothing) 
       | 
       +---- (pid1==0, pid2==0, pid3==0, print nothing) 

Idealmente sotto è come mi piacerebbe vederlo spiegato come in questo modo ha senso per me. I * sono dove risiede la mia principale confusione. Quando il bambino si biforca per esempio pid1 = fork(); che crea un processo con tutti i valori del genitore, ma poi passa un valore come diciamo 1 ai genitori pid1? Significa che il bambino avrebbe pid 1 = 0, pid2 = 0 e pid3 = 0 e il genitore allora come pid1 = 2 e pid2 e 3 uguale a 0? enter image description here

+2

un fork() crea un nuovo processo, che ottiene una copia dei dati principali, come era prima della fork(). Inoltre, un call to fork() può avere tre risultati, non solo 2 o 1 (come sta facendo il codice) i tre risultati sono: <0 significa errore, = 0 significa figlio,> 0 significa genitore. Il codice dovrebbe sempre verificare tutti e tre i risultati. OSSIA questo: 'pid2 = fork();/* B */ pid3 = fork();/* C */'è una cattiva pratica di codifica in quanto non si sa quale processo abbia creato 'C' (in realtà ci saranno 2 dei processi 'C') Considerazioni simili esistono per il processo 'E' – user3629249

+0

bambini 'B' e 'C' mai raggiungere le istruzioni printf() a causa della precedente dichiarazione "if". Solo 'A', 'D' e 'E' raggiungono mai le istruzioni printf(). – user3629249

+0

youtube.com/watch?v=WcsZvdlLkPw in questo il processo genitore ha un valore sovrascritto dall'ID del processo figlio è corretto? – Plisken

risposta

6
int a = fork(); 

crea un processo duplicato "clone?", Che condivide lo stack di esecuzione. La differenza tra genitore e figlio è il valore di ritorno della funzione.

Il figlio riceve 0 restituito e il genitore riceve il nuovo pid.

Ogni volta che vengono copiati gli indirizzi e i valori delle variabili di stack. L'esecuzione continua nel punto in cui è già stata inserita nel codice.

A ogni fork, viene modificato solo un valore - il valore di ritorno da fork.

+0

quindi quello che stai dicendo è che il bambino ottiene i valori del genitore ma restituisce un valore arbitrario al genitore come "1" e questo cambia il valore dei genitori? – Plisken

+0

@plisken, il valore è l'ID di processo per il figlio restituito. Nel sistema operativo, crea una nuova copia della memoria per il processo - tutti gli handle di file, le librerie e la memoria allocata sono esattamente gli stessi. Il sistema operativo imposta quindi il valore di ritorno della funzione fork sul nuovo pid, in modo che il genitore e il figlio ottengano un valore di ritorno pari a 0. La funzione fork è una primitiva. Non può essere scritto in C/C++ a meno che tu non sia il sistema operativo. Venire con lo pseudo codice non avrebbe davvero senso. – mksteve

+0

youtube.com/watch?v=WcsZvdlLkPw in questo il processo genitore ha il valore sovrascritto dall'ID del processo childs è corretto? – Plisken

2

Prima un link ad una documentazione di fork()

http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html

il PID è fornito dal kernel. Ogni volta che il kernel creare un nuovo processo che farà aumentare il contatore PID interno e assegnare il nuovo processo di questo nuovo unico pid e anche assicurarsi che non vi siano duplicati. Una volta che il pid raggiunge un numero elevato, si avvolgerà e ricomincerà.

Quindi non si sa mai quale pid si otterrà da fork(), solo che il genitore manterrà il suo pid univoco e che il fork si assicurerà che il processo figlio abbia un nuovo pid univoco. Questo è indicato nella documentazione fornita sopra.

Se si continua a leggere la documentazione si vedrà che il ritorno fork() 0 per il processo figlio e il nuovo PID unica del bambino verrà restituito al genitore. Se il bambino vuole sapere che è il suo nuovo pid, dovrai interrogarlo usando getpid().

pid_t pid = fork() 
if(pid == 0) { 
    printf("this is a child: my new unique pid is %d\n", getpid()); 
} else { 
    printf("this is the parent: my pid is %d and I have a child with pid %d \n", getpid(), pid); 
} 

e sotto è alcuni commenti in linea sul vostro codice

#include <stdio.h> 
#include <sys/types.h> 
#include <unistd.h> 

int main() { 
    pid_t pid1, pid2, pid3; 
    pid1=0, pid2=0, pid3=0; 
    pid1= fork(); /* A */ 
    if(pid1 == 0){ 
     /* This is child A */ 
     pid2=fork(); /* B */ 
     pid3=fork(); /* C */ 
    } else { 
     /* This is parent A */ 
     /* Child B and C will never reach this code */ 
     pid3=fork(); /* D */ 
     if(pid3==0) { 
      /* This is child D fork'ed from parent A */ 
      pid2=fork(); /* E */ 
     } 
     if((pid1 == 0)&&(pid2 == 0)) { 
      /* pid1 will never be 0 here so this is dead code */ 
      printf("Level 1\n"); 
     } 
     if(pid1 !=0) { 
      /* This is always true for both parent and child E */ 
      printf("Level 2\n"); 
     } 
     if(pid2 !=0) { 
      /* This is parent E (same as parent A) */ 
      printf("Level 3\n"); 
     } 
     if(pid3 !=0) { 
      /* This is parent D (same as parent A) */ 
      printf("Level 4\n"); 
     } 
    } 
    return 0; 
} 
+0

Capisco che, lo faccio. Ma guarda questo https://www.youtube.com/watch?v=WcsZvdlLkPw Il fork passa un valore al genitore, presumibilmente il nuovo id del processo. È corretto? – Plisken

+0

Sì, questo è vero, fork() dirà al genitore quale pid ha il nuovo bambino e l'ho dichiarato.Si prega di consultare anche la documentazione nel link fornito nella sezione "VALORE DI RITORNO" – leakim

+0

Ho letto che apprezzo molto è estremamente utile. Ma questa è la mia ultima domanda. Una volta modificato il valore dei genitori con l'id del processo childs, è necessario modificare altri processi come avviene nel video. – Plisken

19

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

Fork è una chiamata di sistema e non dovreste pensare ad esso come una normale funzione C. Quando si verifica un fork() , si creano effettivamente due nuovi processi con il proprio spazio indirizzo. Variabili inizializzati prima che la chiamata a fork() memorizzi gli stessi valori nello spazio degli indirizzi. Tuttavia, i valori modificati nello spazio degli indirizzi di uno dei due processi rimangono inalterati nell'altro processo uno dei quali è padre e l'altro è secondario. Quindi, se,

pid=fork(); 

Se nei successivi blocchi di codice di controllare il valore di pid.Both processi vengono eseguiti per l'intera lunghezza del codice. Quindi, come li distinguiamo. Ancora Fork è una chiamata di sistema ed ecco la differenza. All'interno del processo figlio appena creato pid memorizzerà 0 mentre nel processo genitore verrà memorizzato un valore positivo. Un valore negativo all'interno di pid indica un errore di fork.

Quando testiamo il valore di pid per scoprire se è uguale a zero o maggiore di quello che stiamo effettivamente scoprendo se siamo nel processo figlio o il processo genitore.

Read more about Fork

+0

La domanda posta era relativa a questo video. https://www.youtube.com/watch?v=WcsZvdlLkPw Perché cambia il valore nel genitore? – Plisken

+0

Fork è una chiamata di sistema. Non appena la chiami. Il processo è duplicato. Nel processo figlio il pid è impostato su zero e nel processo padre il pid riceve un valore positivo. Ora la parte restante del codice è il valore lo stesso per entrambi i processi (stiamo eseguendo lo stesso codice). Quindi, per distinguere tra i processi utilizziamo il valore pid, che come detto in precedenza è separato per child & genitore –

+0

youtube.com/watch?v=WcsZvdlLkPw in questo il il processo genitore ha un valore sovrascritto dall'ID del processo figlio è corretto? – Plisken