X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=prochand.tex;h=16c51de94a0fd6fb69ff199b94eeaf5a0d346948;hp=30e272c5494d3c635f49c564460c894468812eb1;hb=ae7bf994013ffbf4f5ef1d5a38a18033593e3e9f;hpb=ee65c9e30267ed1b0c0cef337c3ff86f9e0b370d diff --git a/prochand.tex b/prochand.tex index 30e272c..16c51de 100644 --- a/prochand.tex +++ b/prochand.tex @@ -1937,17 +1937,18 @@ solo l'\ids{UID} effettivo, e soltanto se il valore specificato corrisponde o all'\ids{UID} reale o all'\ids{UID} salvato, ottenendo un errore di \errcode{EPERM} negli altri casi. -E' importante notare che la funzione può fallire con \errval{EAGAIN} anche -quando viene invocata da un processo con privilegi di amministratore per -cambiare il proprio l'\ids{UID} reale, sia per una temporanea indisponibilità -di risorse del kernel, sia perché l'utente di cui si vuole assumere -l'\ids{UID} andrebbe a superare un eventuale limite sul numero di processi (il -limite \const{RLIMIT\_NPROC}, che tratteremo in -sez.~\ref{sec:sys_resource_limit}),\footnote{non affronteremo qui l'altro caso - di errore, che può avvenire solo quando si esegue la funzione all'interno di - un diverso \textit{user namespace}, argomento su cui torneremo in - sez.~\ref{sec:process_namespaces}.} pertanto occorre sempre verificare lo -stato di uscita della funzione. +E' importante notare che la funzione può fallire, con +\errval{EAGAIN},\footnote{non affronteremo qui l'altro caso di errore, che può + avvenire solo quando si esegue la funzione all'interno di un diverso + \textit{user namespace}, argomento su cui torneremo in + sez.~\ref{sec:process_namespaces} ma la considerazione di controllare sempre + lo stato di uscita si applica allo stesso modo.} anche quando viene invocata +da un processo con privilegi di amministratore per cambiare il proprio +l'\ids{UID} reale, sia per una temporanea indisponibilità di risorse del +kernel, sia perché l'utente di cui si vuole assumere l'\ids{UID} andrebbe a +superare un eventuale limite sul numero di processi (il limite +\const{RLIMIT\_NPROC}, che tratteremo in sez.~\ref{sec:sys_resource_limit}), +pertanto occorre sempre verificare lo stato di uscita della funzione. Non controllare questo tipo di errori perché si presume che la funzione abbia sempre successo quando si hanno i privilegi di amministratore può avere @@ -2099,7 +2100,8 @@ del gruppo \textit{effective} ed i loro prototipi sono: \fdesc{Imposta il \ids{GID} effettivo del processo corrente.} } {Le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, nel qual -caso \var{errno} assume i valori visti per \func{setuid}/\func{setgid}. + caso \var{errno} assume i valori visti per \func{setuid}/\func{setgid} + tranne \errval{EAGAIN}. } \end{funcproto} @@ -2126,7 +2128,7 @@ un completo controllo su tutti e tre i gruppi di identificatori \fdesc{Imposta il \ids{GID} reale, effettivo e salvato del processo corrente.} } {Le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, nel qual -caso \var{errno} può assumere solo il valore \errcode{EPERM}. +caso \var{errno} assume i valori visti per \func{setuid}/\func{setgid}. } \end{funcproto} @@ -2135,7 +2137,7 @@ gli \ids{UID} si applica alla seconda per i \ids{GID}. La funzione \func{setresuid} imposta l'\ids{UID} reale, l'\ids{UID} effettivo e l'\ids{UID} salvato del processo corrente ai valori specificati rispettivamente dagli argomenti \param{ruid}, \param{euid} e \param{suid}. I -processi non privilegiati possono cambiare uno qualunque degli\ids{UID} solo +processi non privilegiati possono cambiare uno qualunque degli \ids{UID} solo ad un valore corrispondente o all'\ids{UID} reale, o a quello effettivo o a quello salvato, l'amministratore può specificare i valori che vuole. Un valore di $-1$ per un qualunque argomento lascia inalterato l'identificatore @@ -2201,9 +2203,10 @@ programmi portabili; i loro prototipi sono: \fdecl{int setfsgid(gid\_t fsgid)} \fdesc{Legge il \ids{GID} di filesystem del processo corrente.} } -{Le funzioni restituiscono il nuovo valore dell'identificativo in caso di - successo e quello corrente per un errore, in questo caso non viene però - impostato nessun codice di errore in \var{errno}.} + +{Le funzioni restituiscono sia in caso di successo che di errore il valore + corrente dell'identificativo, e in caso di errore non viene impostato nessun + codice in \var{errno}.} \end{funcproto} Le due funzioni sono analoghe ed usano il valore passato come argomento per @@ -2212,6 +2215,12 @@ solo se il processo chiamante ha i privilegi di amministratore o, per gli altri utenti, se il valore specificato coincide con uno dei di quelli del gruppo \textit{real}, \textit{effective} o \textit{saved}. +Il problema di queste funzioni è che non restituiscono un codice di errore e +non c'è modo di sapere (con una singola chiamata) di sapere se hanno avuto +successo o meno, per verificarlo occorre eseguire una chiamata aggiuntiva +passando come argomento $-1$ (un valore impossibile per un identificativo), +così fallendo si può di ottenere il valore corrente e verificare se è +cambiato. \subsection{Le funzioni per la gestione dei gruppi associati a un processo} \label{sec:proc_setgroups} @@ -2247,8 +2256,8 @@ La funzione legge gli identificatori dei gruppi supplementari del processo sul vettore \param{list} che deve essere di dimensione pari a \param{size}. Non è specificato se la funzione inserisca o meno nella lista il \ids{GID} effettivo del processo. Se si specifica un valore di \param{size} uguale a $0$ allora -l'argomento \param{list} non viene modificato, ma si ottiene il numero di -gruppi supplementari. +l'argomento \param{list} non viene modificato, ma si ottiene dal valore di +ritorno il numero di gruppi supplementari. Una seconda funzione, \funcd{getgrouplist}, può invece essere usata per ottenere tutti i gruppi a cui appartiene utente identificato per nome; il suo @@ -2389,7 +2398,7 @@ tempo. In tutti questi casi la CPU diventa disponibile ed è compito dello kernel provvedere a mettere in esecuzione un altro processo. Tutte queste possibilità sono caratterizzate da un diverso \textsl{stato} del -processo, in Linux un processo può trovarsi in uno degli stati riportati in +processo; in Linux un processo può trovarsi in uno degli stati riportati in tab.~\ref{tab:proc_proc_states}; ma soltanto i processi che sono nello stato \textit{runnable} concorrono per l'esecuzione. Questo vuol dire che, qualunque sia la sua priorità, un processo non potrà mai essere messo in esecuzione @@ -2404,7 +2413,7 @@ fintanto che esso si trova in uno qualunque degli altri stati. \hline \hline \textit{runnable}& \texttt{R} & Il processo è in esecuzione o è pronto ad - essere eseguito (cioè è in attesa che gli + essere eseguito (in attesa che gli venga assegnata la CPU).\\ \textit{sleep} & \texttt{S} & Il processo è in attesa di un risposta dal sistema, ma può essere @@ -2488,9 +2497,9 @@ prevede solo priorità dinamiche. È di questo che, di norma, ci si dovrà preoccupare nella programmazione. Come accennato in Linux i processi ordinari hanno tutti una priorità assoluta nulla; quello che determina quale, fra tutti i processi in attesa di esecuzione, sarà eseguito per primo, è la cosiddetta -\textsl{priorità dinamica},\footnote{quella che viene mostrata nella colonna - \texttt{PR} del comando \texttt{top}.} che è chiamata così proprio perché -varia nel corso dell'esecuzione di un processo. +\textsl{priorità dinamica}, quella che viene mostrata nella colonna +\texttt{PR} del comando \texttt{top}, che è chiamata così proprio perché varia +nel corso dell'esecuzione di un processo. Il meccanismo usato da Linux è in realtà piuttosto complesso,\footnote{e dipende strettamente dalla versione di kernel; in particolare a partire @@ -2510,18 +2519,19 @@ in stato \textit{runnable} ma non viene posto in esecuzione.\footnote{in processo mettere in esecuzione avviene con un algoritmo molto più complicato, che tiene conto anche della \textsl{interattività} del processo, utilizzando diversi fattori, questa è una brutale semplificazione per - rendere l'idea del funzionamento, per una trattazione più dettagliata, anche - se non aggiornatissima, dei meccanismi di funzionamento dello - \textit{scheduler} si legga il quarto capitolo di \cite{LinKernDev}.} Lo -\textit{scheduler} infatti mette sempre in esecuzione, fra tutti i processi in -stato \textit{runnable}, quello che ha il valore di priorità dinamica più -basso.\footnote{con le priorità dinamiche il significato del valore numerico - ad esse associato è infatti invertito, un valore più basso significa una - priorità maggiore.} Il fatto che questo valore venga diminuito quando un -processo non viene posto in esecuzione pur essendo pronto, significa che la -priorità dei processi che non ottengono l'uso del processore viene -progressivamente incrementata, così che anche questi alla fine hanno la -possibilità di essere eseguiti. + rendere l'idea del funzionamento, per una trattazione più dettagliata dei + meccanismi di funzionamento dello \textit{scheduler}, anche se non + aggiornatissima, si legga il quarto capitolo di \cite{LinKernDev}.} + +Lo \textit{scheduler} infatti mette sempre in esecuzione, fra tutti i processi +in stato \textit{runnable}, quello che ha il valore di priorità dinamica più +basso; con le priorità dinamiche il significato del valore numerico ad esse +associato è infatti invertito, un valore più basso significa una priorità +maggiore. Il fatto che questo valore venga diminuito quando un processo non +viene posto in esecuzione pur essendo pronto, significa che la priorità dei +processi che non ottengono l'uso del processore viene progressivamente +incrementata, così che anche questi alla fine hanno la possibilità di essere +eseguiti. Sia la dimensione della \textit{time-slice} che il valore di partenza della priorità dinamica sono determinate dalla cosiddetta \textit{nice} (o @@ -2620,19 +2630,18 @@ caso \var{errno} assumerà uno dei valori: \end{errlist}} \end{funcproto} -La funzione permette, a seconda di quanto specificato -nell'argomento \param{which}, di leggere il valore di \textit{nice} di un -processo, di un gruppo di processi (vedi sez.~\ref{sec:sess_proc_group}) o di -un utente indicato dall'argomento \param{who}. Nelle vecchie versioni può -essere necessario includere anche \headfiled{sys/time.h}, questo non è più -necessario con versioni recenti delle librerie, ma è comunque utile per -portabilità. +La funzione permette, a seconda di quanto specificato nell'argomento +\param{which}, di leggere il valore di \textit{nice} o di un processo, o di un +gruppo di processi (vedi sez.~\ref{sec:sess_proc_group}) o di un utente, +indicati con l'argomento \param{who}. Nelle vecchie versioni può essere +necessario includere anche \headfiled{sys/time.h}, questo non è più necessario +con versioni recenti delle librerie, ma è comunque utile per portabilità. I valori possibili per \param{which}, ed il tipo di valore che occorre usare -in corrispondenza per \param{who} solo elencati nella legenda di +in corrispondenza per \param{who}, solo elencati nella legenda di tab.~\ref{tab:proc_getpriority} insieme ai relativi significati. Usare un valore nullo per \param{who} indica, a seconda della corrispondente -indicazione usata per \param{which} il processo, il gruppo di processi o +indicazione usata per \param{which}, il processo, il gruppo di processi o l'utente correnti. \begin{table}[htb] @@ -2657,7 +2666,7 @@ l'utente correnti. In caso di una indicazione che faccia riferimento a più processi, la funzione restituisce la priorità più alta (cioè il valore più basso) fra quelle dei -processi corrispondenti. Come per \func{nice} $-1$ è un valore possibile +processi corrispondenti. Come per \func{nice}, $-1$ è un possibile valore corretto, per cui di nuovo per poter rilevare una condizione di errore è necessario cancellare sempre \var{errno} prima della chiamata alla funzione e quando si ottiene un valore di ritorno uguale a $-1$ per verificare che essa @@ -2692,9 +2701,9 @@ i quali valgono le stesse considerazioni fatte per \func{getpriority} e lo specchietto di tab.~\ref{tab:proc_getpriority}. In questo caso come valore di \param{prio} deve essere specificato il valore -di \textit{nice} da assegnare, e non un incremento (positivo o negativo) come -nel caso di \func{nice}, nell'intervallo fra \const{PRIO\_MIN} ($-20$) e -\const{PRIO\_MAX} ($19$). La funzione restituisce il valore di \textit{nice} +di \textit{nice} da assegnare nell'intervallo fra \const{PRIO\_MIN} ($-20$) e +\const{PRIO\_MAX} ($19$), e non un incremento (positivo o negativo) come nel +caso di \func{nice}. La funzione restituisce il valore di \textit{nice} assegnato in caso di successo e $-1$ in caso di errore, e come per \func{nice} anche in questo caso per rilevare un errore occorre sempre porre a zero \var{errno} prima della chiamata della funzione, essendo $-1$ un valore di @@ -2726,33 +2735,33 @@ valore di \textit{nice} è cambiato parecchio nelle progressive riscritture dello \textit{scheduler} di Linux, ed in particolare a partire dal kernel 2.6.23 l'uso di diversi valori di \textit{nice} ha un impatto molto più forte nella distribuzione della CPU ai processi. Infatti se viene comunque calcolata -una priorità dinamica per i processi che non ricevono la CPU così che anche +una priorità dinamica per i processi che non ricevono la CPU, così che anche essi possano essere messi in esecuzione, un alto valore di \textit{nice} corrisponde comunque ad una \textit{time-slice} molto piccola che non cresce comunque, per cui un processo a bassa priorità avrà davvero scarse possibilità di essere eseguito in presenza di processi attivi a priorità più alta. - \subsection{Il meccanismo di \textit{scheduling real-time}} \label{sec:proc_real_time} Come spiegato in sez.~\ref{sec:proc_sched} lo standard POSIX.1b ha introdotto -le priorità assolute per permettere la gestione di processi real-time. In -realtà nel caso di Linux non si tratta di un vero \textit{hard real-time}, in -quanto in presenza di eventuali interrupt il kernel interrompe l'esecuzione di -un processo qualsiasi sia la sua priorità,\footnote{questo a meno che non si - siano installate le patch di RTLinux, RTAI o Adeos, con i quali è possibile - ottenere un sistema effettivamente \textit{hard real-time}. In tal caso - infatti gli interrupt vengono intercettati dall'interfaccia - \textit{real-time} (o nel caso di Adeos gestiti dalle code del nano-kernel), - in modo da poterli controllare direttamente qualora ci sia la necessità di - avere un processo con priorità più elevata di un \textit{interrupt - handler}.} mentre con l'incorrere in un \textit{page fault} si possono -avere ritardi non previsti. Se l'ultimo problema può essere aggirato -attraverso l'uso delle funzioni di controllo della memoria virtuale (vedi -sez.~\ref{sec:proc_mem_lock}), il primo non è superabile e può comportare -ritardi non prevedibili riguardo ai tempi di esecuzione di qualunque processo. +le priorità assolute per permettere la gestione di processi +\textit{real-time}. In realtà nel caso di Linux non si tratta di un vero +\textit{hard real-time}, in quanto in presenza di eventuali interrupt il +kernel interrompe l'esecuzione di un processo, qualsiasi sia la sua +priorità,\footnote{questo a meno che non si siano installate le patch di + RTLinux, RTAI o Adeos, con i quali è possibile ottenere un sistema + effettivamente \textit{hard real-time}. In tal caso infatti gli interrupt + vengono intercettati dall'interfaccia \textit{real-time} (o nel caso di + Adeos gestiti dalle code del nano-kernel), in modo da poterli controllare + direttamente qualora ci sia la necessità di avere un processo con priorità + più elevata di un \textit{interrupt handler}.} mentre con l'incorrere in un +\textit{page fault} si possono avere ritardi non previsti. Se l'ultimo +problema può essere aggirato attraverso l'uso delle funzioni di controllo +della memoria virtuale (vedi sez.~\ref{sec:proc_mem_lock}), il primo non è +superabile e può comportare ritardi non prevedibili riguardo ai tempi di +esecuzione di qualunque processo. Nonostante questo, ed in particolare con una serie di miglioramenti che sono stati introdotti nello sviluppo del kernel,\footnote{in particolare a partire @@ -2815,15 +2824,15 @@ ordinarie o viceversa, che di specificare, in caso di politiche caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EINVAL}] il valore di \param{policy} non esiste o il - relativo valore di \param{p} non è valido per la politica scelta. + valore di \param{p} non è valido per la politica scelta. \item[\errcode{EPERM}] il processo non ha i privilegi per attivare la politica richiesta. \item[\errcode{ESRCH}] il processo \param{pid} non esiste. - \end{errlist}} + \end{errlist}} \end{funcproto} La funzione esegue l'impostazione per il processo specificato dall'argomento -\param{pid}, un valore nullo di questo argomento esegue l'impostazione per il +\param{pid}; un valore nullo di questo argomento esegue l'impostazione per il processo corrente. La politica di \textit{scheduling} è specificata dall'argomento \param{policy} i cui possibili valori sono riportati in tab.~\ref{tab:proc_sched_policy}; la parte alta della tabella indica le @@ -2860,6 +2869,7 @@ corrente. % TODO Aggiungere SCHED_DEADLINE, sulla nuova politica di scheduling aggiunta % con il kernel 3.14, vedi anche Documentation/scheduler/sched-deadline.txt e % http://lwn.net/Articles/575497/ +% vedi anche man 7 sched, man sched_setattr Con le versioni più recenti del kernel sono state introdotte anche delle varianti sulla politica di \textit{scheduling} tradizionale per alcuni carichi @@ -2874,9 +2884,9 @@ di \textit{sleep}.\footnote{cosa che accade con grande frequenza per i processi interattivi, dato che essi sono per la maggior parte del tempo in attesa di dati in ingresso da parte dell'utente.} La si usa pertanto, come indica il nome, per processi che usano molta CPU (come programmi di calcolo) -che in questo modo sono leggermente sfavoriti rispetto ai processi interattivi -che devono rispondere a dei dati in ingresso, pur non perdendo il loro valore -di \textit{nice}. +che in questo modo, pur non perdendo il loro valore di \textit{nice}, sono +leggermente sfavoriti rispetto ai processi interattivi che devono rispondere a +dei dati in ingresso. La politica \const{SCHED\_IDLE} invece è una politica dedicata ai processi che si desidera siano eseguiti con la più bassa priorità possibile, ancora più @@ -2895,7 +2905,7 @@ standard prevede che questo debba essere assegnato all'interno di un intervallo fra un massimo ed un minimo che nel caso di Linux sono rispettivamente 1 e 99. -\begin{figure}[!htbp] +\begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{0.5\textwidth} \includestruct{listati/sched_param.c} @@ -2930,9 +2940,9 @@ prototipi sono: \end{errlist}} \end{funcproto} -Le funzioni ritornano rispettivamente i due valori della massima e minima -priorità statica possano essere ottenuti per una delle politiche di -\textit{scheduling} \textit{real-time} indicata dall'argomento \param{policy}. +Le funzioni ritornano rispettivamente il valore massimo e minimo usabile per +la priorità statica di una delle politiche di \textit{scheduling} +\textit{real-time} indicata dall'argomento \param{policy}. Si tenga presente che quando si imposta una politica di \textit{scheduling} real-time per un processo o se ne cambia la priorità statica questo viene @@ -2947,8 +2957,8 @@ politica scelta è \const{SCHED\_FIFO} quando il processo viene eseguito viene automaticamente rimesso in coda alla lista, e la sua esecuzione continua fintanto che non viene bloccato da una richiesta di I/O, o non rilascia volontariamente la CPU (in tal caso, tornando nello stato \textit{runnable} -sarà reinserito in coda alla lista); l'esecuzione viene ripresa subito solo -nel caso che esso sia stato interrotto da un processo a priorità più alta. +sarà in coda alla lista); l'esecuzione viene ripresa subito solo nel caso che +esso sia stato interrotto da un processo a priorità più alta. Solo un processo con i privilegi di amministratore\footnote{più precisamente con la capacità \const{CAP\_SYS\_NICE}, vedi @@ -3102,7 +3112,7 @@ comportava che i processi venissero messi in fondo alla coda di quelli attivi, con la possibilità di essere rimessi in esecuzione entro breve tempo, con l'introduzione del \textit{Completely Fair Scheduler} questo comportamento è cambiato ed un processo che chiama la funzione viene inserito nella lista dei -processi inattivo, con un tempo molto maggiore.\footnote{è comunque possibile +processi inattivi, con un tempo molto maggiore.\footnote{è comunque possibile ripristinare un comportamento analogo al precedente scrivendo il valore 1 nel file \sysctlfiled{kernel/sched\_compat\_yield}.} @@ -3222,13 +3232,13 @@ questa viene ereditata attraverso una \func{fork}, in questo modo diventa possibile legare automaticamente un gruppo di processi ad un singolo processore. -Nell'uso comune, almeno con i kernel successivi alla serie 2.6.x, l'uso di +Nell'uso comune, almeno con i kernel successivi alla serie 2.6.x, utilizzare questa funzione non è necessario, in quanto è lo \textit{scheduler} stesso che provvede a mantenere al meglio l'affinità di processore. Esistono però esigenze particolari, ad esempio quando un processo (o un gruppo di processi) è utilizzato per un compito importante (ad esempio per applicazioni \textit{real-time} o la cui risposta è critica) e si vuole la massima -velocità, e con questa interfaccia diventa possibile selezionare gruppi di +velocità; con questa interfaccia diventa possibile selezionare gruppi di processori utilizzabili in maniera esclusiva. Lo stesso dicasi quando l'accesso a certe risorse (memoria o periferiche) può avere un costo diverso a seconda del processore, come avviene nelle architetture NUMA @@ -3255,10 +3265,10 @@ cui ogni bit corrisponde ad un processore, ma oggi esistono architetture in cui questo numero può non essere sufficiente, e per questo è stato creato questo tipo opaco e una interfaccia di gestione che permette di usare a basso livello un tipo di dato qualunque rendendosi indipendenti dal numero di bit e -dalla loro disposizione. Per questo le funzioni richiedono anche che oltre -all'insieme di processori si indichi anche la dimensione dello stesso con -l'argomento \param{setsize}, per il quale, se non si usa l'allocazione -dinamica che vedremo a breve, ed è in genere sufficiente passare il valore +dalla loro disposizione. Per questo le funzioni di libreria richiedono che +oltre all'insieme di processori si indichi anche la dimensione dello stesso +con l'argomento \param{setsize}, per il quale, se non si usa l'allocazione +dinamica che vedremo a breve, è in genere sufficiente passare il valore \code{sizeof(cpu\_set\_t)}. L'interfaccia di gestione degli insiemi di processori, oltre alla definizione @@ -3297,7 +3307,7 @@ presente, diverso da zero se è presente). Si tenga presente che trattandosi di macro l'argomento \param{cpu} può essere valutato più volte. Questo significa ad esempio che non si può usare al suo posto una funzione o un'altra macro, altrimenti queste verrebbero eseguite più -volte, l'argomento cioè non deve avere \textsl{effetti collaterali} (in gergo +volte; l'argomento cioè non deve avere \textsl{effetti collaterali} (in gergo \textit{side effects}).\footnote{nel linguaggio C si parla appunto di \textit{side effects} quando si usano istruzioni la cui valutazione comporta effetti al di fuori dell'istruzione stessa, come il @@ -3308,13 +3318,13 @@ volte, l'argomento cioè non deve avere \textsl{effetti collaterali} (in gergo \itindend{side~effects} -Le CPU sono numerate da zero (che indica la prima disponibile) fino ad -un numero massimo che dipende dalla architettura hardware. La costante +Le CPU sono numerate da zero (che indica la prima disponibile) fino ad un +numero massimo che dipende dall'architettura hardware. La costante \constd{CPU\_SETSIZE} indica il numero massimo di processori che possono far parte di un insieme (al momento vale sempre 1024), e costituisce un limite -massimo al valore dell'argomento \param{cpu}. -Dalla versione 2.6 della \acr{glibc} alle precedenti macro è stata aggiunta, -per contare il numero di processori in un insieme, l'ulteriore: +massimo al valore dell'argomento \param{cpu}. Dalla versione 2.6 della +\acr{glibc} alle precedenti macro è stata aggiunta, per contare il numero di +processori in un insieme, l'ulteriore: {\centering \vspace{3pt}