Provided by: manpages-it-dev_4.19.0-7_all bug

NOME

       vfork - crea un processo figlio e blocca il processo genitore

LIBRARY

       Standard C library (libc, -lc)

SINTASSI

       #include <unistd.h>

       pid_t vfork(void);

   Macro per test di funzionalità per glibc (vedere feature_test_macros(7)):

       vfork():
           Since glibc 2.12:
               (_XOPEN_SOURCE >= 500) && ! (_POSIX_C_SOURCE >= 200809L)
                   || /* Since glibc 2.19: */ _DEFAULT_SOURCE
                   || /* glibc <= 2.19: */ _BSD_SOURCE
           Before glibc 2.12:
               _BSD_SOURCE || _XOPEN_SOURCE >= 500

DESCRIZIONE

   Descrizione standard
       (Da  POSIX.1)  La funzione vfork() ha lo stesso effetto di fork(2), con l'eccezione che il
       comportamento è indefinito se il processo creato da vfork() modifica un dato qualsiasi che
       non  sia una variabile di tipo pid_t usata per archiviare il valore restituito da vfork(),
       o torna dalla funzione nella quale vfork() è stato  chiamato,  o  chiama  qualunque  altra
       funzione  prima  di  chiamare con successo _exit(2) o una delle funzioni della famiglia di
       exec(3).

   Descrizione Linux
       vfork(), proprio come fork(2),  crea  un  processo  figlio  del  processo  chiamante.  Per
       dettagli sui valori restituiti e sugli errori, vedere fork(2).

       vfork()  è un caso speciale di clone(2). Si usa per creare nuovi processi senza copiare le
       tabelle di paginazione del  processo  genitore.  Può  essere  utile  in  applicazioni  con
       necessità   di  prestazioni  elevate  nelle  quali  verrà  creato  un  figlio  che  emette
       immediatamente un execve(2).

       vfork() è diverso da fork(2) nel senso che il processo chiamante rimane sospeso finché  il
       figlio  non  termina (sia normalmente, chiamando _exit(2), che in modo anormale, dopo aver
       inviato un segnale fatal), o finchè non esegue una  chiamata  a  execve(2).  Fino  a  quel
       momento,  il  figlio condivide la memoria con il genitore, incluso lo stack. Il figlio non
       deve tornare dalla funzione in esecuzione o chiamare exit(3)  (che  avrebbe  l'effetto  di
       attivare i gestori di exit stabiliti dal processo genitore e di svuotare i buffer stdio(3)
       del genitore), ma può chiamare _exit(2).

       Come in fork(2), il processo figlio creato da vfork() eredita copie di vari attributi  del
       processo  chiamante (p.es., descrittori di file, predisposizioni di segnale e la directory
       di lavoro corrente); la chiamata vfork() differisce solo per la gestione dello  spazio  di
       indirizzi virtuale, come sopra descritto.

       I  segnali  inviati al genitore gli arrivano dopo che il figlio ha liberato la memoria del
       genitore (cioè dopo che il figlio termina o chiama execve(2)).

   Descrizione storica
       Sotto Linux, fork(2)  è  implementato  usando  pagine  copy-on-write,  così  che  la  sola
       penalizzazione  in  cui incorre fork(2) è il tempo e la memoria richiesti per duplicare le
       tabelle di paginazione del genitore, e per  creare  un'unica  struttura  di  task  per  il
       figlio.  Tuttavia,  anticamente  fork(2)  richiedeva l'effettuazione di una copia completa
       dello spazio dati del chiamante, spesso senza reale necessità,  di  solito  immediatamente
       dopo  l'esecuzione  di  exec(3). Quindi, per una maggiore efficienza, BSD ha introdotto la
       chiamata di sistema vfork(), che non copiava completamente lo spazio di indirizzamento del
       processo  genitore,  ma utilizzava la memoria del genitore e le sue strutture di controllo
       fino a una chiamata a execve(2) o un exit. Il processo  genitore  era  sospeso  mentre  il
       figlio  utilizzava le sue risorse. L'uso di vfork() non era semplice: per esempio, per non
       modificare i dati nel processo genitore occorreva sapere quali variabili erano  conservate
       in un registro.

STANDARDS

       4.3BSD;  POSIX.1-2001  (ma  segnato come OBSOLETO). POSIX.1-2008 rimuove le specifiche per
       vfork().

       I requisiti indicati per vfork() dagli standard sono più deboli  di  quelli  indicati  per
       fork(2),  così  un'implementazione dove i due sono sinonimi è conforme. In particolare, il
       programmatore non può contare sul fatto che il genitore rimanga bloccato  fino  a  che  il
       figlio  termini  o  chiami  execve(2), e non può contare su alcuno specifico comportamento
       relativo alla memoria condivisa.

