Provided by: manpages-it-dev_4.13-4_all 

NOME
vfork - crea un processo figlio e blocca il processo genitore
SINTASSI
#include <sys/types.h>
#include <unistd.h>
pid_t vfork(void);
Macro per test di funzionalità per glibc (vedere feature_test_macros(7)):
vfork():
A partire da glibc 2.12:
(_XOPEN_SOURCE >= 500) && ! (_POSIX_C_SOURCE >= 200809L)
|| /* A partire da glibc 2.19: */ _DEFAULT_SOURCE
|| /* Versioni glibc <= 2.19: */ _BSD_SOURCE
Prima di 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.
CONFORME A
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
La chiamata di sistema vfork() è apparsa nella versione 3.0BSD. Nella versione 4.4BSD è diventata
sinonimo di fork(2) ma NetBSD l'ha reintrodotta; si veda http://www.netbsd.org/Documentation/kernel
/vfork.html. In Linux è stata equivalente a fork(2) fino alla versione 2.2.0-pre6. A partire dalla
2.2.0-pre9 (su i386 - un po' più tardi su altre architetture) è una chiamata di sistema indipendente. Il
relativo supporto è stato aggiunto 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)
COLOPHON
Questa pagina fa parte del rilascio 5.10 del progetto Linux man-pages. Una descrizione del progetto, le
istruzioni per la segnalazione degli errori, e l'ultima versione di questa pagina si trovano su
https://www.kernel.org/doc/man-pages/.
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 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.
Linux 15 settembre 2017 VFORK(2)