plik


2.1.3 Funkcja wait Do spisu treści tematu Zarządzanie procesami Opis funkcji wait Spis treści Wprowadzenie Wywołanie funkcji Wartości przekazywane przez funkcję: Sytuacje normalne, Sytuacje błędne Algorytm funkcji Wait a ignorowanie śmierci potomka Bibliografia Wprowadzenie W Linuxie istnieją dwie funkcje służące do zsynchronizowania swojego działania z zakończeniem działania lub zatrzymaniem procesu potomnego.Są to funcje wait i waitpid. Funkcja wait(s) wstrzymuje wywołujący ją proces do momentu, aż jeden z jego procesów potomnych przestanie działać. Funkcja waitpid( pid, s, options) wstrzymuje proces wywołujący do momentu, aż potomek określony przez pid przestanie działać. W obu funkcjach jeżeli odpowiedni potomek już jest, to funkcja wraca natychmiast. Jeżeli paremetr s wywołania funkcji jest różny od 0, to funkcje wpisują pod ten adres przyczynę zakończenia procesu. Wywołanie funkcji Wywołanie funkcji wait( addr_stat) odpowiada wywołąniu waitpid(-1,addr_stat,0). Wywołanie funkcji waitpid wygląda następująco: waitpid( pid_t pid , int *addr_stat ,int options) Wartość pid może być: >0 oznacza oczekiwanie na proces potomny o identyfikatorze równym pid =0 oznacza oczekiwanie na proces potomny, mający taki sam identyfikator grupy jak proces wywołujący waitpid =-1 oznacza oczekiwanie na dowolny proces potomny <-1 oznacza oczekiwanie na proces potomny o identyfikatorze grupy równym co do wartości bezwzględnej argumentowi pid Wartość options może wynosić: WNOHANG oznacza natychmiastowy powrót z funkcji, w przypadku gdy nie ma żadnego zakończonego procesu potomnego WNOTRACE oznacza powrót z funkcji po znalezieniu dowolnego zatrzymanego potomka, który nie był jeszcze uwzględniony w funkcji wait.   Wartości przekazywane przez funkcję Sytuacje normalne Funkcja wait przekazuje dwie wartości: 1) zwraca identyfikator zakończonego lub zatrzymanego procesu potomnego 2) pod podany adres wpisuje przyczynę zakończenia procesu. Jeśli był to proces ZOMBIE to wpisywana jest zawartość pola exit_code. W przypadku procesu STOPPED wartość z exit_code przesuwana jest o osiem bitów w lewo, zaś na wolne miejsce wpisywana jest wartosć 0x7f. Dzięki takiej organizacji proces macierzysty zawsze może rozróżnić, czy proces potomny, który przestał działać jest zatrzymany, czy tez był procesem ZOMBIE i z jakiego powodu. proces potomny: 8 starszych bitów 8 młodszych bitów wywołał exit argument dla exit 0x00 zabity sygnałem 0x00 numer sygnału (*) zatrzymany numer sygnału 0x7f 3) jeżeli ustawiona była opcja WNOHANG i proces nie ma zakończonych lub zatrzymanych potomków to zwracane jest 0 (*) - w tym bajcie oprócz numeru sygnału zapisanego na 5-ciu najmłodszych bitach jest także zapisywana na najstarszym bicie informacja czy proces wygenerował plik core (zrzut pamięci) Sytuacje błędne Po wystąpieniu błędu funkcja biblioteczna wait zwraca -1, a do zmiennej errno wpisuje kod błędu otrzymany z wywołania sys_wait4. Możliwe błędy to: - ECHILD (proces wywołujący nie ma potomków określonych przez pid) - EFAULT (adres podany jako parametr jest niewłaściwy - należy do przestrzeni w której proces nie może pisać) - ERESTARTSYS (w trakcie oczekiwania na śmierć potomka proces dostał niespodziewany sygnał, tzn. różny od SIGCHLD i nie zablokowany) Algorytm funkcji Implementacją funkcji waitpid jest funkcja sys_wait4. int sys_wait4( pid_t pid, unsigned int *stat_addr, int options, struct rusage *ru) { sprawdź poprawność podanych argumentów i w przypadku argumentów niepoprawnych zwróć odpowiedni błąd; sprawdź czy adres podany jako argument ru jest poprawny, jeżeli nie to zwróć błąd; sprawdź czy opcja podana w parametrze options jest jedną z dostępnych opcji, jeżeli nie to zwróć błąd EINVAL; wstaw proces do swojej kolejki wait_chldexit (pole struktury task_struct ); dla każdego potomka p wykonaj { sprawdź czy p należy do zbioru procesów określonych przez pid, jeżeli nie to przejdź do następnego potomka; jeżeli stan p = TASK_STOPPED { jeżeli proces ten był już uwzględniony we wcześniejszych wywołaniach wait to przejdź do następnego potomka; zapisz dane o użytkowaniu procesora przez p do struktury ru; wpisz pod adres addr_stat wartość pola exit_code zatrzymanego procesu odpowiednio przesuniętą; zwróć pid znalezionego procesu; } jeżeli stan p=TAST_ZOMBIE { zwiększ procesowi macierzystemu czas wykorzystania CPU o czas zużyty przez potomka; zapisz dane o użytkowaniu procesora przez p do struktury ru; pod adres sddr_stat wpisz wartość pola exit_code zakończonego procesu; zwolnij miejsce w tablicy procesów po zakończonym procesie; zwróć pid zakończonego procesu; } } jeżeli nie ma procesu potomnego odpowiadającego argumentom funkcji to funkcja zwraca błąd ECHILD; jeżeli wszystkie procesy potomne działają i ustawiona jest opcja WNOHANG to zwróć 0; jeżeli nadszedł jakiś nieoczekiwany sygnał, tzn. różny od SIGCHLD i nie zablokowany to zwróć błąd ERASTARTSYS; zaśnij dopuszczając przerwania ; po obudzeniu od nowa przeglądaj synów; } Funkcja wait a ignorowanie sygnalu śmierci potomka Proces może ustawić obsługę sygnału SIGCHLD na SIG_IGN. Oznacza to, ze proces macierzysty nie jest zainteresowany stanem końcowym swoich procesów potomnych, zatem nie ma sensu przechowywać w systemie procesów ZOMBIE. Dlatego w momencie obsługi sygnału SIGCHLD (do_signal), jeśli proces go ignoruje, jądro samo (za proces) będzie wywoływać funkcję sys_wait4 z opcją WNOHANG do skutku, tzn. aż nie będzie procesów ZOMBIE. Bibliografia: Źródła jądra: kernel/exit.c Maurice J. Bach, Budowa systemów operacyjnych UNIX, WNT 1995 W. Richard Stevens, Programowanie zastosowań sieciowych w systemie UNIX , WNT 1995,1996 Autor: Małgorzata Górbiel

Wyszukiwarka