fork - crea un processo figlio
Standard C library (
libc,
-lc)
#include <unistd.h>
pid_t fork(void);
fork() crea un nuovo processo duplicando il processo chiamante. Il nuovo
processo è chiamato processo
figlio. Il processo chiamante
è chiamato processo
genitore.
Il processo figlio e il processo genitore vengono eseguiti in spazi di memoria
separati. Al momento della chiamata
fork() entrambi gli spazi di
memoria hanno lo stesso contenuto. Scritture in memoria, mappature di file (
mmap(2)), e rimozioni di mappature (
munmap(2)) effettuate da uno
dei processi non hanno effetto sull'altro.
Il processo figlio è un esatto duplicato del processo genitore, tranne
che per i seguenti punti:
- •
- Il processo figlio ha il suo ID unico di processo, e questo
PID non corrisponde all'ID di nessun gruppo di processi esistente (
setpgid(2)).
- •
- L'ID di processo-genitore del processo figlio è
uguale all'ID di processo del genitore.
- •
- Il processo figlio non eredita i blocchi di memoria del suo
genitore ( mlock(2), mlockall(2)).
- •
- L'utilizzo delle risorse di processo (getrusage(2))
e i contatori del tempo CPU ( times(2)) sono reimpostati a zero nel
processo figlio.
- •
- Il set di segnali in attesa nel processo figlio è
inizialmente vuoto ( sigpending(2)).
- •
- Il processo figlio non eredita le regolazioni dei semafori
dal suo genitore ( semop(2)).
- •
- Il processo figlio non eredita dal genitore i blocchi sui
record associati ai processi ( fcntl(2)). (D'altra parte, esso non
eredita i blocchi delle descrizioni dei file aperti fcntl(2) e i
blocchi flock(2) dal suo genitore.)
- •
- Il processo figlio non eredita i temporizzatori dal
genitore ( setitimer(2), alarm(2),
timer_create(2)).
- •
- Il processo figlio non eredita le operazioni rilevanti di
I/O asincrono dal suo genitore ( aio_read(3), aio_write(3)),
né eredita alcun contesto di I/O asincrono dal suo genitore (vedere
io_setup(2)).
Gli attributi del processo nel precedente elenco sono tutti specificati in
POSIX.1. Genitore e figlio inoltre sono differenti tra loro rispetto ai
seguenti attributi dei processi specifici di Linux:
- •
- Il processo figlio non eredita le notifiche di cambio
directory (dnotify) dal suo genitore (si veda la descrizione di
F_NOTIFY in fcntl(2)).
- •
- Le impostazioni di prctl(2) PR_SET_PDEATHSIG
sono azzerate in modo che il processo figlio non riceva un segnale quando
il suo genitore termina.
- •
- Il valore predefinito della tolleranza del temporizzatore
(timer slack) è impostato al valore corrente della tolleranza del
genitore. Si veda la descrizione di PR_SET_TIMERSLACK in
prctl(2).
- •
- Le mappe di memoria che sono state marcate con l'opzione
madvise(2) MADV_DONTFORK non sono ereditate attraverso un
fork().
- •
- La memoria negli intervalli di indirizzi che sono stati
marcati con l'opzione madvise(2) MADV_WIPEONFORK viene
azzerata nel processo figlio dopo un fork(). (Il flag
MADV_WIPEONFORK rimane impostato per quegli stessi intervalli di
indirizzi anche nel processo figlio.)
- •
- Il segnale di termine del processo figlio è sempre
SIGCHLD (vedere clone(2)).
- •
- I bit dei permessi della porta di accesso impostati da
ioperm(2) non vengono ereditati dal processo figlio; il processo
figlio deve rendere attivo ogni bit che è richiesto richiesto
usando ioperm(2).
Notare i seguenti punti ulteriori:
- •
- The child process is created with a single
thread—the one that called fork(). The entire virtual
address space of the parent is replicated in the child, including the
states of mutexes, condition variables, and other pthreads objects; the
use of pthread_atfork(3) may be helpful for dealing with problems
that this can cause.
- •
- Dopo un fork() in un programma che esegue thread
multipli, il processo figlio può chiamare in modo sicuro solo le
funzioni async-signal-safe (vedi signal-safety(7)) fino a quando
non chiama execve(2).
- •
- Il processo figlio eredita copie del set di descrittori del
file aperto del genitore. Ciascun descrittore di file nel processo figlio
fa riferimento alla stessa descrizione di file aperto (vedere
open(2)) come corrispondente descrittore di file nel genitore.
Questo significa che i due descrittori di file condividono le opzioni di
stato del file aperto, gli offset correnti del file, e gli attributi degli
I/O pilotati dai segnali (vedere la descrizione di F_SETOWN e
F_SETSIG in fcntl(2)).
- •
- Il processo figlio eredita copie del set di descrittori
della coda dei messaggi aperti del genitore (vedere
mq_overview(7)). Ciascun descrittore di file nel processo figlio fa
riferimento alla stessa descrizione della coda di messaggi aperti del
corrispondente descrittore di file nel genitore. Questo significa che i
due descrittori di file condividono le stesse opzioni (
mq_flags).
- •
- Il processo figlio eredita copie del set di flussi di
directory aperti dal genitore (vedere opendir(3)). POSIX.1-2001
dice che i corrispondenti flussi di directory nel genitore e nel processo
figlio possono condividere il posizionamento dei flussi di
directory; in Linux/glicb non lo fanno.
In caso di successo il PID del processo figlio viene restituito nel genitore, e
viene restituito 0 nel processo figlio. In caso di fallimento verrà
restituito -1 nel genitore, non verrà creato alcun processo figlio, e
errno verrà impostata per indicare l'errore.
- EAGAIN
- È stato raggiunto un limite imposto dal sistema sul
numero di thread. Ci sono diversi limiti che possono causare questo
errore:
- •
- è stato raggiunto il limite delle risorse soft
RLIMIT_NPROC (impostato con setrlimit(2)), che limita il
numero di processi e di thread per l'ID dell'utente reale;
- •
- è stato raggiunto il limite di sistema del kernel
sul numero di processi e di thread, /proc/sys/kernel/threads-max
(vedi proc(5));
- •
- o è stato raggiunto il mumero massimo di PID,
/proc/sys/kernel/pid_max (vedi proc(5)); o
- •
- è stato raggiunto il limite PID (pids.max)
imposto dal controller cgroup del "process number" (PIDs).
- EAGAIN
- Il chiamante sta operando sotto le regole di pianificazione
dei processi SCHED_DEADLINE e non ha l'opzione reset-on-fork
impostato. Vedi sched(7).
- ENOMEM
-
fork() non è stato possibile allocare le
strutture necessarie del kernel perché c'è poca
memoria.
- ENOMEM
- È stato fatto un tentativo per creare un processo
figlio in uno spazio dei nomi PID il cui processo "init"
è terminato. Vedi pid_namespaces(7).
- ENOSYS
-
fork() non è supportato su questa piattaforma
(per esempio, hardware senza una Memory-Management Unit).
-
ERESTARTNOINTR (da Linux 2.6.17)
- La chiamata di sistema è stata interrotta da un
segnale e sarà riavviata. (Questo può essere visto solo dopo
un tracciamento.)
POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.
Sotto Linux,
fork() è implementato usando pagine copy-on-write, in
modo che la sola penalità nella quale incorre sia il tempo e la memoria
necessari per duplicare le page table del genitore, e per creare una struttura
di task unica per il processo figlio.
Since glibc 2.3.3, rather than invoking the kernel's
fork() system call,
the glibc
fork() wrapper that is provided as part of the NPTL threading
implementation invokes
clone(2) with flags that provide the same effect
as the traditional system call. (A call to
fork() is equivalent to a
call to
clone(2) specifying
flags as just
SIGCHLD.) The
glibc wrapper invokes any fork handlers that have been established using
pthread_atfork(3).
See
pipe(2) and
wait(2) for more examples.
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main(void)
{
pid_t pid;
if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
perror("signal");
exit(EXIT_FAILURE);
}
pid = fork();
switch (pid) {
case -1:
perror("fork");
exit(EXIT_FAILURE);
case 0:
puts("Child exiting.");
exit(EXIT_SUCCESS);
default:
printf("Child is PID %jd\n", (intmax_t) pid);
puts("Parent exiting.");
exit(EXIT_SUCCESS);
}
}
clone(2),
execve(2),
exit(2),
setrlimit(2),
unshare(2),
vfork(2),
wait(2),
daemon(3),
pthread_atfork(3),
capabilities(7),
credentials(7)
La traduzione italiana di questa pagina di manuale è stata creata da
Giulio Daprelà <
[email protected]>, Elisabetta Galli
<
[email protected]> e Marco Curreli <
[email protected]>
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
[email protected]