X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=signal.tex;h=ab37bddbdacc6992fb3c50a781ec9003d4de196b;hp=0dec1d064622c72cdb3fed3bfa0b6d059217e010;hb=50b469ec4e7bba4d52eaaa51edd77b18967079c2;hpb=f0f00a6c19f809e188a588e25b48f859148ff971 diff --git a/signal.tex b/signal.tex index 0dec1d0..ab37bdd 100644 --- a/signal.tex +++ b/signal.tex @@ -1214,16 +1214,17 @@ fig.~\ref{fig:sig_alarm_def}.\footnote{questo comporta anche che non Si deve comunque tenere presente che fino al kernel 2.6.16 la precisione di queste funzioni era limitata dalla frequenza del timer di sistema,\footnote{il - valore della constante \texttt{HZ}, di cui abbiamo già parlato in + valore della costante \texttt{HZ}, di cui abbiamo già parlato in sez.~\ref{sec:proc_hierarchy}.} in quanto le temporizzazioni erano calcolate -in numero di interruzioni del timer (i cosiddetti ''\textit{jiffies}''), ed era -assicurato soltanto che il segnale non sarebbe stato mai generato prima della -scadenza programmata (l'arrotondamento cioè era effettuato per -eccesso).\footnote{questo in realtà non è del tutto vero a causa di un bug, - presente fino al kernel 2.6.12, che in certe circostanze causava l'emissione - del segnale con un arrotondamento per difetto.} L'uso del contatore dei -\textit{jiffies}, un intero a 32 bit, comportava inoltre l'impossibilità di -specificare tempi molto lunghi.\footnote{superiori al valore della costante +in numero di interruzioni del timer (i cosiddetti \itindex{jiffies} +''\textit{jiffies}''), ed era assicurato soltanto che il segnale non sarebbe +stato mai generato prima della scadenza programmata (l'arrotondamento cioè era +effettuato per eccesso).\footnote{questo in realtà non è del tutto vero a + causa di un bug, presente fino al kernel 2.6.12, che in certe circostanze + causava l'emissione del segnale con un arrotondamento per difetto.} L'uso +del contatore dei \itindex{jiffies} \textit{jiffies}, un intero a 32 bit, +comportava inoltre l'impossibilità di specificare tempi molto +lunghi.\footnote{superiori al valore della costante \const{MAX\_SEC\_IN\_JIFFIES}, pari, nel caso di default di un valore di \const{HZ} di 250, a circa 99 giorni e mezzo.} Con il cambiamento della rappresentazione effettuato nel kernel 2.6.16 questo problema è scomparso e @@ -1241,7 +1242,9 @@ Questo ha una conseguenza che pu conto poi che in caso di sistema molto carico, si può avere il caso patologico in cui un timer scade prima che il segnale di una precedente scadenza sia stato consegnato; in questo caso, per il comportamento dei segnali descritto -in sez.~\ref{sec:sig_sigchld}, un solo segnale sarà consegnato. +in sez.~\ref{sec:sig_sigchld}, un solo segnale sarà consegnato. Per questo +oggi l'uso di questa funzione è deprecato a favore dei \textit{POSIX timer} +che tratteremo in sez.~\ref{sec:sig_timer_adv}. Dato che sia \func{alarm} che \func{setitimer} non consentono di leggere il valore corrente di un timer senza modificarlo, è possibile usare la funzione @@ -1822,7 +1825,7 @@ tab.~\ref{tab:sig_sa_flag}. Come si può notare in fig.~\ref{fig:sig_sigaction} \func{sigaction} permette di utilizzare due forme diverse di gestore,\footnote{la possibilità è prevista dallo standard POSIX.1b, ed è stata aggiunta nei kernel della serie 2.1.x - con l'introduzione dei segnali real-time (vedi + con l'introduzione dei segnali \textit{real-time} (vedi sez.~\ref{sec:sig_real_time}); in precedenza era possibile ottenere alcune informazioni addizionali usando \var{sa\_handler} con un secondo parametro addizionale di tipo \var{sigcontext}, che adesso è deprecato.} da @@ -1854,12 +1857,12 @@ causato l'emissione del segnale. \end{figure} In generale \var{si\_code} contiene, per i segnali generici, per quelli -real-time e per tutti quelli inviati tramite da un processo con \func{kill} o -affini, le informazioni circa l'origine del segnale stesso, ad esempio se -generato dal kernel, da un timer, da \func{kill}, ecc. Il valore viene sempre -espresso come una costante,\footnote{le definizioni di tutti i valori - possibili si trovano in \file{bits/siginfo.h}.} ed i valori possibili in -questo caso sono riportati in tab.~\ref{tab:sig_si_code_generic}. +\textit{real-time} e per tutti quelli inviati tramite da un processo con +\func{kill} o affini, le informazioni circa l'origine del segnale stesso, ad +esempio se generato dal kernel, da un timer, da \func{kill}, ecc. Il valore +viene sempre espresso come una costante,\footnote{le definizioni di tutti i + valori possibili si trovano in \file{bits/siginfo.h}.} ed i valori possibili +in questo caso sono riportati in tab.~\ref{tab:sig_si_code_generic}. Nel caso di alcuni segnali però il valore di \var{si\_code} viene usato per fornire una informazione specifica relativa alle motivazioni della ricezione @@ -1975,10 +1978,10 @@ cui si sono appena citati i rispettivi segnali.\footnote{il prefisso del nome Il resto della struttura \struct{siginfo\_t} è definito come \ctyp{union} ed i valori eventualmente presenti dipendono dal segnale, così \const{SIGCHLD} ed i -segnali real-time (vedi sez.~\ref{sec:sig_real_time}) inviati tramite +segnali \textit{real-time} (vedi sez.~\ref{sec:sig_real_time}) inviati tramite \func{kill} avvalorano \var{si\_pid} e \var{si\_uid} coi valori corrispondenti al processo che ha emesso il segnale, \const{SIGCHLD} avvalora anche i campi -\const{si\_status}, \const{si\_utime} e \const{si\_stime} che indicano +\var{si\_status}, \var{si\_utime} e \var{si\_stime} che indicano rispettivamente lo stato di uscita, l'\textit{user time} e il \textit{system time} (vedi sez.~\ref{sec:sys_cpu_times}) usati dal processo; \const{SIGILL}, \const{SIGFPE}, \const{SIGSEGV} e \const{SIGBUS} avvalorano @@ -2382,32 +2385,38 @@ parte l'uso di \type{sigjmp\_buf} per \param{env}, Abbiamo finora parlato dei gestori dei segnali come funzioni chiamate in corrispondenza della consegna di un segnale. In realtà un gestore non può essere una funzione qualunque, in quanto esso può essere eseguito in -corrispondenza all'interruzione in un punto qualunque del programma principale, -ed ad esempio può essere problematico chiamare all'interno di un gestore di -segnali la stessa funzione che dal segnale è stata interrotta. +corrispondenza all'interruzione in un punto qualunque del programma +principale, cosa che ad esempio può rendere problematico chiamare all'interno +di un gestore di segnali la stessa funzione che dal segnale è stata +interrotta. \index{funzioni!sicure|(} Il concetto è comunque più generale e porta ad una distinzione fra quelle che -che POSIX chiama \textsl{funzioni insicure} (\textit{unsafe function}) e -\textsl{funzioni sicure} (\textit{safe function}); quando un segnale -interrompe una funzione insicura ed il gestore chiama al suo interno una -funzione insicura il sistema può dare luogo ad un comportamento indefinito. - -Tutto questo significa che un gestore di segnale deve essere programmato con -molta cura per evitare questa evenienza, pertanto è non è possibile chiamare -al suo interno una funzione qualunque, e si può ricorrere soltanto all'uso di -funzioni sicure. - -L'elenco delle funzioni sicure varia a secondo dello standard a cui si fa -riferimento, secondo quanto riportato dallo standard POSIX 1003.1 nella +POSIX chiama \textsl{funzioni insicure} (\textit{signal unsafe function}) e +\textsl{funzioni sicure} (o più precisamente \textit{signal safe function}); +quando un segnale interrompe una funzione insicura ed il gestore chiama al suo +interno una funzione insicura il sistema può dare luogo ad un comportamento +indefinito, la cosa non avviene invece per le funzioni sicure. + +Tutto questo significa che la funzione che si usa come gestore di segnale deve +essere programmata con molta cura per evirare questa evenienza e che non è +possibile utilizzare al suo interno una qualunque funzione di sistema, se si +vogliono evitare questi problemi si può ricorrere soltanto all'uso delle +funzioni considerate sicure. + +L'elenco delle funzioni considerate sicure varia a seconda della +implementazione utilizzata e dello standard a cui si fa +riferimento;\footnote{non è riportata una lista specifica delle funzioni + sicure per Linux, si suppone pertanto che siano quelle richieste dallo + standard.} secondo quanto riportato dallo standard POSIX 1003.1 nella revisione del 2003, le ``\textit{signal safe function}'' che possono essere -chiamate anche all'interno di un gestore di segnali sono quelle della lista -riportata in fig.~\ref{fig:sig_safe_functions}. +chiamate anche all'interno di un gestore di segnali sono tutte quelle della +lista riportata in fig.~\ref{fig:sig_safe_functions}. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{15cm} + \begin{minipage}[c]{14cm} \func{\_exit}, \func{abort}, \func{accept}, \func{access}, \func{aio\_error} \func{aio\_return}, \func{aio\_suspend}, \func{alarm}, \func{bind}, \func{cfgetispeed}, \func{cfgetospeed}, \func{cfsetispeed}, @@ -2446,6 +2455,27 @@ riportata in fig.~\ref{fig:sig_safe_functions}. \index{funzioni!sicure|)} +Lo standard POSIX.1-2004 modifica la lista di +fig.~\ref{fig:sig_safe_functions} aggiungendo le funzioni \func{\_Exit} e +\func{sockatmark}, mentre lo standard POSIX.1-2008 rimuove della lista le tre +funzioni \func{fpathconf}, \func{pathconf}, \func{sysconf} e vi aggiunge le +ulteriori funzioni in fig.~\ref{fig:sig_safe_functions_posix_2008}. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{14cm} + \func{execl}, \func{execv}, \func{faccessat}, \func{fchmodat}, + \func{fchownat}, \func{fexecve}, \func{fstatat}, \func{futimens}, + \func{linkat}, \func{mkdirat}, \func{mkfifoat}, \func{mknod}, + \func{mknodat}, \func{openat}, \func{readlinkat}, \func{renameat}, + \func{symlinkat}, \func{unlinkat}, \func{utimensat}, \func{utimes}. + \end{minipage} + \normalsize + \caption{Ulteriori funzioni sicure secondo lo standard POSIX.1-2008.} + \label{fig:sig_safe_functions_posix_2008} +\end{figure} + + Per questo motivo è opportuno mantenere al minimo indispensabile le operazioni effettuate all'interno di un gestore di segnali, qualora si debbano compiere operazioni complesse è sempre preferibile utilizzare la tecnica in cui si usa @@ -2465,7 +2495,7 @@ introdotte per la gestione dei cosiddetti ``\textsl{segnali real-time}'', alla gestione avanzata delle temporizzazioni e le nuove interfacce per la gestione di segnali ed eventi attraverso l'uso di file descriptor. -\subsection{I segnali real-time} +\subsection{I segnali \textit{real-time}} \label{sec:sig_real_time} Lo standard POSIX.1b, nel definire una serie di nuove interfacce per i servizi @@ -2512,14 +2542,26 @@ Tutte queste nuove funzionalit sez.~\ref{sec:sig_sigaction}, è disponibile anche con i segnali ordinari, si applicano solo ai nuovi segnali \textit{real-time}; questi ultimi sono accessibili in un intervallo di valori specificati dalle due costanti -\const{SIGRTMIN} e \const{SIGRTMAX},\footnote{in Linux di solito (cioè sulla - piattaforma i386) il primo valore è 33, ed il secondo \code{\_NSIG-1}, che - di norma è 64, per un totale di 32 segnali disponibili, contro gli almeno 8 - richiesti da POSIX.1b.} che specificano il numero minimo e massimo associato -ad un segnale real-time. - -% TODO rivedere secondo man 7 signal con le informazioni aggiornate sul numero -% di segnali real-time disponibili +\const{SIGRTMIN} e \const{SIGRTMAX}, che specificano il numero minimo e +massimo associato ad un segnale \textit{real-time}. + +Su Linux di solito il primo valore è 33, mentre il secondo è \code{\_NSIG-1}, +che di norma (vale a dire sulla piattaforma i386) è 64. Questo dà un totale di +32 segnali disponibili, contro gli almeno 8 richiesti da POSIX.1b. Si tenga +presente però che i primi segnali \textit{real-time} disponibili vendono usati +dalle \acr{glibc} per l'implementazione dei \textit{thread} POSIX (vedi +sez.~\ref{sec:thread_posix_intro}), ed il valore di \const{SIGRTMIN} viene +modificato di conseguenza.\footnote{vengono usati i primi tre per la vecchia + implementazione dei \textit{LinuxThread} ed i primi due per la nuova NTPL + (\textit{New Thread Posix Library}), il che comporta che \const{SIGRTMIN} a + seconda dei casi può essere 34 o 35.} + +Per questo motivo nei programmi che usano i segnali \textit{real-time} non si +deve mai usare un valore assoluto dato che si correrebbe il rischio di +utilizzare un segnale in uso alle librerie, ed il numero del segnale deve +invece essere sempre specificato in forma relativa a \const{SIGRTMIN} (come +\code{SIGRTMIN + n}) avendo inoltre cura di controllare di non aver mai +superato \const{SIGRTMAX}. I segnali con un numero più basso hanno una priorità maggiore e vengono consegnati per primi, inoltre i segnali \textit{real-time} non possono @@ -2530,38 +2572,25 @@ segnale \textit{real-time}.\footnote{lo standard non definisce niente al riguardo ma Linux, come molte altre implementazioni, adotta questa politica.} - Si tenga presente che questi nuovi segnali non sono associati a nessun evento -specifico, a meno di non utilizzarli in meccanismi di notifica come quelli per -l'I/O asincrono (vedi sez.~\ref{sec:file_asyncronous_io}) o per le code di -messaggi POSIX (vedi sez.~\ref{sec:ipc_posix_mq}); pertanto devono essere -inviati esplicitamente. +specifico, a meno di non richiedere specificamente il loro utilizzo in +meccanismi di notifica come quelli per l'I/O asincrono (vedi +sez.~\ref{sec:file_asyncronous_io}) o per le code di messaggi POSIX (vedi +sez.~\ref{sec:ipc_posix_mq}); pertanto devono essere inviati esplicitamente. Inoltre, per poter usufruire della capacità di restituire dei dati, i relativi gestori devono essere installati con \func{sigaction}, specificando per \var{sa\_flags} la modalità \const{SA\_SIGINFO} che permette di utilizzare la forma estesa \var{sa\_sigaction} (vedi sez.~\ref{sec:sig_sigaction}). In -questo modo tutti i segnali real-time possono restituire al gestore una serie -di informazioni aggiuntive attraverso l'argomento \struct{siginfo\_t}, la cui -definizione è stata già vista in fig.~\ref{fig:sig_siginfo_t}, nella -trattazione dei gestori in forma estesa. +questo modo tutti i segnali \textit{real-time} possono restituire al gestore +una serie di informazioni aggiuntive attraverso l'argomento +\struct{siginfo\_t}, la cui definizione è stata già vista in +fig.~\ref{fig:sig_siginfo_t}, nella trattazione dei gestori in forma estesa. -In particolare i campi utilizzati dai segnali real-time sono \var{si\_pid} e -\var{si\_uid} in cui vengono memorizzati rispettivamente il \acr{pid} e -l'user-ID effettivo del processo che ha inviato il segnale, mentre per la -restituzione dei dati viene usato il campo \var{si\_value}. - -Questo è una \ctyp{union} di tipo \struct{sigval\_t} (la sua definizione è in -fig.~\ref{fig:sig_sigval}) in cui può essere memorizzato o un valore numerico, -se usata nella forma \var{sival\_int}, o un indirizzo, se usata nella forma -\var{sival\_ptr}. L'unione viene usata dai segnali real-time e da vari -meccanismi di notifica\footnote{un campo di tipo \struct{sigval\_t} è presente - anche nella struttura \struct{sigevent} (definita in - fig.~\ref{fig:file_sigevent}) che viene usata dai meccanismi di notifica - come quelli per l'I/O asincrono (vedi sez.~\ref{sec:file_asyncronous_io}) o - le code di messaggi POSIX (vedi sez.~\ref{sec:ipc_posix_mq}).} per -restituire dati al gestore del segnale; in alcune definizioni essa viene -identificata anche come \code{union sigval}. +In particolare i campi utilizzati dai segnali \textit{real-time} sono +\var{si\_pid} e \var{si\_uid} in cui vengono memorizzati rispettivamente il +\acr{pid} e l'user-ID effettivo del processo che ha inviato il segnale, mentre +per la restituzione dei dati viene usato il campo \var{si\_value}. \begin{figure}[!htb] \footnotesize \centering @@ -2573,6 +2602,18 @@ identificata anche come \code{union sigval}. \label{fig:sig_sigval} \end{figure} +Questo è una \ctyp{union} di tipo \struct{sigval\_t} (la sua definizione è in +fig.~\ref{fig:sig_sigval}) in cui può essere memorizzato o un valore numerico, +se usata nella forma \var{sival\_int}, o un indirizzo, se usata nella forma +\var{sival\_ptr}. L'unione viene usata dai segnali \textit{real-time} e da +vari meccanismi di notifica\footnote{un campo di tipo \struct{sigval\_t} è + presente anche nella struttura \struct{sigevent} (definita in + fig.~\ref{fig:file_sigevent}) che viene usata dai meccanismi di notifica + come quelli per l'I/O asincrono (vedi sez.~\ref{sec:file_asyncronous_io}) o + le code di messaggi POSIX (vedi sez.~\ref{sec:ipc_posix_mq}).} per +restituire dati al gestore del segnale; in alcune definizioni essa viene +identificata anche come \code{union sigval}. + A causa delle loro caratteristiche, la funzione \func{kill} non è adatta ad inviare segnali \textit{real-time}, poiché non è in grado di fornire alcun valore per \struct{sigval\_t}; per questo motivo lo standard ha previsto una @@ -2604,25 +2645,32 @@ di errore senza inviare nessun segnale. Se il segnale è bloccato la funzione ritorna immediatamente, se si è installato un gestore con \const{SA\_SIGINFO} e ci sono risorse disponibili, -(vale a dire che c'è posto\footnote{la profondità della coda è indicata dalla - costante \const{SIGQUEUE\_MAX}, una della tante costanti di sistema definite +(vale a dire che c'è posto nella coda dei segnali \textit{real-time}) esso +viene inserito e diventa pendente; una volta consegnato riporterà nel campo +\var{si\_code} di \struct{siginfo\_t} il valore \const{SI\_QUEUE} e il campo +\var{si\_value} riceverà quanto inviato con \param{value}. Se invece si è +installato un gestore nella forma classica il segnale sarà generato, ma tutte +le caratteristiche tipiche dei segnali \textit{real-time} (priorità e coda) +saranno perse. + +Secondo lo standard POSIX la profondità della coda è indicata dalla costante +\const{SIGQUEUE\_MAX},\footnote{una della tante costanti di sistema definite dallo standard POSIX che non abbiamo riportato esplicitamente in - sez.~\ref{sec:sys_limits}; il suo valore minimo secondo lo standard, - \const{\_POSIX\_SIGQUEUE\_MAX}, è pari a 32. Nel caso di Linux questo è uno - dei parametri del kernel impostabili sia con \func{sysctl}, che scrivendolo - direttamente in \procfile{/proc/sys/kernel/rtsig-max}, il valore predefinito - è di 1024.} nella coda dei segnali real-time) esso viene inserito e diventa -pendente; una volta consegnato riporterà nel campo \var{si\_code} di -\struct{siginfo\_t} il valore \const{SI\_QUEUE} e il campo \var{si\_value} -riceverà quanto inviato con \param{value}. Se invece si è installato un -gestore nella forma classica il segnale sarà generato, ma tutte le -caratteristiche tipiche dei segnali real-time (priorità e coda) saranno perse. + sez.~\ref{sec:sys_limits}.} il suo valore minimo secondo lo standard, +\const{\_POSIX\_SIGQUEUE\_MAX}, è pari a 32. Nel caso di Linux la coda ha una +dimensione variabile; fino alla versione 2.6.7 c'era un limite massimo globale +che poteva essere impostato come parametro del kernel in +\procfile{/proc/sys/kernel/rtsig-max};\footnote{ed il valore predefinito era + pari a 1024.} a partire dal kernel 2.6.8 il valore globale è stato rimosso e +sostituito dalla risorsa \const{RLIMIT\_SIGPENDING} associata al singolo +utente, che può essere modificata con \func{setrlimit} come illustrato in +sez.~\ref{sec:sys_resource_limit}. Lo standard POSIX.1b definisce inoltre delle nuove funzioni che permettono di gestire l'attesa di segnali specifici su una coda, esse servono in particolar modo nel caso dei \itindex{thread} \textit{thread}, in cui si possono usare i -segnali real-time come meccanismi di comunicazione elementare; la prima di -queste funzioni è \funcd{sigwait}, il cui prototipo è: +segnali \textit{real-time} come meccanismi di comunicazione elementare; la +prima di queste funzioni è \funcd{sigwait}, il cui prototipo è: \begin{prototype}{signal.h} {int sigwait(const sigset\_t *set, int *sig)} @@ -2641,11 +2689,11 @@ queste funzioni La funzione estrae dall'insieme dei segnali pendenti uno qualunque dei segnali specificati da \param{set}, il cui valore viene restituito in \param{sig}. Se sono pendenti più segnali, viene estratto quello a priorità più alta (cioè con -il numero più basso). Se, nel caso di segnali real-time, c'è più di un segnale -pendente, ne verrà estratto solo uno. Una volta estratto il segnale non verrà -più consegnato, e se era in una coda il suo posto sarà liberato. Se non c'è -nessun segnale pendente il processo viene bloccato fintanto che non ne arriva -uno. +il numero più basso). Se, nel caso di segnali \textit{real-time}, c'è più di +un segnale pendente, ne verrà estratto solo uno. Una volta estratto il segnale +non verrà più consegnato, e se era in una coda il suo posto sarà liberato. Se +non c'è nessun segnale pendente il processo viene bloccato fintanto che non ne +arriva uno. Per un funzionamento corretto la funzione richiede che alla sua chiamata i segnali di \param{set} siano bloccati. In caso contrario si avrebbe un @@ -2666,8 +2714,8 @@ prevalentemente con i \itindex{thread} \textit{thread}; \funcd{sigwaitinfo} e Analoga a \func{sigwait}, ma riceve anche le informazioni associate al segnale in \param{info}. - \funcdecl{int sigtimedwait(const sigset\_t *set, siginfo\_t *value, const - struct timespec *info)} + \funcdecl{int sigtimedwait(const sigset\_t *set, siginfo\_t *info, const + struct timespec *timout)} Analoga a \func{sigwaitinfo}, con un la possibilità di specificare un timeout in \param{timeout}. @@ -2716,14 +2764,316 @@ riceverlo fra due chiamate successive. \subsection{La gestione avanzata delle temporizzazioni} \label{sec:sig_timer_adv} -% TODO trattare i Posix timer, e le fuzioni: +Sia le funzioni per la gestione dei tempi viste in +sez.~\ref{sec:sys_cpu_times} che quelle per la gestione dei timer di +sez.~\ref{sec:sig_alarm_abort} sono state a lungo limitate dalla risoluzione +massima dei tempi dell'orologio interno del kernel, che era quella ottenibile +dal timer di sistema che governa lo \textit{scheduler},\footnote{e quindi + limitate dalla frequenza dello stesso che si ricordi, come già illustrato in + sez.~\ref{sec:proc_hierarchy}, è data dal valore della costante + \texttt{HZ}.} i contatori usati per il calcolo dei tempo infatti erano +basati sul numero di \itindex{jiffies} \textit{jiffies} che vengono +incrementati ad ogni \textit{clock tick} del timer di sistema.\footnote{il che + comportava anche, come accennato in sez.~\ref{sec:sig_alarm_abort} per + \func{setitimer}, problemi per il massimo periodo di tempo copribile da + alcuni di questi orologi, come quelli associati al \textit{process time} + almeno fino a quando, con il kernel 2.6.16, non è stato rimosso il limite di + un valore a 32 bit per i \textit{jiffies}.} + +Nelle architetture moderne però tutti i computer sono dotati di temporizzatori +hardware che possono supportare risoluzioni molto elevate, ed in maniera del +tutto indipendente dalla frequenza scelta per il timer di sistema che governa +lo \textit{scheduler};\footnote{normalmente si possono ottenere precisioni + fino al microsecondo, andando molto oltre in caso di hardware dedicato.} per +questo lo standard POSIX ha previsto una serie di nuove funzioni relative a a +quelli che vengono chiamati ``\textsl{orologi} \textit{real-time}'', in grado +di supportare risoluzioni fino al nanosecondo. Inoltre le CPU più moderne sono +dotate a loro volta di contatori ad alta definizione che consentono una grande +accuratezza nella misura del tempo da esse dedicato all'esecuzione di un +processo. + +Per usare queste funzionalità ed ottenere risoluzioni temporali più accurate, +occorre però un opportuno supporto da parte del kernel, ed i cosiddetti +\textit{high resolution timer} che consentono di fare ciò sono stati +introdotti nel kernel ufficiale solo a partire dalla versione +2.6.21.\footnote{deve essere stata abilitata l'opzione di compilazione + \texttt{CONFIG\_HIGH\_RES\_TIMERS}, erano però disponibili anche in + precedenza come patch facenti parte dello sviluppo delle estensioni + \textit{real-time} del kernel, per cui alcune distribuzioni possono avere + questo supporto anche con versioni precedenti del kernel.} Le funzioni +definite dallo standard POSIX per gestire orologi ad alta definizione però +erano già presenti, essendo stata introdotte insieme ad altre funzioni per il +supporto delle estensioni \textit{real-time} con il rilascio del kernel 2.6, +ma la risoluzione effettiva era nominale. + +A tutte le implementazioni che si rifanno a queste estensioni è richiesto di +disporre di una versione \textit{real-time} almeno per l'orologio generale di +sistema, quello che mantiene il \textit{calendar time} (vedi +sez.~\ref{sec:sys_time_base}), che in questa forma deve indicare il numero di +secondi e nanosecondi passati a partire dal primo gennaio 1970 (\textit{The + Epoch}).\footnote{si ricordi che l'orologio ordinario usato dal + \textit{calendar time} riporta solo un numero di secondi, e che la + risoluzione effettiva normalmente non raggiunge il nanosecondo (a meno di + hardware specializzato).} Oltre all'orologio generale di sistema possono +essere presenti altri tipi di orologi \textit{real-time}, ciascuno dei quali +viene identificato da un opportuno valore di una variabile di tipo +\type{clockid\_t}; un elenco di quelli disponibili su Linux è riportato in +tab.~\ref{tab:sig_timer_clockid_types}. + +\begin{table}[htb] + \footnotesize + \centering + \begin{tabular}[c]{|l|p{8cm}|} + \hline + \textbf{Valore} & \textbf{Significato} \\ + \hline + \hline + \const{CLOCK\_REALTIME} & Orologio \textit{real-time} di sistema, può + essere impostato solo con privilegi + amministrativi.\\ + \const{CLOCK\_MONOTONIC} & Orologio che indica un tempo monotono + crescente (a partire da un tempo iniziale non + specificati) che non può essere modificato.\\ + \const{CLOCK\_MONOTONIC\_RAW}&Simile al precedente, ma non subisce gli + aggiustamenti dovuti all'uso di NTP (viene + usato per fare riferimento ad una fonte + hardware.\footnotemark\\ + \const{CLOCK\_PROCESS\_CPUTIME\_ID}& contatore del tempo di CPU usato + da un processo (il \textit{process time} di + sez.~\ref{sec:sys_cpu_times}, nel totale di + \textit{system time} e \textit{user time}) + comprensivo di tutto il tempo di CPU usato + da eventuali \itindex{thread} + \textit{thread}.\\ + \const{CLOCK\_THREAD\_CPUTIME\_ID}& contatore del tempo di CPU + (\textit{user time} e \textit{system time}) + usato da un singolo \itindex{thread} + \textit{thread}.\\ +% \const{} & .\\ + \hline + \end{tabular} + \caption{Valori possibili per una variabile di tipo \type{clockid\_t} + usata per indicare a quale tipo di orologio si vuole fare riferimento.} + \label{tab:sig_timer_clockid_types} +\end{table} + +\footnotetext{specifico di Linux, introdotto a partire dal kernel 2.6.28, non + previsto da POSIX e non presente in altri sistemi unix-like.} + +Per poter utilizzare queste funzionalità le \acr{glibc} richiedono che la +macro \macro{\_POSIX\_C\_SOURCE} sia definita ad un valore maggiore o uguale +di \texttt{199309L} (vedi sez.~\ref{sec:intro_gcc_glibc_std}), inoltre i +programmi che le usano devono essere linkati con la libreria delle estensioni +\textit{real-time} usando esplicitamente l'opzione \texttt{-lrt}. Si tenga +presente inoltre che la disponibilità di queste funzionalità avanzate può +essere controllato dalla definizione della macro \macro{\_POSIX\_TIMERS} ad un +valore maggiore di 0, e che le ulteriori macro +\macro{\_POSIX\_MONOTONIC\_CLOCK}, \macro{\_POSIX\_CPUTIME} e +\macro{\_POSIX\_THREAD\_CPUTIME} indicano la presenza dei rispettivi orologi +di tipo \const{CLOCK\_MONOTONIC}, \const{CLOCK\_PROCESS\_CPUTIME\_ID} e +\const{CLOCK\_PROCESS\_CPUTIME\_ID}.\footnote{tutte queste macro sono definite + in \texttt{unistd.h}, che peranto deve essere incluso per poterle + controllarle.} Infine se il kernel ha il supporto per gli \textit{high + resolution timer} un elenco degli orologi e dei timer può essere ottenuto +tremite il file \procfile{/proc/timer\_list}. + +Le due funzioni che ci consentono rispettivamente di modificare o leggere il +valore per uno degli orologi \textit{real-time} sono \funcd{clock\_settime} e +\funcd{clock\_gettime}; i rispettivi prototipi sono: +\begin{functions} + \headdecl{time.h} + + \funcdecl{int clock\_settime(clockid\_t clockid, const struct timespec *tp)} + \funcdecl{int clock\_gettime(clockid\_t clockid, struct timespec *tp)} + + Imposta o legge un orologio \textit{real-time}. + + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà uno dei seguenti valori: + \begin{errlist} + \item[\errcode{EINVAL}] il valore specificato per \param{clockid} non è + valido o il relativo orologio \textit{real-time} non è supportato dal + sistema. + \item[\errcode{EPERM}] non si ha il permesso di impostare l'orologio + indicato (solo per \func{clock\_settime}). + \item[\errcode{EFAULT}] l'indirizzo \param{tp} non è valido. + \end{errlist} +} +\end{functions} + +Entrambe le funzioni richiedono che si specifichi come primo argomento il tipo +di orologio su cui si vuole operare con uno dei valori di +tab.~\ref{tab:sig_timer_clockid_types} o con il risultato di una chiamata a +\func{clock\_getcpuclockid} (che tratteremo a breve), il secondo argomento +invece è sempre il puntatore \param{tp} ad una struttura \struct{timespec} +(vedi fig.~\ref{fig:sys_timespec_struct}) che deve essere stata +precedentemente allocata; nel primo caso questa devrà anche essere stata +inizializzata con il valore che si vuole impostare sull'orologio, mentre nel +secondo verrà restituito al suo interno il valore corrente dello stesso. + +Si tenga presente inoltre che per eseguire un cambiamento sull'orologio +generale di sistema \const{CLOCK\_REALTIME} occorrono i privilegi +amministrativi;\footnote{ed in particolare la \textit{capability} + \const{CAP\_SYS\_TIME}.} inoltre ogni cambiamento ad esso apportato non avrà +nessun effetto sulle temporizzazioni effettuate in forma relativa, come quelle +impostate sulle quantità di \textit{process time} o per un intervallo di tempo +da trascorrere, ma solo su quelle che hanno richiesto una temporizzazione ad +un istante preciso (in termini di \textit{calendar time}). Si tenga inoltre +presente che nel caso di Linux \const{CLOCK\_REALTIME} è l'unico orologio per +cui si può effettuare una modifica, infatti nonostante lo standard preveda la +possibilità di modifiche anche per \const{CLOCK\_PROCESS\_CPUTIME\_ID} e +\const{CLOCK\_THREAD\_CPUTIME\_ID}, il kernel non le consente. + +Oltre alle due funzioni precedenti, lo standard POSIX prevede una terza +funzione che consenta di ottenere la risoluzione effettiva fornita da un certo +orologio, la funzione è \funcd{clock\_getres} ed il suo prototipo è: +\begin{functions} + \headdecl{time.h} + + \funcdecl{int clock\_getres(clockid\_t clockid, struct timespec *res)} + + Legge la risoluzione di un orologio \textit{real-time}. + + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà uno dei seguenti valori: + \begin{errlist} + \item[\errcode{EINVAL}] il valore specificato per \param{clockid} non è + valido. + \item[\errcode{EFAULT}] l'indirizzo di \param{res} non è valido. + \end{errlist} +} +\end{functions} + +La funzione richiede come primo argomento l'indicazione dell' orologio di cui +si vuole conoscere la risoluzione (effettuata allo stesso modo delle due +precedenti) e questa verrà restituita in una struttura \struct{timespec} +all'indirizzo puntato dall'argomento \param{res}. + +Come accennato il valore di questa risoluzione dipende sia dall'hardware +disponibile che dalla implementazione delle funzioni, e costituisce il limite +minimo di un intervallo di tempo che si può indicare, qualunque valore si +voglia utilizzare nelle funzioni di impostazione che non corrisponda ad un +multiplo intero di questa risoluzione, sarà troncato in maniera automatica. + +Si tenga presente inoltre che con l'introduzione degli \textit{high resolution + timer} i due orologi \const{CLOCK\_PROCESS\_CPUTIME\_ID} e +\const{CLOCK\_THREAD\_CPUTIME\_ID} fanno riferimento ai contatori presenti in +opportuni registri interni del processore; questo sui sistemi multiprocessore +può avere delle ripercussioni sulla precisione delle misure di tempo che vanno +al di là della risoluzione teorica ottenibile con \func{clock\_getres}, che +può essere ottenuta soltanto quando si è sicuri che un processo (o un +\textit{thread}) sia sempre stato eseguito sullo stesso processore. + +Con i sistemi multiprocessore infatti ogni singola CPU ha i suoi registri +interni, e se ciascuna di esse utilizza una base di tempo diversa (se cioè il +clock del processore non è unico) avendo queste in genere frequenze +leggermente diverse, otterremo dei valori dei contatori scorrelati fra loro +senza possibilità di sincronizzazione. + +Il problema si presenta, in forma più lieve, anche se la base di tempo è la +stessa, dato che un sistema multiprocessore non avvia mai tutte le CPU allo +stesso istante, si potrà così avere di nuovo una differenza fra i contatori, +soggetta però soltanto ad uno sfasamento costante. Per questo caso il kernel +per alcune architetture ha del codice che consente di ridurre al minimo la +differenza, ma non può essere comunque garantito che questa si annulli (anche +se in genere risulta molto piccola e trascurabile nella gran parte dei casi). + +Per poter gestire questo tipo di problematiche lo standard ha previsto una +apposita funzione che sia in grado di ottenere l'identificativo dell'orologio +associato al \textit{process time} di un processo, la funzione è +\funcd{clock\_getcpuclockid} ed il suo prototipo è: +\begin{functions} + \headdecl{time.h} + + \funcdecl{int clock\_getcpuclockid(pid\_t pid, clockid\_t *clockid)} + + Ottiene l'identificatore dell'orologio di CPU usato da un processo. + + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà uno dei seguenti valori: + \begin{errlist} + \item[\errcode{ENOSYS}] il valore specificato per \param{clockid} non è + valido. + \item[\errcode{EPERM}] l'indirizzo di \param{res} non è valido. + \item[\errcode{ENOENT}] non c'è modo di avere + \item[\errcode{ESRCH}] non esiste il processo \param{pid}. + \end{errlist} +} +\end{functions} + + +% TODO trattare gli orologi ad alta definizione e le funzioni POSIX per gli +% stessi cioè: % clock_getres clock_gettime clock_settime (vedi man page) + +Abbiamo visto in sez.~\ref{sec:sig_alarm_abort} come l'interfaccia di +\func{setitimer} derivata da BSD presenti delle limitazioni,\footnote{in + particolare la possibilità di perdere un segnale sotto carico.} tanto che +nello standard POSIX.1-2008 questa viene marcata come obsoleta, e ne viene +fortemente consigliata la sostituzione con nuova interfaccia definita dallo +standard POSIX.1-2001 che va sotto il nome di \textit{Posix Timer API}. + +La \textit{system call} per la nuova interfaccia sono stata introdotte a +partire dal kernel 2.6, ma fino al kernel 2.6.16 la precisione degli allarmi +era limitata dalla risoluzione del timer di sistema, e solo a partire dal +kernel 2.6.21, con la implementazione delle temporizzazioni ad alta +definizione, la risoluzione corrisponde a quella fornita dall'hardware +disponibile. + +Una delle principali differenze della nuova interfaccia è che un processo può +utilizzare un numero arbitrario di timer; questi vengono creati (ma non +avviati) tramite la funzione \funcd{timer\_create}, il cui prototipo è: +\begin{functions} + \headdecl{signal.h} + \headdecl{time.h} + + \funcdecl{int timer\_create(clockid\_t clockid, struct sigevent *evp, + timer\_t *timerid)} + + Crea un nuovo timer Posix. + + \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di + errore, nel qual caso \var{errno} assumerà uno dei valori già visti per + \func{sigwait}, ai quali si aggiunge, per \func{sigtimedwait}: + \begin{errlist} + \item[\errcode{EAGAIN}] fallimento nel tentativo di allocare le strutture + dei timer. + \item[\errcode{EINVAL}] uno dei valori specificati per \param{clockid} o per + i campi \var{sigev\_notify}, \var{sigev\_signo} o + \var{sigev\_notify\_thread\_id} di \param{evp} non è valido. + \item[\errcode{ENOMEM}] errore di allocazione della memoria. + \end{errlist} +} +\end{functions} + +La funzione richiede tre argomenti, il primo serve ad indicare quale tipo di +orologio + + + fig.~\ref{fig:file_sigevent} + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includestruct{listati/sigevent.h} + \end{minipage} + \normalsize + \caption{La struttura \structd{sigevent}, usata per specificare le modalità + di notifica degli eventi relativi alle operazioni di I/O asincrono.} + \label{fig:file_sigevent} +\end{figure} + + + + + +% TODO trattare i Posix timer, e le fuzioni: % timer_getoverrun, timer_gettime, timer_settime, timer_create, timer_delete \subsection{Le interfacce per la notifica attraverso i file descriptor} \label{sec:sig_signalfd_eventfd} - + % TODO trattare qui eventfd signalfd e timerfd introdotte con il 2.6.22 % timerfd è stata tolta nel 2.6.23 e rifatta per bene nel 2.6.25 @@ -2781,7 +3131,11 @@ riceverlo fra due chiamate successive. % LocalWords: INTDIV INTOVF FLTDIV FLTOVF FLTUND underflow FLTRES FLTINV SEGV % LocalWords: FLTSUB MAPERR ACCERR ADRALN ADRERR OBJERR BRKPT CLD EXITED MSG % LocalWords: KILLED DUMPED TRAPPED STOPPED CONTINUED PRI HUP SigFunc jiffies -% LocalWords: SEC +% LocalWords: SEC unsafe sockatmark execl execv faccessat fchmodat fchownat +% LocalWords: fexecve fstatat futimens linkat mkdirat mkfifoat mknod mknodat +% LocalWords: openat readlinkat renameat symlinkat unlinkat utimensat utimes +% LocalWords: LinuxThread NTPL Library clockid evp timerid sigev notify high +% LocalWords: resolution CONFIG RES patch REALTIME MONOTONIC RAW NTP CPUTIME %%% Local Variables: