Procesy
Algorytm Wait
Autorzy: Bartłomiej Kijanka, Paweł Piechocki
Gdybyśmy chcięli zsynchronizować działanie procesu z
zakończeniem jego procesów potomnych, umożliwią nam to
systemowe funkcje:
- pid_t wait (int *statptr);
- pid_t waitpid (pid_t pid, int *statptr, int options);
Funkcja wait() wstrzymuje wywołujący ją proces do momentu,
aż jeden z jego procesów potomnych przestanie działać.
Funkcja waitpid() proces wywołujący do momentu, aż potomek
określony przez pid przestanie działać.
Jeżeli któryś z procesów potomnych osiągnął wymagany stan
przed wywołaniem wait(), to funkcja wraca natychmiast. Podobnie,
gdy proces nie ma żadnych potomków, tyle, że tym razem wraca z
błędem -1.
Kiedy proces potomny się kończy, do ojca przesyłane są
informacje o jego stanie (np. exit_code) i jego PID. Te dane są
zawarte w zmiennej addr_stat.
Powyższe funkcje są interfejsem dla wewnętrznej funkcji:
asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr,
int options, struct rusage * ru);
Dopuszczalne wartości parametrów dla sys_wait4 to:
- >0 czekamy na proces potomny o identyfikatorze równym
pid
- 0 czekamy na proces potomny, mający taki sam GID jak
proces wywołujący waitpid
- -1 czekiwanie na dowolny proces potomny
- <-1 oznacza oczekiwanie na proces potomny o GID równym |pid|
- WNOHANG - natychmiastowy powrót z funkcji, gdy nie ma
żadnego zakończonego procesu potomnego
- WUNTRACED - powrót z funkcji po znalezieniu zatrzymanego
procesu potomnego, który nie był jeszcze uwzględniony
w funkcji wait
- __WNOTHREAD - nie czekamy na procesy potomne innych
wątków z naszej grupy
- __WALL - czekamy na wszystkich, bez względu na typ
- __WCLONE - czekamy tylko na dzieci powstałe poprzez
wywołanie funkcją clone
Jeśli nie podamy ani __WALL, ani __WCLONE, wait będzie
czakać wyłącznie na normalne dzieci.
Służy do zwracania informacji o zakończonym procesie; dane
są zawarte w pierwszych 2 bajtach tej zmiennej. Możliwe
wartości to:
Wydarzenie |
Starszy Bajt |
Młodszy Bajt |
Proces zakończył się prawidłowo |
exit_code |
0 |
Proces został wstrzymany |
exit_code |
0x7f |
Proces został zabity sygnałem |
0 |
numer sygnału |
Wskaźnik do struktury rusage, w której pamiętane są
informacje o korzystaniu z zasobów takie jak np. czas w trybie
użytkownika i czas w trybie jądra. Podanie wartości NULL
oznacza, że nie interesują nas te informacje. Struktura ta jest
wypełniana za pomocą funkcji getrusage().
Udane wywołanie sys_wait4 zwraca pid procesu którego się
doczekaliśmy. Oprócz tego mogą zostać zwrócone następujące
kody błędów:
- EINVAL - niewłasciwe flagi
- ERESTARTSYS - podczas czekania do naszego procesu
przesłano sygnał
- ECHILD - nie istnieje potomek odpowiadający parametrowi
pid, na którego moglibyśmy czekać
Sprawdza poprawność parametrów. zwraca -EINVAL jeśli błąd
Dodaje proces current do kolejki current->wait_chldexit i ustawia stan procesu current na TASK_INTERRUPTIBLE
LOOP
Dla każdego potomkai (i jeśli nie dostaliśmy flagi __WNOTHREAD dla każdego potomka każdego następnego wątku):
Sprawdza pid potomka czy na niego czekamy, jeśli nie to kolejny potomek
Jeśli nie dostaliśmy flagi __WALL to:
Jeśli dostaliśmy flagę __WCLONE i potomek nie był utworzony funkcją clone to bierzemy następnego potomka
Jeśli nie dostaliśmy flagi __WCLONE i potomek był utworzony funkcją clone to bierzemy następnego potomka
Jeśli potomek jest w stanie TASK_STOPPED to:
Jeśli już ktoś na niego czekał (exit_code == 0) to bierzemy kolejnego potomka
Jeśli nie dostaliśmy flagi WUNTRACED i potomek nie ma ustawionej flagi PT_TRACED to kolejny potomek
Zapisuje statystyczne informacje o potomku
Zwraca poprzez zmienną stat_addr kod wyjścia
Ustawia exit_code potomka na 0
Ustawia wartość zwracaną na pid potomka
Jeśli potomek jest w stanie TASK_ZOMBIE to:
Dodaje czas w trybie uzytkownika i systemowym potomka do odpowiednich w wartości procesu current
Zapisuje statystyczne informacje o potomku
Zwraca poprzez zmienną stat_addr kod wyjścia
Jeśli ojciec potomka jest inny niż oryginalny ojciec, zawiadamia oryginalnego ojca o śmierci potomka,
W przeciwnym przypadku zwalnia strukturę procesu potomka
Ustawia wartość zwracaną na pid potomka
Jeśli potomek jest w innym stanie to bierzemy kolejnego potomka
Jeśli flaga == 1 to:
Jeśli dostaliśmy flagę WNOHANG, ustawia wartość zwracaną na 0 i wychodzi poza pętle LOOP
Jeśli w międzyczasie dostalismy jakieś sygnały, ustawia wartość zwracaną na -ERESTARTSYS i wychodzi poza pętle LOOP
Wywołuje schedule() i oddaje sterowanie
W przeciwnym przypadku: ustawia wartość zwracaną na -ECHILD i wychodzi poza pętle LOOP
Usuwa proces current z kolejki current->wait_chldexit i ustawia stan procesu current na TASK_RUNNING