NOTE

       Alcuni considerano la semantica di vfork() come un difetto dell'architettura, e la  pagina
       di  manuale  di  4.2BSD  dichiarava:  "Questa  chiamata  di sistema verrà eliminata quando
       saranno implementati  opportunimeccanismi  di  condivisione.  Gli  utenti  non  dovrebbero
       dipendere  dal  metodo di condivisione della memoria di vfork() poiché, a quel punto, esso
       diventerebbe sinonimo di fork(2)." Comunque, anche se il moderno hardware per la  gestione
       della memoria ha ridotto la differenza fra fork(2) e vfork(), ci sono varie ragioni per le
       quali Linux e altri sistemi hanno mantenuto vfork():

       •  Alcune applicazioni in  cui  le  prestazioni  sono  essenziali  richiedono  il  piccolo
          vantaggio in termini di prestazioni garantito da vfork().

       •  BR  vfork  ()può  essere  implementato  su  sistemi  in  cui manca un'unità di gestione
          dellamemoria   (MMU),   ma.BR   fork   (2)non   può   essere   implementato   su   tali
          sistemi.(POSIX.1-2008  ha rimosso.BR vfork ()dallo standard; nelle motivazioni di POSIX
          per la  funzione.BR  posix_spawn  (3)si  nota  che  quella  funzione,che  fornisce  una
          funzionalità  equivalente  a.BR  fork  (2)+ exec (3),è progettata per poter essere resa
          disponibile su sistemi in cui manca MMU).

       •  Su sistemi con memoria limitata,  vfork()  evita  la  necessità  di  impegnare  memoria
          temporaneamente  (si  veda la descrizione di /proc/sys/vm/overcommit_memory in proc(5))
          per l'esecuzione di un nuovo progamma. (Questo può essere  particolarmente  vantaggioso
          nel  caso  di  un  grosso processo genitore che voglia eseguire un piccolo programma di
          supporto in un processo figlio.)  Per  contrasto,  usare  fork(2)  in  questo  scenario
          richiede  l'impegno  di  una  quantità  di  memoria  pari  alla dimensione del processo
          genitore (se è attivo lo strict overcommitting) oppure una sovrallocazione  di  memoria
          col rischio che un processo venga terminato dal processo killer out-of-memory (OOM).

   Avvertimenti
       Il  processo  figlio  dovrebbe  far attenzione di non modificare la memoria in maniera non
       permessa, poiché tali modifiche saranno utilizzabili dal processo genitore una  volta  che
       il  processo  figlio  termina  o  esegue  un altro programma. A tal riguardo, i gestori di
       segnale possono essere particolarmente problematici:  se  un  gestore  di  segnale  che  è
       invocato  nel  processo  figlio di vfork() modifica la memoria, questi cambiamenti possono
       determinare uno stato del processo contradditorio, visto dalla  prospettiva  del  processo
       genitore  (p.es.,  le  modifiche di memoria sarebbero visibili nel processo genitore, ma i
       cambiamenti allo stato dei descrittori di file aperti non sarebbero visibili).

       Quando vfork() viene chiamato in un processo multithread, viene  sospeso  solo  il  thread
       (processo)  chiamante  fino  a  quando  il  processo  figlio non termina o esegue un nuovo
       programma.  Questo significa che  il  processo  figlio  sta  condividendo  uno  spazio  di
       indirizzamento  con  altro  codice in esecuzione. Questo può essere pericoloso se un altro
       thread nel processo genitore  cambia  le  credenziali  di  accesso  alle  risorse  (usando
       setuid(2)  o  simili),  poiché a quel punto ci sono due processi con differenti livelli di
       privilegio in esecuzione in un unico spazio di indirizzamento. Come esempio dei rischi, si
       supponga  che  un  programma  multithread  in esecuzione come root crei un processo figlio
       usando vfork(). Dopo il vfork(), un thread nel processo genitore  cambia  l'autorizzazione
       del  processo  a  quella  di  un utente senza privilegi per eseguire del codice non sicuro
       (p.es., eseguendo un plug-in  aperto  con  dlopen(3)).  In  questo  caso,  sono  possibili
       attacchi  in  cui  il processo genitore usa mmap(2) per mappare del codice che sarà quindi
       eseguito dal processo figlio in modalità privilegiata.

   Note Linux
       I gestori di fork definiti usando pthread_atfork(3) non sono chiamati quando un  programma
       multithread  che  impiega  le  chiamate  alla libreria di threading NPTL chiama vfork(). I
       gestori di fork sono invece chiamati da un programma che  usi  la  libreria  di  threading
       LinuxThreads.  (Vedere  pthreads(7)  per  una  descrizione  delle librerie di threading di
       Linux).

       Una chiamata a vfork() è equivalente a una chiamata a clone(2) con flag definite come:

            CLONE_VM | CLONE_VFORK | SIGCHLD

   Storia
       The vfork()  system call appeared in 3.0BSD.  In 4.4BSD it was made synonymous to  fork(2)
       but   NetBSD   introduced   it   again;   see  ⟨http://www.netbsd.org/Documentation/kernel
       /vfork.html⟩.  In Linux, it has been equivalent to fork(2)  until Linux 2.2.0-pre6 or  so.
       Since  Linux  2.2.0-pre9  (on  i386,  somewhat  later  on  other  architectures)  it is an
       independent system call.  Support was added in glibc 2.0.112.

BUG

       I dettagli sulla gestione del segnale sono oscuri e  diversi  da  sistema  a  sistema.  La
       pagina  di  manuale  di  BSD  afferma: "Per evitare una possibile situazione di stallo, ai
       processi che sono figli non vengono mai inviati, nel mezzo di un vfork(), segnali  SIGTTOU
       o SIGTTIN; invece, output o ioctls sono permessi e i tentativi di input restituiscono come
       risultato un'indicazione di fine file."

VEDERE ANCHE

       clone(2), execve(2), _exit(2), fork(2), unshare(2), wait(2)

TRADUZIONE

       La traduzione italiana di questa pagina di  manuale  è  stata  creata  da  Giulio  Daprelà
       <giulio@pluto.it>,    Elisabetta    Galli    <lab@kkk.it>,    Antonio   Giovanni   Colombo
       <azc100@gmail.com> e Marco Curreli <marcocurreli@tiscali.it>

       Questa traduzione è documentazione libera; leggere la GNU General Public License  Versione
       3 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ o successiva per le condizioni di copyright.
       Non ci assumiamo alcuna responsabilità.

       Per segnalare errori nella traduzione di questa pagina di manuale inviare un  messaggio  a
       ⟨pluto-ildp@lists.pluto.it⟩.