Materiale rimasto indietro e segnali real time
authorSimone Piccardi <piccardi@gnulinux.it>
Mon, 16 Aug 2021 18:27:48 +0000 (20:27 +0200)
committerSimone Piccardi <piccardi@gnulinux.it>
Mon, 16 Aug 2021 18:27:48 +0000 (20:27 +0200)
listati/Action.c [new file with mode: 0644]
listati/SigAction.c [new file with mode: 0644]
listati/rtsigvalsend.c [new file with mode: 0644]
listati/rtsigvalsend_handl.c [new file with mode: 0644]
signal.tex
sources/rtsigvalsend.c

diff --git a/listati/Action.c b/listati/Action.c
new file mode 100644 (file)
index 0000000..b119244
--- /dev/null
@@ -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 (file)
index 0000000..adfbec2
--- /dev/null
@@ -0,0 +1 @@
+typedef void SigAction(int, siginfo_t *, void *);
diff --git a/listati/rtsigvalsend.c b/listati/rtsigvalsend.c
new file mode 100644 (file)
index 0000000..9689734
--- /dev/null
@@ -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 (file)
index 0000000..a58e0be
--- /dev/null
@@ -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);
+}
index 78d5080e82d5c51be297921fdcdb1aa9bec1b7a0..63a940027b3d5c027e23e0f5d23bbfa596701d1a 100644 (file)
@@ -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}
index a1e022d518d7e9a4bc669ced498994f24ea534f1..c989488e50258eb484863914bb0f66640b6df25b 100644 (file)
@@ -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);