wait(2) System Calls Manual wait(2) NAAM wait, waitpid, waitid - wacht op toestand verandering in een proces BIBLIOTHEEK Standard C bibliotheek (libc, -lc) SAMENVATTING #include pid_t wait(int *wstatus); pid_t waitpid(pid_t pid, int *_NULL_baarwstatus, int opties); int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int opties); /* Dit is het glibc en POSIX interface; zie OPMERKING voor informatie over de ruwe systeem aanroep. */ Feature Test Macro's eisen in glibc (zie feature_test_macros(7)): waitid(): Vanaf glibc 2.26: _XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200809L glibc 2.25 en eerder: _XOPEN_SOURCE || /* Vanaf glibc 2.12: */ _POSIX_C_SOURCE >= 200809L || /* Glibc <= 2.19: */ _BSD_SOURCE BESCHRIJVING Al deze systeem aanroepen worden gebruikt om te wachten op een toestandsverandering in een kind van het aanroepende proces en verkrijgen informatie over het kind wiens toestand werd veranderd. Een toestandsverandering wordt gezien als: het kind werd beeindigd; het kind werd beeindigd door een signaal; of het kind werd hervat door een signaal. In het geval van een beeindigd kind, het uitvoeren van een "wacht" maakt het mogelijk dat het systeem de hulpbronnen die geassocieerd zijn met het kind kunnen vrijgeven; als de "wacht" niet wordt uitgevoerd, dan blijft het beeindigde kind een een "zombie" toestand (zie OPMERKINGEN hieronder). Als een kind al van toestand is veranderd, dan keren deze aanroepen meteen terug. Anders zouden ze blokkeren totdat een kind van toestand verandert of een signaal verwerker interrumpeert de aanroep (aannemende dat systeem aanroepen niet automatisch geherstart worden gebruik makende van de SA_RESTART vlag van sigaction(2)). In de rest van deze pagina:een kind waarvan de toestand werd veranderd en waarop niet gewacht werd door een van de systeem aanroepen wordt aangeduid als waitable. wait() and waitpid() De wait() systeem aanroep schort het uitvoeren van de huidige thread op totdat een van zijn kinderen eindigt. De aanroep wait(&wstatus) is equivalent aan: waitpid(-1, &wstatus, 0); De waitpid() systeem aanroep schort het uitvoeren van de huidige thread op tot dat een kind gespecificeerd door pid argument is veranderd van toestand. Standaard wacht waitpid() alleen op beeindigde kinderen, maar is dit gedrag aanpasbaar via het opties argument, zoals hieronder beschreven. De waarde van pid kan een van de volgende zijn: < -1 wat betekend dat er gewacht wordt op elk kind proces van wie de proces groep ID gelijk is aan de absolute waarde van pid. -1 wat betekent wacht op een kind proces. 0 wat betekend dat er gewacht wordt op elk kind proces van wie het proces groep ID gelijk is aan dat van het aanroepende proces ten tijde van de aanroep van waitpid(). > 0 wat betekend dat er gewacht wordt op elk kind van wie het proces ID gelijk is aan de waarde van pid. De waarde van opties is een OF (incl.) van nul of meer van de volgende constanten: WNOHANG betekend dat er onmiddellijk wordt teruggekeerd als geen kind beeindigd was. WUNTRACED keer ook terug als het kind werd beeindigd (maar niet getraceerd via ptrace(2)). In de status van traced kinderen die werden beeindigd wordt voorzien, zelfs als deze optie niet werd opgegeven. WCONTINUED (sinds Linux 2.6.10) keer ook terug als een beeindigd kind werd hervat door het afleveren van SIGCONT. (Zie hieronder voor de alleen-Linux opties.) Als wstatus niet NULL is, dan slaan wait() en waitpid() status informatie op in de int naar welk het wijst. Dit geheel getal kan worden ingezien met de volgende macro's (die het geheel getal zelf als argument gebruiken, niet de wijzer er naar toe, zoals gedaan in wait() en waitpid()!): WIFEXITED(wstatus) retourneert "waar" als het kind normaal beeindigde, dat is, door het aanroepen van exit(3) of _exit(2), of door terug te keren uit main(). WEXITSTATUS(wstatus) retourneert de terugkeer status van het kind. Deze bestaat uit de minst belangrijke 8 bits van het status argument dat het kind specificeerde in een aanroep van exit(3) of _exit(2) of als het argument van een return statement in main(). Deze macro moet alleen gebruikt worden als WIFEXITED een "waar" terug gaf. WIFSIGNALED(wstatus) geeft "waar" terug als het proces eindigde door een signaal. WTERMSIG(wstatus) geeft het nummer van het signaal dat ervoor zorgde dat het kind proces eindigde. Deze macro kan alleen gebruikt worden als WIFSIGNALED "waar" terug gaf. WCOREDUMP(wstatus) retourneert "waar" als het kind een core dump produceerde (zie core(5)). Deze macro kan alleen gebruikt worden als WIFSIGNALED "waar" terug gaf. Deze macro is niet gespecificeerd in POSIX.1-2001 en is niet beschikbaar in enkele UNIX implementaties (b.v. AIX, SunOS). Daarom, sluit zijn gebruik binnen #ifdef WCOREDUMP ... #endif in. WIFSTOPPED(wstatus) geeft "waar" terug als het kind proces werd beeindigd door het afleveren van een signaal; dit is alleen mogelijk als de aanroep werd gedaan met WUNTRACED of wanneer het kinderen wordt getraceerd (zie ptrace(2)). WSTOPSIG(wstatus) geeft het nummer van het signaal dat ervoor zorgde dat het kind stopte. Deze macro kan alleen afgehandeld worden als WIFSTOPPED ongelijk-nul teruggaf. WIFCONTINUED(wstatus) (vanaf Linux 2.6.10) geeft "waar" terug als het kind werd hervat door het aanleveren van SIGCONT. waitid() De waitid() systeem aanroep (beschikbaar vanaf Linux 2.6.9.) geeft preciezere controle over het wachten op toestandsveranderingen van kinderen De idtype en id argumenten selecteren de kind(eren) om op te wachten, als volgt: idtype == P_PID Wacht op het kind wiens proces ID overeenkomt met id. idtype == P_PID (vanaf Linux 5.4) Wacht op het kind gerefereerd door de PID bestands beschrijving gespecificeerd in id. (Zie pidfd_open(2) voor verdere informatie over PID bestands beschrijvers.) idtype == P_PGID Wacht op enig kind wiens proces groep ID overeenkomt met id. Vanaf Linux 5.4, als id is NUL, dan wacht op enig kind dat tot dezelfde proces groep zit als de proces groep van de aanroeper ten tijde van de aanroep. idtype == P_ALL Wacht op enig kind; id wordt geignoreerd. De kind status veranderingen om te wachten worden gespecificeerd door OF'en van een of meer van de volgende vlaggen in opties: WEXITED Wacht op kinderen die zijn beeindigd. WSTOPPED Wacht op kinderen die zijn gestopt door het leveren van een signaal. WCONTINUED Wacht op (eerder gestopte) kinderen die zijn hervat door het aanleveren van SIGCONT. De volgende vlaggen mogen additioneel worden geOF'd in opties: WNOHANG Zoals voor waitpid(). WNOWAIT Laat het kind in een wachtbare status; een latere "wait"-aanroep kan opnieuw gebruikt worden om de status van het kind op te vragen. Bij een succesvolle terugkeer, waitid() vult de volgende velden van de siginfo_t structure aangewezen door infop: si_pid Het proces ID van het kind. si_uid Het effectieve gebruiker ID van het kind. (Dit veld is niet gezet op de meeste andere implementaties.) si_signo Altijd gezet op SIGCHLD. si_status Ofwel de retour status van het kind, zoals mee gegeven aan _exit(2) (of exit(3)), ofwel het signaal de veroorzaakte het kind te beeindigen, stoppen of doorgaan. Het si_code veld kan worden gebruikt om te bepalen hoe dit veld te interpreteren. si_code Zet op een van: CLD_EXITED (kind roep aan _exit(2)); CLD_KILLED (kind beeindigd door signaal); CLD_DUMPED (kind beeindigd door signaal, en dumpte core); CLD_STOPPED (kind gestopt door signaal); CLD_TRAPPED (getraceerd kind zit vast); or CLD_CONTINUED (kind vervolgt door SIGCONT). Als WNOHANG werd opgegeven in opties en er waren geen kinderen in een wacht toestand, dan geeft waitid() meteen 0 terug and de status van de siginfo_t structure aangewezen door infop hangt af van de implementatie. Om (overdraagbaar) dit geval te onderscheiden van die waar een kind zich in een wacht toestand bevond, maak dan het si_pid veld nul voor de aanroep en controleer op een niet-nul waarde in dit veld nadat de aanroep terugkeerde. POSIX.1-2008 Technical Corrigendum 1 (2013) voegt de eis toe dat wanneer WNOHANG werd gespecificeerd in opties en er waren geen kinderen wacht toestand, dan zou waitid() de si_pid en si_signo velden nul moeten maken. Op Linux en andere implementaties die aan deze eis voldoen, is het niet noodzakelijk om het si_pid veld nul te maken voor het aanroepen van waitid(). Echter volgen niet alle implementaties de POSIX.1 specificatie op dit punt. EIND WAARDE wait(): bij succes, retourneert het proces ID van het beeindigde kind; bij falen wordt een -1 teruggegeven. waitpid(): bij succes, retourneert het proces ID van het kind waarvan de status werd veranderd; als WNOHANG gebruikt werd en een of meer kind(eren) aangeduid door pid bestaan, maar hebben hun toestand niet verandert, dan wordt nul teruggegeven. Bij een fout wordt -1 teruggegeven. waitpid(): geeft 0 terug bij succes of als WNOHANG werd opgegeven en geen kind(eren) aangeduid door id is nog niet van toestand veranderd; bij een fout wordt -1 teruggegeven. Bij falen, zal elk van deze aanroepen errno zetten om de fout aan te duiden. FOUTEN EAGAIN De PID bestandsindicator gespecificeerd in id is niet-blokkerend en het proces dat er naar verwijst werd niet beeindigd. ECHILD (voor wait()) Het aanroepende proces heeft geen enkel kind waarop gewacht wordt. ECHILD (voor waitpid() of waitid()) Het proces gespecificeerd door pid (waitpid()) of idtype en id (waitid()) bestaat niet of is geen kind van het aanroepende proces. (Dit kan gebeuren als het eigen kind als de actie voor SIGCHLD is gezet op SIG_IGN. Zie ook de Linux Opmerkingen sectie over threads.) EINTR WNOHANG was is niet gezet en een gedeblokkeerd signaal of een SIGCHLD werd ontvangen; zie signal(7). EINVAL Het opties argument was ongeldig. ESRCH (voor wait() of waitpid()) pid is gelijk aan INT_MIN. VERSIES C library/kernel verschillen wait() is eigenlijk een bibliotheek functie die (in glibc) is geimplementeerd als een aanroep naar wait4(2). Op sommige architecturen, is er geen waitpid() systeem aanroep; in plaats daarvan, is dit interface geimplementeerd door een C bibliotheek omwikkel functie die wait4(2) aanroept. De ruwe waitid() systeem aanroep gebruikt het vijfde argument, van het type struct rusagefP. Als dit argument niet-NULL is, dan wordt het gebruikt om hulpbron informatie over het kind te retourneren, op dezelfde manier als wait4(2). Zie getrusage(2) voor details. VOLDOET AAN POSIX.1-2008. GESCHIEDENIS SVr4, 4.3BSD, POSIX.1-2001. OPMERKINGEN Een kind dat stopt, maar waar niet op gewacht is wordt een "zombie". De kernel onderhoudt een minimale verzameling van informatie over het zombie proces (PID, beeindiging status, hulpbron gebruik informatie) om de ouder in staat te stellen om later te wachten om de informatie over het kind te verkrijgen. Zolang de zombie niet werd verwijderd door te wachten, zal het een item in de proces tabel van de kernel in beslag nemen, en als deze tabel vol is, is het niet meer mogelijk om meer processen te creeren. Als een ouder proces beeindigd, dan zullen zijn "zombie"kinderen (als die er zijn) worden geadopteerd door init(1), (of door het dichtstbijzijnde "maaimachine" proces zoals gedefinieerd door het gebruik van de prctl(2) PR_SET_CHILD_SUBREAPER operatie); init(1) voert automatisch een wacht uit om zombies te verwijderen. POSIX.1-2001 specificeert dat als een dispositie van SIGCHLD is gezet op SIG_IGN of de SA_NOCLDWAIT vlag is gezet voor SIGCHLD (zie sigaction(2)), dan zullen kinderen die eindigen geen zombies worden en een aanroep van wait() of waitpid() zal blokkeren totdat alle kinderen beeindigd zijn, en vervolgens falen met errno gezet op ECHILD. (De originele POSIX standaard liet het gedrag van het zetten van SIGCHLD op SIG_IGN ongespecificeerd. Let op dat zelfs als de standaard dispositie van SIGCHLD "negeer" is, dan zal het expliciet zetten van de dispositie op SIG_IGN resulteren in een andere behandeling van zombie proces kinderen.) Linux 2.6 voldoet aan de POSIX eisen. Hoewel Linux 2.4 (en eerder) dat niet deed: als een wait() of waitpid() aanroep wordt gedaan terwijl SIGCHLD wordt geignoreerd, dan gedraagt de aanroep zich alsof SIGCHLD niet geignoreerd werd, dat betekend, de aanroep blokkeert totdat het volgende kind stopt en vervolgens het proces ID en de status van dat kind teruggeeft. Linux notities In de Linux kernel, een kernel-thread is niet anders van constructie dan een proces. In plaats daarvan, is een thread eenvoudig weg een proces dat werd aangemaakt door de Linux-unieke clone(2) systeem aanroep; andere routines zoals de overdraagbare pthread_create(3) aanroep zijn geimplementeerd met clone(2). Voor Linux 2,4 was een thread slechts een speciaal geval van een proces, met als consequentie dat een thread niet kon wachten op kinderen of een andere thread, zelfs wanneer de laatste tot dezelfde thread groep behoorde. Echter, schrijft POSIX wel deze functionaliteit voor, en vanaf Linux 2.4 kan een thread, en doet dat ook standaard, wachten op kinderen of andere thread in dezelfde thread groep. De volgende Linux-specifieke opties zijn alleen van toepassing op kinderen aangemaakt door clone(2); die kunnen ook gebruikt worden, sinds Linux 4.7, met waitid(): __WCLONE Wacht alleen op "kloon" kinderen. Als weggelaten, wacht dan alleen op "niet-kloon" kinderen. (Een "kloon"kind is er een dat geen signaal levert, of een signaal anders dan SIGCHLD aan zijn ouder bij beeindiging.) Deze optie wordt genegeerd als _WALL ook werd gespecificeerd. __WALL (sinds Linux 2.4) Wacht op alle kinderen, van welk type ("kloon" of "niet-kloon") dan ook. __WNOTHREAD (sinds Linux 2.4) Wacht niet op kinderen of andere threads in dezelfde thread groep. Dit was standaard voor Linux 2.4. Vanaf Linux 4.7, is de __WALL vlag automatisch inbegrepen als het kind wordt ge-"ptraced". BUGS Volgens POSIX.1-2008 moet een applicatie die waitid() aanroept er voor zorgen dat infop wijst naar een siginfo_t structure (m.a.w. dat het een niet-null wijzer is). Op Linux, als infop gelijk is aan NULL, dan is waitid() succesvol en retourneert het proces ID van het kind waarop gewacht wordt. Applicaties moeten vermijden op dit inconsistent, niet-standaard en onnodige kenmerk te vertrouwen. VOORBEELDEN Het volgende programma demonstreert het gebruik van fork(2) en waitpid(). Het programma creeert een kind proces. Als geen commando regel argument mee gegeven werd naar het programma, dan schort het kind zijn uitvoer op door pause(2) te gebruiken, om zo toe te staan dat de gebruiker signalen naar het kind kan sturen. Anders, als wel een commando regel argument werd mee gegeven, dan stop het kind onmiddellijk, en gebruikt het gehele getal mee gegeven op de commando regel als de uitvoer status. Het ouder proces voert een lus uit die het kind door gebruik van waitpid() monitort, en gebruikt de W*() macros, zoals hierboven beschreven, om de wacht status waarde te analyseren. De volgend shell sessie demonstreert het gebruik van het programma: $ ./a.out & Child PID is 32360 [1] 32359 $ kill -STOP 32360 stopped by signal 19 $ kill -CONT 32360 continued $ kill -TERM 32360 killed by signal 15 [1]+ Done ./a.out $ Programma bron #include #include #include #include #include #include int main(int argc, char *argv[]) { int wstatus; pid_t cpid, w; cpid = fork(); if (cpid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (cpid == 0) { /* Code executed by child */ printf("Child PID is %jd\n", (intmax_t) getpid()); if (argc == 1) pause(); /* Wait for signals */ _exit(atoi(argv[1])); } else { /* Code executed by parent */ do { w = waitpid(cpid, &wstatus, WUNTRACED | WCONTINUED); if (w == -1) { perror("waitpid"); exit(EXIT_FAILURE); } if (WIFEXITED(wstatus)) { printf("exited, status=%d\n", WEXITSTATUS(wstatus)); } else if (WIFSIGNALED(wstatus)) { printf("killed by signal %d\n", WTERMSIG(wstatus)); } else if (WIFSTOPPED(wstatus)) { printf("stopped by signal %d\n", WSTOPSIG(wstatus)); } else if (WIFCONTINUED(wstatus)) { printf("continued\n"); } } while (!WIFEXITED(wstatus) && !WIFSIGNALED(wstatus)); exit(EXIT_SUCCESS); } } ZIE OOK _exit(2), clone(2), fork(2), kill(2), ptrace(2), sigaction(2), signal(2), wait4(2), pthread_create(3), core(5), credentials(7), signal(7) VERTALING De Nederlandse vertaling van deze handleiding is geschreven door Jos Boersema , Mario Blattermann en Luc Castermans 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 . Linux man-pages 6.9.1 15 juni 2024 wait(2)