====== Fork ====== * fork() slouží ke spuštění další instance procesu vytvořením kopie včetně aktuálního kontextu * oba procesy pokračují v kódu od místa zavolání funkce fork * proces pozná, zda je potomek nebo rodič, podle návratové hodnoty fork pid_t pid = fork(); if (pid<0) { // failed } if (pid == 0) { // child } else { // parent } * pokud je ukončen rodičovský proces, z potomka se stane sirotek (orphan) * pokud je ukončen potomek před rodičem, stává se nemrtvým (zombie) ===== likvidace zombie procesů ===== * zombie je proces, který skončil provádění kódu, ale zůstal zapsán v tabulce procesů, aby si rodičovský proces mohl přečíst jeho návratovou hodnotu. * zombie zůstává v "Terminated state", dokud s tím rodič něco neudělá. * blokující wait() * funkce wait čeká na ukončení potomka. * zavoláme v kódu po vytvoření potomka. Čekání blokuje proces * neblokující wait() * zaregistrujeme handler, který při příjmu signálu SIGCHLD zavolá wait() * zrušení potřeby wait() * zaregistrujeme handler SIG_IGN a nastavíme flag SA_NOCLDWAIT * systém pak ukončené potomky rovnou zapracovává struct sigaction sa; sa.sa_handler = SIG_IGN; sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT; sigaction(SIGCHLD, &sa, NULL); * double fork * vytvoříme potomka a v něm dalšího. * prvního potomka zabijeme, čímž uděláme z potomka dalšího sirotka * tohle řešení se prý používá nejčastěji, protože přináší další výhody jako odpojení stdin/out/err od mateřského procesu atd. pid_t pid1, pid2; pid1 = fork(); if (pid1 == -1) { // fork failed exit(1); } if (pid1 == 0) { // child pid2 = fork(); //second fork if (pid2 == -1) { // fork failed exit(1); } if (pid2 == 0) { // child ret = system(cmd); exit(ret); } // parent exit(0); } //parent waitpid(pid1, &ret, 0);