Fork (programmazione)

modalità attraverso cui un processo crea in memoria una copia di se stesso

Una fork in programmazione è la modalità attraverso cui un processo crea in memoria una copia di se stesso: la copia prenderà il nome di processo figlio, mentre il processo originale verrà chiamato processo padre.

Nei sistemi operativi UNIX e Unix-like il processo padre ed il processo figlio possono scegliere le istruzioni da eseguire tramite il valore di ritorno della chiamata di sistema fork(). Il valore di ritorno della chiamata fork() vale 0 nel processo figlio, un numero maggiore di 0 nel processo padre (il valore restituito è proprio il PID del figlio) o un valore minore di 0 nel caso in cui non sia stato possibile creare un nuovo processo (ad esempio per un eccessivo numero di processi attualmente attivi).

Quando un processo effettua la chiamata fork() verrà creato un nuovo spazio di indirizzamento. Comunque, con tecniche di copy-on-write non verrà occupata memoria fisica fino al momento in cui uno dei due processi non effettuerà una scrittura. Il processo figlio avrà una copia esatta di tutti i segmenti di memoria del processo padre. Sia il processo padre che il figlio possono proseguire la loro esecuzione indipendentemente l'uno dall'altro.

Importanza della fork() in Unix

modifica

La fork() è una parte importante di Unix, critica per il supporto della sua filosofia di progettazione, la quale incoraggia lo sviluppo di filtri. In Unix, un filtro è un piccolo programma che legge il suo input dallo standard input, e scrive il suo output nello standard output. Una pipeline di questi comandi può essere concatenata insieme da una shell per creare nuovi comandi. Per esempio, è possibile legare insieme l'output del comando find e l'input del comando wc per creare un nuovo comando che stamperà il numero di file che terminano con ".cpp" trovati nella directory corrente, secondo quanto segue:

$ find . -name "*.cpp" -print | wc -l

Per fare ciò la shell effettua una fork() di sé stessa, e usa la pipeline per agganciare l'output del comando find all'input del comando wc. Vengono creati due processi figli, uno per ogni comando (find e wc). Questi processi figli vengono ricoperti con il codice associato ai programmi che intendono eseguire, grazie alla famiglia di chiamate di sistema exec.

Più in generale, una fork() viene eseguita dalla shell ogni qualvolta un utente immette un comando.

Esempio

modifica

Questo è un esempio in Linguaggio C che illustra l'idea del forking in ambiente Unix-like:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main()
{
   int pid; //pid_t pid;

   pid = fork();

   if(pid == 0)
   {
      /* Processo figlio.
       * Se fork() ritorna 0, siamo all'interno 
       * del processo figlio
       * Conteremo fino a dieci, una volta al secondo.
       */
      int j;
      for(j=0; j < 10; j++)
      {
         printf("Figlio: %d\n", j);
         sleep(1);
      }
      _exit(0); /* Notare che non viene usata la exit() */
   }
   else if(pid > 0)
   { 
      /* Processo padre, la fork ha restituito
       * il pid del figlio appena creato.
       * Contiamo ancora fino a dieci.
       */
      int i;
      for(i=0; i < 10; i++)
      {
         printf("Padre: %d\n", i);
         sleep(1);
      }
   }
   else
   {   
      /* Errore. */
      fprintf(stderr, "Errore nel fork");
      exit(1);
   }
   return 0;
}

Un possibile output generato dall'esecuzione del codice:

Figlio: 0
Padre: 0
Figlio: 1
Padre: 1
Figlio: 2
Padre: 2
Figlio: 3
Padre: 3
Figlio: 4
Padre: 4
Figlio: 5
Padre: 5
Figlio: 6
Padre: 6
Figlio: 7
Padre: 7
Figlio: 8
Padre: 8
Figlio: 9
Padre: 9

L'ordine di esecuzione dei processi è determinato dallo scheduler.

Voci correlate

modifica

Collegamenti esterni

modifica
  Portale Informatica: accedi alle voci di Wikipedia che trattano di Informatica