fork - maak een kind-proces
Standard C bibliotheek (libc, -lc)
#include <unistd.h>
pid_t fork(void);
fork() maakt een nieuw proces aan door het huidige proces
te dupliceren. Het nieuwe proces wordt het kind-proces genoemd. Het huidige
proces wordt het ouder proces genoemd.
Het kind-proces en het ouder-proces draaien in aparte geheugen
ruimten. Tijdens de fork() hebben beide geheugen gebieden dezelfde
inhoud. Schrijven naar geheugen, afbeelden (mmap(2)) en vrijgeven
(munmap(2)) van bestanden door een van de processen
beïnvloeden het andere niet.
Het kind-proces is een exact duplicaat van het ouder-proces
behalve de volgende punten:
- •
- Het kind heeft zijn eigen unieke proces ID en dit PID komt niet overeen
met enig ID van een van de bestaande proces groepen ( (setpgid(2))
of sessie.
- •
- Het ouder proces ID van het kind is hetzelfde als het proces ID van de
ouder.
- •
- Het kind erft het slot op het geheugen niet van de ouder (mlock(2),
mlockall(2)).
- •
- Gebruik van bronnen (getrusage(2)) en de CPU tijd tellers
(times(2)) worden op nul gezet in het kind.
- •
- De verzameling van in afwachting zijnde signalen in kind is leeg
(sigpending(2)).
- •
- Het kind erft geen seinpaal aanpassingen van zijn ouder
(semop(2)).
- •
- Het kind erft geen geassocieerde dossier sloten van zijn ouder
fcntl(2)). (Aan de andere kant erft het wel fnctl(2) de open
bestandsindicator sloten en de flock(2) van zijn ouder.)
- •
- Het kind erft geen timers van zijn ouder (setitimer(2),
alarm(2), timer_create(2)).
- •
- Het kind erft geen uitstaande asynchrone Invoer/Uitvoer operatie van zijn
ouder (aio_read(3), aio_write(3)), noch erft het enige
asynchrone Invoer/Uitvoer contexts van zijn ouder (zie
io_setup(2)).
De proces attributen in de voorafgaande lijst zijn allemaal
gespecificeerd in POSIX.1. De ouder en het kind verschillen op met
betrekking tot de volgende Linux-specifieke proces attributen:
- •
- Het kind erft geen meldingen over verandering in mappen (dnotify) van zijn
ouder (zie de beschrijving van F_NOTIFY in fcntl(2)).
- •
- De prctl(2) PR_SET_PDEATHSIG wordt teruggezet zodat het kind
geen signaal ontvangt wanneer zijn ouder stopt.
- •
- De standaard waarde van de timer speling wordt gezet op de huidige waarde
van de ouder. Zie de beschrijving van PR_SET_TIMERSLACK in
prctl(2).
- •
- De geheugen indelingen die werden gemarkeerd met de madvise(2)
MADV_DONTFORK vlag worden niet overgeërfd langs
fork().
- •
- Geheugen in de adres gebieden die werden gemarkeerd met de
madvise(2) MADV_WIPEONFORK vlag wordt met 0-gevuld in het
kind na de fork(). (DeMADV_WIPEONFORK instelling blijft van
kracht voor deze adres gebieden in het kind)
- •
- Het beëindiging signaal van het kind is altijd SIGCHLD (zie
clone(2)).
- •
- De toegangsrechten bits van de poort gezet door ioperm(2) worden
niet geërfd door het kind; het kind moet de benodigde bits zelf aan
zetten met ioperm(2).
Let op de volgende punten:
- •
- Het kind-proces wordt gemaakt met een enkele thread—die die
fork() aanriep. De complete virtuele adresruimte van de ouder wordt
gekopieerd in het kind, inclusief de statussen van de seinpalen, de
conditie variabelen, en andere pthread objecten; het gebruik van
pthread_atfork(3) kan nuttig zijn tijdens het afhandelen van
problemen die dit kunnen veroorzaken.
- •
- Na een fork() in een multithreaded programma, kan het kind zonder
problemen asynchrone-signaal-veilige functies aanroepen (zie
signal-safety(7)) totdat het moment dat execve(2) wordt
aangeroepen.
- •
- Het kind erft kopieën van de verzameling open bestandsindicatoren
van de ouder. Elke bestandsindicator in het kind wijst naar dezelfde open
bestandsindicator (zie open(2)) als de daarmee overeenkomende
bestandsindicator in de ouder. Dit betekent dat de twee open
bestandsindicatoren dezelfde open bestandsstatus vlaggen delen, de
bestandspositie en de signaal-gedreven Invoer/Uitvoer attributen (zie de
beschrijving van F_SETOWN en F_SETSIG in
fcntl(2)).
- •
- Het kind erft kopieën van de verzameling open bericht
rij-indicatoren van de ouder (zie mq_overview(7)). Elke
bestandsindicator in het kind wijst naar dezelfde open bericht
rij-indicator als de daarmee overeenkomende bestandsindicator in de ouder.
Dit betekent dat de twee bestandsindicatoren dezelfde vlaggen
mq_flags) delen.
- •
- Het kind erft kopieën van de verzameling open map stromen van de
ouder (zie opendir(3)). POSIX.1 schrijft dat de overeenkomende map
stromen in de ouder en het kind dezelfde map stroom posities mogen
delen; op Linux/glibc doen ze dit niet.
Bij succes wordt de PID van het kind-proces teruggegeven aan het
ouder-proces en wordt 0 teruggegeven in het kind-proces. Bij falen wordt -1
teruggegeven aan het ouder-proces, er wordt geen kind-proces gemaakt, en
errno wordt overeenkomstig gezet.
- EAGAIN
- Een door het systeem bepaalde limiet op het aantal threads werd
tegengekomen. Er zijn verschillende limieten die deze fout kunnen
oproepen:
- •
- de RLIMIT_NPROC zachte bron limiet (ingesteld via
setrlimit(2)), die het aantal processen en threads voor het echte
gebruikers ID limiteert, werd bereikt;
- •
- de systeem-brede limiet van de kernel op het aantal processen en threads,
/proc/sys/kernel/threads-max, werd bereikt (zie
proc(5));
- •
- het maximaal aantal PID´s, /proc/sys/kernel/pid_max, werd
bereikt (zie proc(5)); of
- •
- de PID limiet (pids.max) opgelegd door de cgroup "proces
nummer" (PID´s) controller werd bereikt.
- EAGAIN
- De aanroeper werkt onder het SCHED_DEADLINE agendabeheer beleid en
heeft niet de reset-on-fork vlag gezet. Zie sched(7).
- ENOMEM
- fork() faalde in het vrijmaken van de nodige kernel structuren
omdat er te weinig geheugen was.
- ENOMEM
- Een poging werd gedaan om een kind-proces aan te maken in de PID
naamruimte wiens "init" proces werd beëindigd. Zie
pid_namespaces(7).
- ENOSYS
- fork() is niet ondersteund op dit platform (bij voorbeeld: hardware
zonder een Memory-Management Unit).
- ERESTARTNOINTR
(sinds Linux 2.6.17)
- De systeem aanroep werd onderbroken door een signaal en wordt geherstart.
(Dit kan alleen geobserveerd worden tijdens een trace.)
POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.
Onder Linux is fork() geïmplementeerd door gebruik
te maken van copy-on-write pagina´s, de enige straf die dit mee
brengt is de benodigde tijd en hoeveelheid geheugen die nodig is om de
pagina tabellen van de ouder te dupliceren, en om een unieke taak structuur
in het kind te maken.
Vanaf glibc 2.3.3, in plaats van het aanroepen van de
fork() systeem aanroep, roept de glibc fork() omwikkel
functie, die voorzien is als onderdeel van de NPTL threading implementatie,
clone(2) aan met vlaggen die hetzelfde effect geven als de
traditionele systeem aanroep. (Een aanroep van fork() is equivalent
met de aanroep van clone(2) waarbij de flags gespecificeerd
wordt als precies SIGCHLD.) De glibc functie roept enig vork
afhandelaars aan die werden vastgesteld door pthread_atfork(3).
Zie pipe(2) en wait(2) voor meer voorbeelden.
#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("Kind verlaten.");
exit(EXIT_SUCCESS);
default:
printf("Kind is PID %jd\n", (intmax_t) pid);
puts("Ouder verlaten.");
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)
De Nederlandse vertaling van deze handleiding is geschreven door
Jos Boersema <joshb@xs4all.nl>, Mario Blättermann
<mario.blaettermann@gmail.com> en Luc Castermans
<luc.castermans@gmail.com>
Deze vertaling is vrije documentatie; lees de
GNU General
Public License Version 3 of later over de Copyright-voorwaarden. Er is
geen AANSPRAKELIJKHEID.
Indien U fouten in de vertaling van deze handleiding zou vinden,
stuur een e-mail naar
debian-l10n-dutch@lists.debian.org.