Przyszedł czas na odświeżenie wiedzy o sygnałach.
http://www.kernel.org/doc/man-pages/online/pages/man7/signal.7.html
Streszczenie:
Sygnały dostarczane do procesu traktujemy jak przerwania w systemie z bezpośrednim dostepem do procesora.
W Linuxie występują 2 rodzaje sygnałów, Standardowe i RealTime. Cytujac zródło:
"Real-time signals are distinguished by the following:
1. Multiple instances of real-time signals can be queued. By contrast, if multiple instances of a standard signal are delivered while that signal is currently blocked, then only one instance is queued.
2. If the signal is sent using sigqueue(2), an accompanying value (either an integer or a pointer) can be sent with the signal. If the receiving process establishes a handler for this signal using the SA_SIGINFO flag to sigaction(2) then it can obtain this data via the si_value field of the siginfo_t structure passed as the second argument to the handler. Furthermore, the si_pid and si_uid fields of this structure can be used to obtain the PID and real user ID of the process sending the signal.
3. Real-time signals are delivered in a guaranteed order. Multiple real-time signals of the same type are delivered in the order they were sent. If different real-time signals are sent to a process, they are delivered starting with the lowest-numbered signal. (I.e., low-numbered signals have highest priority.) By contrast, if multiple standard signals are pending for a process, the order in which they are delivered is unspecified.
If both standard and real-time signals are pending for a process, POSIX leaves it unspecified which is delivered first. Linux, like many other implementations, gives priority to standard signals in this case."
Sygnały mogą zostać wysłane do procesu lub wątku. Zazwyczaj funkcje pozwalające wysłać sygnał do wątku posiadają przedrostek pthread- . Sygnał wysłany do procesu zostanie dostarczony do dowolnego z wątków który w danym momencie go nie blokuje. Jeśli wszystkie wątki blokują sygnał skierowany do procesu, pozostanie on nieobsłużony do czasu aż przynajmniej jeden z wątków zezwoli na jego przetwarzanie.
Nalezy pamietać że istnieja 2 pojęcia dotyczące sygnałów, dyspozycje oraz maska. Dyspozycja sygnałów określa czy sygnał ma wykonać domyślna akcje (zależna od sygnału np zakończyć proces lub wykonać core dump), czy należny go zignorować czy przechwycić/dostarczyć. Natomiast maska pozwala na tymczasowe skolejkowanie sygnału w przypadku dyspozycji dostarczenia, do czasu kiedy nie zostanie wyczyszczona (maska). Sygnał skolejowany nazwany jest sygnałem w stanie "pending".
Dyspozycja jest peer aplikacja, natomiast maski sygnałów są peer watek.
Inną ważną informacją jest to że biblioteka pthread używa 2 lub 3 pierwsze sygnały typu real time, do implementacji jej wewnętrznych usług. Dlatego też należy bezwzględnie używać makra SIGRTMIN aby w aplikacji nie użyć przypadkiem numerów sygnałów wykorzystywanych w bibliotece pthread. Inna rzeczą o której trzeba pamiętać jest to że kernel ogranicza też maksymalna ilość kolejkowanie sygnałów (w zależności od wersji jest do ograniczenie typu system-wide (do 2.6.7) lub user-wide (od 2.6.8)).
Należy pamiętać ze w funkcji obsługi sygnału nie wolno wykonywać dowolnie zdefiniowanego kodu. POSIX wprowadza w tym celu pojęcie Async-"signal-safe" functions.
Następna sprawa są wywołania funkcji systemowych przerwane sygnałami. Wywołania systemowe przerwane sygnałami mogą być automatycznie wznawiane (bez powiadamiania aplikacji o błędzie wywołania) w niektórych przypadkach o ile użyto flagi SA_RESTART w wywoływaniu sigaction lub podobnym.
Następujące funkcje klasyfikują się do wymienionego przypadku:
- read(2), readv(2), write(2), writev(2), and ioctl(2) calls on "slow" devices. A "slow" device is one where the I/O call may block for an indefinite time, for example, a terminal, pipe, or socket. (A disk is not a slow device according to this definition.) If an I/O call on a slow device has already transferred some data by the time it is interrupted by a signal handler, then the call will return a success status (normally, the number of bytes transferred)
- open(2), if it can block (e.g., when opening a FIFO; see fifo(7)).
- wait(2), wait3(2), wait4(2), waitid(2), and waitpid(2).
- Socket interfaces: accept(2), connect(2), recv(2), recvfrom(2), recvmsg(2), send(2), sendto(2), and sendmsg(2), unless a timeout has been set on the socket (see below).
- File locking interfaces: flock(2) and fcntl(2) F_SETLKW.
- POSIX message queue interfaces: mq_receive(3), mq_timedreceive(3), mq_send(3), and mq_timedsend(3).
- futex(2) FUTEX_WAIT (since Linux 2.6.22; beforehand, always failed with EINTR).
- POSIX semaphore interfaces: sem_wait(3) and sem_timedwait(3) (since Linux 2.6.22; beforehand, always failed with EINTR).
Ważne zaznaczenia jest to ze dysk nie jest uznany za "wolne" urządzenie, dlatego przy pisaniu lub czytaniu z pliku zawsze należny sprawdzać kod powrotu oznaczający ilość wpisanych lub odczytanych danych. 0 nie jest kodem błędu! ale informacja ze żadne dane nie zostały zapisane w momencie przyjęcia sygnału.
Brak komentarzy:
Prześlij komentarz