Z czytania stron podręcznika read()
i write()
wywołań wynika, że połączenia te są przerywane sygnałami, niezależnie od tego, czy muszą być blokowane, czy nie.
W szczególności załóżmy
- proces ustanawia moduł obsługi dla niektórych sygnałów.
- urządzenie jest otwarte (powiedzmy terminal) z
O_NONBLOCK
nie ustawionym (tzn. działa w trybie blokowania) - następnie proces wykonuje
read()
wywołanie systemowe w celu odczytu z urządzenia, w wyniku czego wykonuje ścieżkę kontroli jądra w przestrzeni jądra. - podczas gdy preces wykonuje swoją pracę
read()
w przestrzeni jądra, sygnał, dla którego wcześniej zainstalowano moduł obsługi, jest dostarczany do tego procesu i wywoływany jest moduł obsługi sygnału.
Czytając strony podręcznika i odpowiednie sekcje w woluminie interfejsów systemowych (XSH) SUSv3 , okazuje się, że:
ja. Jeśli a read()
zostanie przerwane przez sygnał przed odczytaniem jakichkolwiek danych (tj. Musiał zablokować, ponieważ żadne dane nie były dostępne), zwraca -1 z errno
ustawionym na [EINTR].
ii. Jeśli a read()
zostanie przerwane przez sygnał po pomyślnym odczytaniu niektórych danych (tj. Możliwe było natychmiastowe rozpoczęcie obsługi żądania), zwraca liczbę odczytanych bajtów.
Pytanie A):
Czy słusznie zakładam, że w obu przypadkach (blok / brak bloku) dostarczenie i obsługa sygnału nie jest całkowicie przejrzysta dla read()
?
Przypadek I wydaje się zrozumiałe, ponieważ blokowanie read()
zwykle TASK_INTERRUPTIBLE
ustawia proces w takim stanie, że po dostarczeniu sygnału jądro ustawia proces w TASK_RUNNING
stan.
Jednak gdy read()
nie trzeba blokować (przypadek ii.) I przetwarza żądanie w przestrzeni jądra, pomyślałbym, że nadejście sygnału i jego obsługa byłaby przejrzysta, podobnie jak nadejście i poprawna obsługa HW przerwanie byłoby. W szczególności założyłbym, że po dostarczeniu sygnału proces zostałby tymczasowo wprowadzony w tryb użytkownika w celu wykonania jego procedury obsługi sygnału, z której w końcu powróciłby w celu zakończenia przetwarzania przerwanego read()
(w przestrzeni jądra), aby read()
działał kurs do zakończenia, po którym proces wraca do punktu tuż po wywołaniu read()
(w przestrzeni użytkownika), w wyniku czego odczytane są wszystkie dostępne bajty.
Ale ii. wydaje się sugerować, że read()
jest przerwane, ponieważ dane są dostępne natychmiast, ale zwraca zwraca tylko niektóre dane (zamiast wszystkich).
To prowadzi mnie do mojego drugiego (i ostatniego) pytania:
Pytanie B):
Jeśli moje założenie w punkcie A) jest prawidłowe, dlaczego read()
przerwanie zostaje przerwane, nawet jeśli nie trzeba go blokować, ponieważ dostępne są dane, aby natychmiast zaspokoić żądanie? Innymi słowy, dlaczego nie jest read()
ono wznawiane po wykonaniu procedury obsługi sygnału, co ostatecznie powoduje zwrócenie wszystkich dostępnych danych (które mimo wszystko były dostępne)?