plucky (2) vfork.2.gz

Provided by: manpages-it-dev_4.25.1-1_all bug

NOME

       vfork - crea un processo figlio e blocca il processo genitore

LIBRERIA

       Libreria C standard (libc, -lc)

SINTASSI

       #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
                   || /* 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.

VERSIONI

       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.

       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  opportuni
       meccanismi  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  l'hardware
       moderno  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 della memoria (MMU),
          ma fork(2) non può essere implementato  su  tali  sistemi.  (POSIX.1-2008  ha  rimosso  vfork()  dallo
          standard;  nelle  motivazioni di POSIX per la funzione posix_spawn(3) si nota che quella funzione, che
          fornisce  una  funzionalità  equivalente  a  fork(2)+  exec(3),è  progettata  per  poter  essere  resa
          disponibile su sistemi in cui manca una 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).

   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

CONFORME A

       Nulla.

STORIA

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

       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  circa.  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.

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.

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>,   Marco   Curreli
       <marcocurreli@tiscali.it> e Giuseppe Sacco <eppesuig@debian.org>

       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⟩.