#define _POSIX_C_SOURCE 200809L #include /* waitpid */ #include /* close */ #include /* exit */ #include /* open */ #include #include #include /* Uvažme situaci, kdy chceme spustit složitější výpočet, který * sestává z většího množství procesů, které nejsou všechny přímými * potomky toho aktuálního. Navrhněte podprogram ‹await›, kterému * předáme * * • ukazatel na podprogram ‹subr›, který provádí nějaký výpočet * v pomocných procesech. * * Podprogram ‹await› vyčká, než skončí všechny procesy, které * ‹subr› vytvořil, a poté vrátí řízení volajícímu. Výsledkem * ‹await› je buď 0 v případě úspěchu, nebo -1 v případě chyby. * * Není odpovědností podprogramu ‹await›, aby na vzniklé podprocesy * volal ‹waitpid› – pro nepřímé potomky to ani není možné a pro ty * přímé by to bylo přinejlepším ošemetné. Předpokládejte, že * uvolnění zdrojů vyřeší volající – úkolem ‹await› je pouze vyčkat * do chvíle, než pomocné procesy skončí. */ int await( void ( *subr )( void ) ); /* ┄┄┄┄┄┄┄ %< ┄┄┄┄┄┄┄┄┄┄ následují testy ┄┄┄┄┄┄┄┄┄┄ %< ┄┄┄┄┄┄┄ */ static const char *mark = "zt.r3_mark"; void forky( void ) { pid_t pid_1 = fork(), pid_2 = -1; if ( pid_1 == -1 ) err( 1, "fork" ); if ( pid_1 > 0 ) /* parent */ return; pid_2 = fork(); if ( pid_2 == 0 ) /* child of the child */ { sleep( 5 ); int fd = open( mark, O_CREAT, 0666 ); if ( fd == -1 ) err( 1, "creating %s", mark ); close( fd ); exit( 0 ); } exit( 0 ); } int main( void ) { if ( unlink( mark ) == -1 && errno != ENOENT ) err( 1, "unlinking %s", mark ); assert( await( forky ) == 0 ); assert( access( mark, R_OK ) == 0 ); return 0; }