From: Simone Piccardi Date: Mon, 16 Aug 2021 18:27:48 +0000 (+0200) Subject: Materiale rimasto indietro e segnali real time X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=381b50b7a33f32f8f262e59a6cdf16faf57c94ae Materiale rimasto indietro e segnali real time --- diff --git a/listati/Action.c b/listati/Action.c new file mode 100644 index 0000000..b119244 --- /dev/null +++ b/listati/Action.c @@ -0,0 +1,15 @@ +inline SigAction * Action(int signo, SigAction *func) +{ + struct sigaction new_handl, old_handl; + new_handl.sa_flags=SA_SIGINFO; /* we use sa_sigaction handler */ + new_handl.sa_sigaction = func; /* set signal handler */ + /* clear signal mask: no signal blocked during execution of func */ + if (sigemptyset(&new_handl.sa_mask)!=0){ /* initialize signal set */ + return NULL; + } + /* change action for signo signal */ + if (sigaction(signo, &new_handl, &old_handl)){ + return NULL; + } + return (old_handl.sa_sigaction); +} diff --git a/listati/SigAction.c b/listati/SigAction.c new file mode 100644 index 0000000..adfbec2 --- /dev/null +++ b/listati/SigAction.c @@ -0,0 +1 @@ +typedef void SigAction(int, siginfo_t *, void *); diff --git a/listati/rtsigvalsend.c b/listati/rtsigvalsend.c new file mode 100644 index 0000000..9689734 --- /dev/null +++ b/listati/rtsigvalsend.c @@ -0,0 +1,28 @@ +int main(int argc, char *argv[], char *envp[]) +{ + char buffer[MAXLINE+1]; + int nread; + sigval_t value; + int signo = SIGRTMIN+1; + + struct sigaction new_handl, old_handl; + sigemptyset(&new_handl.sa_mask); + new_handl.sa_sigaction = sig_handler; + new_handl.sa_flags=SA_SIGINFO; + /* change action for signo signal */ + sigaction(signo, &new_handl, &old_handl); + while (1) { + nread = read(STDIN_FILENO, buffer, MAXLINE); + if (nread < 0) { + printf("Errore in lettura: %s\n", strerror(errno)); + return 0; + } + buffer[nread]=0; + value.sival_int = strtol(buffer, NULL, 10); + if (value.sival_int > 0) { + sigqueue(getpid(), signo, value); + } else { + printf("Ignoring invalid input\n"); + } + } +} diff --git a/listati/rtsigvalsend_handl.c b/listati/rtsigvalsend_handl.c new file mode 100644 index 0000000..a58e0be --- /dev/null +++ b/listati/rtsigvalsend_handl.c @@ -0,0 +1,6 @@ +void sig_handler(int signum, siginfo_t *info, void *ucontext) { + printf("Signal %d\n", signum); + printf("From pid %d\n", info->si_pid); + printf("From user %d\n", info->si_uid); + printf("Value %d\n", info->si_value.sival_int); +} diff --git a/signal.tex b/signal.tex index 78d5080..63a9400 100644 --- a/signal.tex +++ b/signal.tex @@ -2920,10 +2920,11 @@ stata già vista in fig.~\ref{fig:sig_siginfo_t}, nella trattazione dei gestori in forma estesa. In particolare i campi di \struct{siginfo\_t} utilizzati dai segnali -\textit{real-time} sono \var{si\_pid} e \var{si\_uid} in cui vengono -memorizzati rispettivamente il \ids{PID} e l'\ids{UID} effettivo del processo -che ha inviato il segnale, ed il campo \var{si\_value} che viene usato -appositamente per poter restituire dei dati al gestore. +\textit{real-time} sono \var{si\_pid} e \var{si\_uid} in cui vengono riportati +rispettivamente il \ids{PID} e l'\ids{UID} effettivo del processo che ha +inviato il segnale, e lo specifico campo \var{si\_value}. Questo campo viene +indicato in fig.~\ref{fig:sig_siginfo_t} come di tipo \type{sigval\_t}; se ne +è riportata la definizione in fig.~\ref{fig:sig_sigval}. \begin{figure}[!htb] \footnotesize \centering @@ -2936,27 +2937,24 @@ appositamente per poter restituire dei dati al gestore. \label{fig:sig_sigval} \end{figure} -Detto campo, la cui definizione è riportata in fig.~\ref{fig:sig_sigval}, -viene indicato con il tipo di dato \type{sigval\_t}, che è una \dirct{union} -di tipo \struct{sigval} in cui può essere memorizzato o un valore numerico, se -usata nella forma \var{sival\_int}, o un puntatore, se usata nella forma -\var{sival\_ptr}. - -L'unione viene usata dai segnali \textit{real-time} e da vari meccanismi di -notifica per restituire dati al gestore del segnale in \var{si\_value}. Un -campo di tipo \type{sigval\_t} è presente anche nella struttura -\struct{sigevent} (definita in fig.~\ref{fig:struct_sigevent}) che viene usata -dai meccanismi di notifica come quelli per i timer POSIX (vedi -sez.~\ref{sec:sig_timer_adv}), l'I/O asincrono (vedi -sez.~\ref{sec:file_asyncronous_io}) o le code di messaggi POSIX (vedi -sez.~\ref{sec:ipc_posix_mq}). -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 il campo \var{si\_value} restituito nella struttura -\struct{siginfo\_t} prevista da un gestore in forma estesa. Per questo motivo -lo standard ha previsto una nuova funzione, \funcd{sigqueue}, il cui prototipo -è: +Si tratta quindi di una unione \struct{sigval} con due possibili campi +alternativi in cui può essere memorizzato o un valore numerico, se usata con +\var{sival\_int}, o un puntatore, se usata con \var{sival\_ptr}. L'unione +viene usata dai segnali \textit{real-time}, ma anche da vari altri meccanismi +di notifica, per inviare eventuali informazioni aggiuntive al gestore del +segnale in \var{si\_value}. Ad esempio un campo di tipo \type{sigval\_t} è +presente anche nella struttura \struct{sigevent} (definita in +fig.~\ref{fig:struct_sigevent}) che viene usata da vari meccanismi di notifica +come quelli per i timer POSIX (che vedremo in sez.~\ref{sec:sig_timer_adv}), +quello dell'I/O asincrono (che vedremo in sez.~\ref{sec:file_asyncronous_io}) +o dalle code di messaggi POSIX (che vedremo in sez.~\ref{sec:ipc_posix_mq}). + +A causa di questa loro caratteristica, la funzione \func{kill}, pure essendo +utilizzabile, non è adatta ad inviare segnali \textit{real-time}, perché non è +in grado di impostare alcun valore per il campo \var{si\_value}. Per questo +motivo lo standard POSIX ha previsto una nuova funzione, \funcd{sigqueue}, il +cui prototipo è: \begin{funcproto}{ \fhead{signal.h} @@ -2978,7 +2976,6 @@ lo standard ha previsto una nuova funzione, \funcd{sigqueue}, il cui prototipo } \end{funcproto} - La funzione invia il segnale indicato dall'argomento \param{signo} al processo indicato dall'argomento \param{pid}. Per il resto il comportamento della funzione è analogo a quello di \func{kill}, ed i privilegi occorrenti ad @@ -3098,6 +3095,53 @@ che venga eseguita l'azione predefinita, devono essere mascherati per tutti i \textit{thread}, compreso quello dedicato alla gestione, che potrebbe riceverlo fra due chiamate successive. +Come esempio elementare dell'uso dei segnali \textit{real-time}, e della +possibilità di inviare informazioni al gestore degli stessi con +\func{sigqueue}, si è riportato in fig.~\ref{fig:sig_rtsival_main} il corpo +principale di un programma elementare che legge dal terminale un valore +numerico, ed utilizza un segnale \textit{real-time} per inviarlo al gestore +dello stesso. Si sono trascurati i controlli dei valori di ritorno delle varie +funzioni per brevità. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{\codesamplewidth} + \includecodesample{listati/rtsigvalsend.c} + \end{minipage} + \normalsize + \caption{Corpo principale di un programma di invio di segnali + \textit{real-time}.} + \label{fig:sig_rtsival_main} +\end{figure} + +Dopo aver definito (\texttt{\small 5}) una variabile \var{value} di tipo +\type{sigval\_t} per inviare i dati, ed aver opportunamente scelto +(\texttt{\small 6}) per \var{signo} un segnale \textit{real-time}, la parte +iniziale del programma (\texttt{\small 8--11}) installa il relativo gestore +(la cui definizione è riportata in fig.~\ref{fig:sig_rtsival_handl}), dopo di +che il programma si pone in un ciclo infinito (\texttt{\small 14--27}) in cui +prima (\texttt{\small 15--20}) legge in buffer dallo \textit{standard input} +una stringa immessa dall'utente, terminandola opportunamente (\texttt{\small + 20}), e poi tenta di convertire la stessa (\texttt{\small 21}) in un numero +con \func{strtol}, assegnando il risultato a \texttt{value.sival\_int}, se la +conversione ha successo e \texttt{value.sival\_int} è positivo) invia a se +stesso (\texttt{\small 23}) il segnale \textit{real-time}, altrimenti stampa +un avviso (\texttt{\small 24}). + + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{\codesamplewidth} + \includecodesample{listati/rtsigvalsend_handl.c} + \end{minipage} + \normalsize + \caption{Codice del gestore.} + \label{fig:sig_rtsival_handl} +\end{figure} + + + + \subsection{La gestione avanzata delle temporizzazioni} \label{sec:sig_timer_adv} diff --git a/sources/rtsigvalsend.c b/sources/rtsigvalsend.c index a1e022d..c989488 100644 --- a/sources/rtsigvalsend.c +++ b/sources/rtsigvalsend.c @@ -39,7 +39,7 @@ #define MAXLINE 256 -void SigHand(int signum, siginfo_t *info, void *ucontext) { +void sig_handler(int signum, siginfo_t *info, void *ucontext) { printf("Signal %d\n", signum); printf("From pid %d\n", info->si_pid); printf("From user %d\n", info->si_uid); @@ -54,8 +54,8 @@ int main(int argc, char *argv[], char *envp[]) int signo = SIGRTMIN+1; struct sigaction new_handl, old_handl; - new_handl.sa_sigaction = SigHand; sigemptyset(&new_handl.sa_mask); + new_handl.sa_sigaction = sig_handler; new_handl.sa_flags=SA_SIGINFO; /* change action for signo signal */ sigaction(signo, &new_handl, &old_handl);