From 14dab17d3c3d2e11e554197ea2045dbc7a485de9 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sun, 3 Jun 2012 17:28:10 +0000 Subject: [PATCH] Finita revisione capitolo sui segnali. --- signal.tex | 163 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 108 insertions(+), 55 deletions(-) diff --git a/signal.tex b/signal.tex index 2d0fa2c..982fc68 100644 --- a/signal.tex +++ b/signal.tex @@ -1605,7 +1605,7 @@ favore della nuova funzione di sistema \funcd{nanosleep}, il cui prototipo è: \begin{funcproto}{ \fhead{unistd.h} \fdecl{int nanosleep(const struct timespec *req, struct timespec *rem)} -\fdesc{Pone il processo in pausa per un periodo di tempo.} +\fdesc{Pone il processo in pausa per un intervallo di tempo.} } {La funzione ritorna $0$ se l'attesa viene completata e $-1$ per un errore, @@ -1651,8 +1651,8 @@ specificato, ma prima che il processo possa tornare ad essere eseguito occorrerà almeno attendere la successiva interruzione del timer di sistema, cioè un tempo che a seconda dei casi può arrivare fino a 1/\const{HZ}, (sempre che il sistema sia scarico ed il processa venga immediatamente rimesso in -esecuzione); per questo motivo il valore restituito in \param{rem} è sempre -arrotondato al multiplo successivo di 1/\const{HZ}. +esecuzione). Per questo motivo il valore restituito in \param{rem} è sempre +arrotondato al multiplo successivo di 1/\const{HZ}. Con i kernel della serie 2.4 in realtà era possibile ottenere anche pause più precise del centesimo di secondo usando politiche di \itindex{scheduler} @@ -2910,7 +2910,7 @@ indefinito. La seconda è identica alla prima ma in più permette di specificare un timeout con l'argomento omonimo, scaduto il quale ritornerà con un errore. Se si -specifica per \param{timeoout} un puntatore nullo il comportamento sarà +specifica per \param{timeout} un puntatore nullo il comportamento sarà identico a \func{sigwaitinfo}. Se si specifica un tempo di timeout nullo e non ci sono segnali pendenti la funzione ritornerà immediatamente, in questo modo si può eliminare un segnale dalla coda senza dover essere bloccati qualora @@ -3033,7 +3033,7 @@ tab.~\ref{tab:sig_timer_clockid_types}. \const{CLOCK\_BOOTTIME} & Identico a \const{CLOCK\_MONOTONIC} ma tiene conto anche del tempo durante il quale il sistema è stato sospeso (nel caso di - sospenzione in RAM o \textsl{ibernazione} su + sospensione in RAM o \textsl{ibernazione} su disco. Questo orologio è specifico di Linux, ed è disponibile a partire dal kernel 2.6.39.\\ @@ -3056,8 +3056,6 @@ tab.~\ref{tab:sig_timer_clockid_types}. \end{table} -% Note: aggiungere le estensioni introdotte, verificandone il -% funzionamento, vedi http://lwn.net/Articles/429595/ % NOTE: dal 2.6.39 anche CLOCK_BOOTTIME_ALARM e CLOCK_BOOTTIME % NOTE: dal 3.0 anche i cosiddetti Posix Alarm Timers, con % CLOCK_REALTIME_ALARM vedi http://lwn.net/Articles/429925/ @@ -3166,7 +3164,7 @@ tab.~\ref{tab:sig_timer_clockid_types} sono delle estensioni specifiche di Linux, create per rispondere ad alcune esigenze specifiche, come quella di tener conto di eventuali periodi di sospensione del sistema, e presenti solo nelle versioni più recenti del kernel. In particolare gli ultimi due, -contraddistinti dal suffusso \texttt{\_ALARM}, hanno un impiego particolare, +contraddistinti dal suffisso \texttt{\_ALARM}, hanno un impiego particolare, derivato dalle esigenze emerse con Android per l'uso di Linux sui cellulari, che consente di creare timer che possono scattare, riattivando il sistema, anche quando questo è in sospensione. Per il loro utilizzo è prevista la @@ -3254,7 +3252,6 @@ l'orologio associato ad un \textit{thread} invece che a un processo, è % TODO, dal 2.6.39 aggiunta clock_adjtime -% TODO manca clock_nanosleep, referenziata in sez.~\ref{sec:sig_gen_beha} Con l'introduzione degli orologi ad alta risoluzione è divenuto possibile ottenere anche una gestione più avanzata degli allarmi; abbiamo già visto in @@ -3313,7 +3310,7 @@ meccanismo di notifica. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{\textwidth} + \begin{minipage}[c]{0.8\textwidth} \includestruct{listati/sigevent.h} \end{minipage} \normalsize @@ -3443,7 +3440,7 @@ state allocate. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{\textwidth} + \begin{minipage}[c]{0.8\textwidth} \includestruct{listati/itimerspec.h} \end{minipage} \normalsize @@ -3462,14 +3459,16 @@ numero di secondi e nanosecondi indicati da questo campo. Se invece si usa per \param{flags} il valore \const{TIMER\_ABSTIME}, che al momento è l'unico valore valido per \param{flags}, allora \var{it\_value} viene considerato come un valore assoluto rispetto al valore usato dall'orologio a cui è associato il -timer.\footnote{quindi a seconda dei casi lo si potrà indicare o come un tempo - assoluto, quando si opera rispetto all'orologio di sistema (nel qual caso il - valore deve essere in secondi e nanosecondi dalla \textit{epoch}) o come - numero di secondi o nanosecondi rispetto alla partenza di un orologio di - CPU, quando si opera su uno di questi.} Infine un valore nullo di -\var{it\_value}, dover per nullo si intende con valori nulli per entrambi i -campi \var{tv\_sec} e \var{tv\_nsec}, può essere utilizzato, indipendentemente -dal tipo di orologio utilizzato, per disarmare l'allarme. +timer. + +Quindi a seconda dei casi si potrà impostare un timer o con un tempo assoluto, +quando si opera rispetto all'orologio di sistema (nel qual caso il valore deve +essere in secondi e nanosecondi dalla \textit{epoch}) o con un numero di +secondi o nanosecondi rispetto alla partenza di un orologio di CPU, quando si +opera su uno di questi. Infine un valore nullo di \var{it\_value}, dove per +nullo si intende con valori nulli per entrambi i campi \var{tv\_sec} e +\var{tv\_nsec}, può essere utilizzato, indipendentemente dal tipo di orologio +utilizzato, per disarmare l'allarme. Il campo \var{it\_interval} di \struct{itimerspec} viene invece utilizzato per impostare un allarme periodico. Se il suo valore è nullo, se cioè sono nulli @@ -3488,17 +3487,17 @@ programma che riceve l'allarme su un eventuale numero di scadenze che sono passate prima della ricezione della notifica dell'allarme. É infatti possibile, qualunque sia il meccanismo di notifica scelto, che -quest'ultima venga ricevuta dopo che il timer è scaduto più di una -volta.\footnote{specialmente se si imposta un timer con una ripetizione a - frequenza elevata.} Nel caso dell'uso di un segnale infatti il sistema mette -in coda un solo segnale per timer,\footnote{questo indipendentemente che si - tratti di un segnale ordinario o \textit{real-time}; per questi ultimi - sarebbe anche possibile inviare un segnale per ogni scadenza, questo però - non viene fatto per evitare il rischio, tutt'altro che remoto, di riempire - la coda.} e se il sistema è sotto carico o se il segnale è bloccato, prima -della sua ricezione può passare un intervallo di tempo sufficientemente lungo -ad avere scadenze multiple, e lo stesso può accadere anche se si usa un -\textit{thread} di notifica. +quest'ultima venga ricevuta dopo che il timer è scaduto più di una volta, +specialmente se si imposta un timer con una ripetizione a frequenza +elevata. Nel caso dell'uso di un segnale infatti il sistema mette in coda un +solo segnale per timer,\footnote{questo indipendentemente che si tratti di un + segnale ordinario o \textit{real-time}, per questi ultimi sarebbe anche + possibile inviare un segnale per ogni scadenza, questo però non viene fatto + per evitare il rischio, tutt'altro che remoto, di riempire la coda.} e se il +sistema è sotto carico o se il segnale è bloccato, prima della sua ricezione +può passare un intervallo di tempo sufficientemente lungo ad avere scadenze +multiple, e lo stesso può accadere anche se si usa un \textit{thread} di +notifica. Per questo motivo il gestore del segnale o il \textit{thread} di notifica può ottenere una indicazione di quante volte il timer è scaduto dall'invio della @@ -3536,7 +3535,6 @@ Qualora si voglia rileggere lo stato corrente di un timer, ed ottenere il tempo mancante ad una sua eventuale scadenza, si deve utilizzare la funzione di sistema \funcd{timer\_gettime}, il cui prototipo è: - \begin{funcproto}{ \fhead{time.h} \fdecl{int timer\_gettime(timer\_t timerid, int flags, struct @@ -3554,7 +3552,6 @@ di sistema \funcd{timer\_gettime}, il cui prototipo è: } \end{funcproto} - La funzione restituisce nella struttura \struct{itimerspec} puntata da \param{curr\_value} il tempo restante alla prossima scadenza nel campo \var{it\_value}. Questo tempo viene sempre indicato in forma relativa, anche @@ -3594,6 +3591,60 @@ questo era stato attivato. Nel caso, poco probabile ma comunque possibile, che un timer venga cancellato prima della ricezione del segnale pendente per la notifica di una scadenza, il comportamento del sistema è indefinito. +Infine a partire dal kernel 2.6 e per le versioni della \acr{libc} superiori +alla 2.1, si può utilizzare la nuova interfaccia dei timer Posix anche per le +funzioni di attesa, per questo è disponibile la funzione di sistema +\funcd{clock\_nanosleep}, il cui prototipo è: + +\begin{funcproto}{ +\fhead{time.h} +\fdecl{int clock\_nanosleep(clockid\_t clock\_id, int flags, const struct + timespec *request,\\ +\phantom{int clock\_nanosleep(}struct timespec *remain)} +\fdesc{Pone il processo in pausa per un tempo specificato.} +} + +{La funzione ritorna $0$ in caso di successo ed un valore positivo per un + errore, espresso dai valori: + \begin{errlist} + \item[\errcode{EINTR}] la funzione è stata interrotta da un segnale. + \item[\errcode{EINVAL}] si è specificato un numero di secondi negativo o + un numero di nanosecondi maggiore di 999.999.999 o indicato un orologio + non valido. + \end{errlist} + ed inoltre \errval{EFAULT} nel suo significato generico.} +\end{funcproto} + +I due argomenti \param{request} e \param{remain} sono identici agli analoghi di +\func{nanosleep} che abbiamo visto in sez.~\ref{sec:sig_pause_sleep}, ed hanno +lo stesso significato. L'argomento \param{clock\_id} consente di indicare +quale orologio si intende utilizzare per l'attesa con uno dei valori della +prima parte di tab.~\ref{tab:sig_timer_clockid_types} (eccetto +\const{CLOCK\_THREAD\_CPUTIME\_ID}). L'argomento \param{flags} consente di +modificare il comportamento della funzione, il suo unico valore valido al +momento è \const{TIMER\_ABSTIME} che, come per \func{timer\_settime} indica di +considerare il tempo indicato in \param{request} come assoluto anziché +relativo. + +Il comportamento della funzione è analogo a \func{nanosleep}, se la chiamata +viene interrotta il tempo rimanente viene restituito in \param{remain}. +Utilizzata normalmente con attese relative può soffrire degli stessi problemi +di deriva di cui si è parlato in sez.~\ref{sec:sig_pause_sleep} dovuti ad +interruzioni ripetute per via degli arrotondamenti fatti a questo tempo. Ma +grazie alla possibilità di specificare tempi assoluti con \param{flags} si può +ovviare a questo problema ricavando il tempo corrente con +\func{clock\_gettime}, aggiungendovi l'intervallo di attesa, ed impostando +questa come tempo assoluto. + +Si tenga presente che se si è usato il valore \const{TIMER\_ABSTIME} +per \param{flags} e si è indicato un tempo assoluto che è già passato la +funzione ritorna immediatamente senza nessuna sospensione. In caso di +interruzione da parte di un segnale il tempo rimanente viene restituito +in \param{remain} soltanto se questo non è un puntatore \val{NULL} e non si è +specificato \const{TIMER\_ABSTIME} per \param{flags} . + +% TODO manca clock_nanosleep, referenziata in sez.~\ref{sec:sig_gen_beha} + \itindend{POSIX~Timer~API} @@ -3691,7 +3742,7 @@ restituito dalla funzione per un successivo ripristino). \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{\textwidth} + \begin{minipage}[c]{0.8\textwidth} \includestruct{listati/stack_t.h} \end{minipage} \normalsize @@ -3732,13 +3783,13 @@ una chiamata ad una funzione della famiglia \func{exec} cancella ogni Abbiamo visto in fig.~\ref{fig:sig_sleep_incomplete} come si possa usare \func{longjmp} per uscire da un gestore rientrando direttamente nel corpo -del programma; sappiamo però che nell'esecuzione di un gestore il segnale +del programma, sappiamo però che nell'esecuzione di un gestore il segnale che l'ha invocato viene bloccato, e abbiamo detto che possiamo ulteriormente modificarlo con \func{sigprocmask}. Resta quindi il problema di cosa succede alla maschera dei segnali quando si esce da un gestore usando questa funzione. Il comportamento dipende -dall'implementazione; in particolare la semantica usata da BSD prevede che sia +dall'implementazione. In particolare la semantica usata da BSD prevede che sia ripristinata la maschera dei segnali precedente l'invocazione, come per un normale ritorno, mentre quella usata da System V no. @@ -3748,33 +3799,35 @@ caratteristiche si sono abilitate con le macro viste in sez.~\ref{sec:intro_gcc_glibc_std}. Lo standard POSIX però prevede anche la presenza di altre due funzioni -\funcd{sigsetjmp} e \funcd{siglongjmp}, che permettono di decidere quale dei -due comportamenti il programma deve assumere; i loro prototipi sono: -\begin{functions} - \headdecl{setjmp.h} - - \funcdecl{int sigsetjmp(sigjmp\_buf env, int savesigs)} Salva il contesto - dello \textit{stack} per un \index{salto~non-locale} salto non-locale. - - \funcdecl{void siglongjmp(sigjmp\_buf env, int val)} Esegue un salto - non-locale su un precedente contesto. +\funcd{sigsetjmp} e \funcd{siglongjmp}, che permettono di decidere in maniera +esplicita quale dei due comportamenti il programma deve assumere; i loro +prototipi sono: + +\begin{funcproto}{ +\fhead{setjmp.h} +\fdecl{int sigsetjmp(sigjmp\_buf env, int savesigs)} +\fdesc{Salva il contesto dello \textit{stack} e la maschera dei segnali.} +\fdecl{void siglongjmp(sigjmp\_buf env, int val)} +\fdesc{Ripristina il contesto dello \textit{stack} e la maschera dei segnali.} +} - \bodydesc{Le due funzioni sono identiche alle analoghe \func{setjmp} e - \func{longjmp} di sez.~\ref{sec:proc_longjmp}, ma consentono di specificare - il comportamento sul ripristino o meno della maschera dei segnali.} -\end{functions} +{La funzioni sono identiche alle analoghe \func{setjmp} e \func{longjmp} di + sez.~\ref{sec:proc_longjmp} ed hanno gli stessi errori e valori di uscita.} +\end{funcproto} Le due funzioni prendono come primo argomento la variabile su cui viene salvato il contesto dello \itindex{stack} \textit{stack} per permettere il \index{salto~non-locale} salto non-locale; nel caso specifico essa è di tipo \type{sigjmp\_buf}, e non \type{jmp\_buf} come per le analoghe di sez.~\ref{sec:proc_longjmp} in quanto in questo caso viene salvata anche la -maschera dei segnali. +maschera dei segnali. Nel caso di \func{sigsetjmp}, se si specifica un valore di \param{savesigs} -diverso da zero la maschera dei valori sarà salvata in \param{env} e -ripristinata in un successivo \func{siglongjmp}; quest'ultima funzione, a -parte l'uso di \type{sigjmp\_buf} per \param{env}, è assolutamente identica a +diverso da zero la maschera dei valori verrà salvata in \param{env} insieme al +contesto dello \itindex{stack} \textit{stack} usato per il salto non +locale. Se così si è fatto la maschera dei segnali verrà ripristinata in una +successiva chiamata a \func{siglongjmp}. Quest'ultima, a parte l'uso di un +valore di \param{env} di tipo \type{sigjmp\_buf}, è assolutamente identica a \func{longjmp}. @@ -3840,11 +3893,11 @@ parte l'uso di \type{sigjmp\_buf} per \param{env}, è assolutamente identica a % LocalWords: ENOSYS pthread ENOENT NULL attribute itimerspec new old ABSTIME % LocalWords: epoch multiplexing overrun res lpthread sec nsec curr one shot % LocalWords: delete stopped gdb alpha mips emulation locking ppoll epoll PGID -% LocalWords: pwait msgrcv msgsnd semop semtimedop runnable sigisemptyset +% LocalWords: pwait msgrcv msgsnd semop semtimedop runnable sigisemptyset HRT +% LocalWords: sigorset sigandset BOOTTIME Android request remain %%% Local Variables: %%% mode: latex %%% TeX-master: "gapil" %%% End: -% LocalWords: sigorset sigandset -- 2.30.2