X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=system.tex;h=8b117142910ddc8788ecc267081272fbd9fcd01a;hp=38a7abcce10b0ec20e3319552cb7285321a2c75c;hb=b08cbbc5abd1579c0a94d357d5ded1fe902044a0;hpb=9ed5353304ae9ef478fce673c5e0dbe873ee2ba8 diff --git a/system.tex b/system.tex index 38a7abc..8b11714 100644 --- a/system.tex +++ b/system.tex @@ -1,4 +1,4 @@ -fo \chapter{La gestione del sistema, delle risorse, e degli errori} +\chapter{La gestione del sistema, delle risorse, e degli errori} \label{cha:system} In questo capitolo tratteremo varie interfacce che attengono agli aspetti più @@ -324,8 +324,8 @@ relative spiegazioni, si pu \texttt{\_SC\_SSIZE\_MAX}&\macro{SSIZE\_MAX}& valore massimo del tipo di dato \type{ssize\_t}.\\ \texttt{\_SC\_CLK\_TCK}& \macro{CLK\_TCK} & - Il numero di \textit{clock tick} al secondo, cioè la frequenza delle - interruzioni del timer di sistema (vedi \secref{sec:proc_priority}).\\ + Il numero di \textit{clock tick} al secondo, cioè l'unità di misura del + \textit{process time} (vedi \secref{sec:sys_unix_time}).\\ \texttt{\_SC\_JOB\_CONTROL}&\macro{\_POSIX\_JOB\_CONTROL}& Indica se è supportato il \textit{job control} (vedi \secref{sec:sess_xxx}) in stile POSIX.\\ @@ -882,18 +882,18 @@ nome del filesystem stesso. \footnotesize \centering \begin{minipage}[c]{15cm} \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{} - struct statfs { - long f_type; /* tipo di filesystem */ - long f_bsize; /* dimensione ottimale dei blocchi di I/O */ - long f_blocks; /* blocchi totali nel filesystem */ - long f_bfree; /* blocchi liberi nel filesystem */ - long f_bavail; /* blocchi liberi agli utenti normali */ - long f_files; /* inodes totali nel filesystem */ - long f_ffree; /* inodes liberi nel filesystem */ - fsid_t f_fsid; /* filesystem id */ - long f_namelen; /* lunghezza massima dei nomi dei file */ - long f_spare[6]; /* riservati per uso futuro */ - }; +struct statfs { + long f_type; /* tipo di filesystem */ + long f_bsize; /* dimensione ottimale dei blocchi di I/O */ + long f_blocks; /* blocchi totali nel filesystem */ + long f_bfree; /* blocchi liberi nel filesystem */ + long f_bavail; /* blocchi liberi agli utenti normali */ + long f_files; /* inodes totali nel filesystem */ + long f_ffree; /* inodes liberi nel filesystem */ + fsid_t f_fsid; /* filesystem id */ + long f_namelen; /* lunghezza massima dei nomi dei file */ + long f_spare[6]; /* riservati per uso futuro */ +}; \end{lstlisting} \end{minipage} \normalsize @@ -1455,10 +1455,10 @@ corrente e massimo. \centering \begin{minipage}[c]{15cm} \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{} - struct rlimit { - rlim_t rlim_cur; - rlim_t rlim_max; - }; +struct rlimit { + rlim_t rlim_cur; + rlim_t rlim_max; +}; \end{lstlisting} \end{minipage} \normalsize @@ -1467,10 +1467,11 @@ corrente e massimo. \label{fig:sys_rlimit_struct} \end{figure} - -Per far leggere o settare i limiti sdi utilizzo delle risorse da parte di un -processo le \acr{glibc} prevedono due funzioni, \func{getrlimit} e -\func{setrlimit}, i cui prototipi sono: +In genere il superamento di un limite comporta o l'emissione di un segnale o +il fallimento della system call che lo ha provocato; per far leggere o settare +i limiti di utilizzo delle risorse da parte di un processo le \acr{glibc} +prevedono due funzioni, \func{getrlimit} e \func{setrlimit}, i cui prototipi +sono: \begin{functions} \headdecl{sys/time.h} \headdecl{sys/resource.h} @@ -1502,21 +1503,47 @@ specificarne i valori. \begin{table}[htb] \footnotesize \centering - \begin{tabular}[c]{|l|p{8cm}|} + \begin{tabular}[c]{|l|p{12cm}|} \hline \textbf{Valore} & \textbf{Significato}\\ \hline \hline - \macro{RLIMIT\_CPU} & \\ - \macro{RLIMIT\_FSIZE} & \\ - \macro{RLIMIT\_DATA} & \\ - \macro{RLIMIT\_STACK} & \\ - \macro{RLIMIT\_CORE} & \\ - \macro{RLIMIT\_RSS} & \\ - \macro{RLIMIT\_NPROC} & \\ - \macro{RLIMIT\_NOFILE} & \\ - \macro{RLIMIT\_MEMLOCK}& \\ - \macro{RLIMIT\_AS} & \\ + \macro{RLIMIT\_CPU} & Il massimo tempo di CPU che il processo può + usare. Il superamento del limite comporta + l'emissione di un segnale di \macro{SIGXCPU}.\\ + \macro{RLIMIT\_FSIZE} & La massima dimensione di un file che un processo + può usare. Se il processo cerca di scrivere + oltre questa dimensione riceverà un segnale di + \macro{SIGXFSZ}.\\ + \macro{RLIMIT\_DATA} & La massima dimensione della memoria dati di un + processo. Il tentatico di allocare più memoria + causa il fallimento della funzione di + allocazione. \\ + \macro{RLIMIT\_STACK} & La massima dimensione dello stack del + processo. Se il processo esegue operazioni che + estendano lo stack oltre questa dimensione + riceverà un segnale di \macro{SIGSEGV}.\\ + \macro{RLIMIT\_CORE} & La massima dimensione di un file di \textit{core + dump} creato da un processo. Nel caso le + dimensioni dovessero essere maggiori il file non + verrebbe generato.\footnotemark\\ + \macro{RLIMIT\_RSS} & L'ammontare massimo di memoria fisica dato al + processo. Il limite è solo una indicazione per + il kernel, qualora ci fosse un surplus di + memoria questa verrebbe assegnata.\\ + \macro{RLIMIT\_NPROC} & Il numero massimo di processi che possono essere + creati sullo stesso user id. Se il limite viene + raggiunto \func{fork} fallirà con un + \macro{EAGAIN}.\\ + \macro{RLIMIT\_NOFILE} & Il numero massimo di file che il processo può + aprire. L'apertura di un ulteriore file fallirà + con un errore \macro{EMFILE}.\\ + \macro{RLIMIT\_MEMLOCK}& L'ammontare massimo di memoria che può essere + bloccata (vedi \secref{sec:proc_mem_lock}).\\ + \macro{RLIMIT\_AS} & La dimensione massima di tutta la memoria che il + processo può ottenere. Se il processo tenta di + allocarne di più funzioni come \func{brk}, + \func{malloc} o \func{mmap} falliranno. \\ \hline \end{tabular} \caption{Valori possibili dell'argomento \param{resource} delle funzioni @@ -1524,37 +1551,116 @@ specificarne i valori. \label{tab:sys_rlimit_values} \end{table} +\footnotetext{Settare questo limite a zero è la maniera più semplice per + evitare la creazione di \file{core} file.} + È inoltre definita la costante \macro{RLIM\_INFINITY} che permette di sbloccare l'uso di una risorsa, ma solo un processo con i privilegi di amministratore può innalzare un limite al di sopra del valore corrente del -limite massimo. I limiti vengono ereditati dal processo padre attraverso una -\func{fork} (vedi \secref{sec:proc_fork}) e mantenuti attraverso una -\func{exec}. - +limite massimo. Si tenga conto infine che tutti i limiti vengono ereditati dal +processo padre attraverso una \func{fork} (vedi \secref{sec:proc_fork}) e +mantenuti attraverso una \func{exec} (vedi \secref{sec:proc_exec}). - -\subsection{Le risorse di memoria} +\subsection{Le risorse di memoria e processore} \label{sec:sys_memory_res} +La gestione della memoria è già stata affrontata in dettaglio in +\secref{sec:proc_memory}; abbiamo visto allora che il kernel provvede il +meccanismo della memoria virtuale attraverso la divisione della memoria fisica +in pagine. + +In genere questo è del tutto trasparente al singolo processo, ma in certi +casi, come per l'I/O mappato in memoria (vedi \ref{sec:file_memory_map}) che +usa lo stesso meccanismo per accedere ai file, è necessario conoscere le +dimensioni delle pagine usate dal kernel. Lo stesso vale quando si vuole +gestire in maniera ottimale l'interazione della memoria allocata con il +meccanismo della paginazione. + +Di solito la dimensione delle pagine di memoria è fissata dall'architettura +hardware, per cui in genere la dimensione delle pagine di memoria era una +costante definita in fase di compilazione, ma oggi alcune architetture (ad +esempio su Sun Sparc) permettono di variare questa dimensione, e non volendo +dover fornire binari diversi per ogni possibile modello, è necessario poter +utilizzare una funzione. + +In genere questa dimensione può essere ottenuta attraverso una chiamata a +\func{sysconf} come \func{sysconf(\_SC\_PAGESIZE)}, ma in BSD 4.2 è stata +introdotta una apposita funzione, \func{getpagesize}, che restituisce la +dimensione delle pagine di memoria; il suo prototipo è: +\begin{prototype}{unistd.h}{int getpagesize(void)} + Legge le dimensioni delle pagine di memoria. + + \bodydesc{La funzione ritorna la dimensione di una pagina in byte, e non + sono previsti errori.} +\end{prototype} -\subsection{Le risorse di processore} -\label{sec:sys_cpu_load} - - +La funzione è prevista in SVr4, 4.4BSD e SUSv2, anche se questo ultimo +standard la etichetta come obsoleta, mentre lo standard POSIX 1003.1-2001 la +ha eliminata. In Linux è implementata come una system call nelle architetture +in cui essa è necessaria, ed in genere restituisce il valore del simbolo +\macro{PAGE\_SIZE} del kernel, anche se le versioni delle librerie del C +precedenti le \acr{glibc} 2.1 implementavano questa funzione restituendo +sempre un valore statico. + +Le \acr{glibc} forniscono, come specifica estensione GNU, altre due funzioni, +\func{get\_phys\_pages} e \func{get\_avphys\_pages} che permettono di ottenere +informazioni riguardo la memoria; i loro prototipi sono: +\begin{functions} + \headdecl{sys/sysinfo.h} + + \funcdecl{long int get\_phys\_pages(void)} + Legge il numero totale di pagine di memoria disponibili per il sistema. + + \funcdecl{long int get\_avphys\_pages(void)} + + Legge il numero di pagine di memoria disponibili nel sistema. + + \bodydesc{Le funzioni restituiscono un numero di pagine.} +\end{functions} +Queste funzioni sono equivalenti all'uso della funzione \func{sysconf} +rispettivamente con i parametri \macro{\_SC\_PHYS\_PAGES} e +\macro{\_SC\_AVPHYS\_PAGES}. La prima restituisce il numero totale di pagine +corrispondenti alla RAM della macchina; la seconda invece la memoria +effettivamente disponibile per i processi. + +Le \acr{glibc} supportano inoltre, come estenzioni GNU, due funzioni che +restituiscono il numero di processori della macchina (e quello dei processori +attivi); anche queste sono informazioni comunque ottenibili attraverso +\func{sysconf} utilizzando rispettivamente i parametri +\macro{\_SC\_NPROCESSORS\_CONF} e \macro{\_SC\_NPROCESSORS\_ONLN}. + +Infine le \acr{glibc} riprendono da BSD la funzione \func{getloadavg} che +permette di ottenere il carico di processore della macchina, in questo modo è +possibile prendere decisioni su quando far partire eventuali nuovi processi. +Il suo prototipo è: +\begin{prototype}{stdlib.h}{int getloadavg(double loadavg[], int nelem)} + Legge il carico medio della macchina. + + \bodydesc{La funzione ritorna il numero di elementi scritti o -1 in caso di + errore.} +\end{prototype} -\var{tms\_utime}, \var{tms\_stime}, \var{tms\_cutime}, \var{tms\_uetime} +La funzione restituisce in ciascun elemento di \param{loadavg} il numero medio +di processi attivi sulla coda dello scheduler, calcolato su un diverso +intervalli di tempo. Il numero di intervalli che si vogliono leggere è +specificato da \param{nelem}, dato che nel caso di Linux il carico viene +valutato solo su tre intervalli (corrispondenti a 1, 5 e 15 minuti), questo è +anche il massimo valore che può essere assegnato a questo argomento. \section{La gestione dei tempi del sistema} \label{sec:sys_time} -In questa sezione tratteremo le varie funzioni per la gestione delle -date e del tempo in un sistema unix-like, e quelle per convertire i vari -tempi nelle differenti rappresentazioni che vengono utilizzate. +In questa sezione, una volta introdotti i concetti base della gestione dei +tempi da parte del sistema, tratteremo le varie funzioni attinenti alla +gestione del tempo in un sistema unix-like, a partire da quelle per misurare i +veri tempi di sistema associati ai processi, a quelle per convertire i vari +tempi nelle differenti rappresentazioni che vengono utilizzate, a quelle della +gestione di data e ora. \subsection{La misura del tempo in Unix} @@ -1564,26 +1670,30 @@ Storicamente i sistemi unix-like hanno sempre mantenuto due distinti tipi di dati per la misure dei tempi all'interno del sistema: essi sono rispettivamente chiamati \textit{calendar time} e \textit{process time}, secondo le definizioni: -\begin{itemize} -\item \textit{calendar time}: è il numero di secondi dalla mezzanotte del - primo gennaio 1970, in tempo universale coordinato (o UTC), data che viene - usualmente indicata con 00:00:00 Jan, 1 1970 (UTC) e chiamata \textit{the - Epoch}. Questo tempo viene anche chiamato anche GMT (Greenwich Mean Time) - dato che l'UTC corrisponde all'ora locale di Greenwich. È il tempo su cui - viene mantenuto l'orologio del calcolatore, e viene usato ad esempio per - indicare le date di modifica dei file o quelle di avvio dei processi. Per - memorizzare questo tempo è stato riservato il tipo primitivo \type{time\_t}. -\item \textit{process time}: detto anche tempo di processore. Viene misurato - in \textit{clock tick}, corrispondenti al numero di interruzioni effettuate - dal timer di sistema, e che per Linux avvengono ogni centesimo di - secondo.\footnote{eccetto per la piattaforma alpha dove avvengono ogni - millesimo di secondo.} Il dato primitivo usato per questo tempo è - \type{clock\_t}, inoltre la costante \macro{HZ} restituisce la frequenza di - operazione del timer, e corrisponde dunque al numero di tick al secondo. Lo - standard POSIX definisce allo stesso modo la costante \macro{CLK\_TCK}); - questo valore può comunque essere ottenuto con \func{sysconf} (vedi - \secref{sec:sys_limits}). -\end{itemize} +\begin{description} +\item[\textit{calendar time}]: detto anche \textsl{tempo di calendario}. È il + numero di secondi dalla mezzanotte del primo gennaio 1970, in tempo + universale coordinato (o UTC), data che viene usualmente indicata con + 00:00:00 Jan, 1 1970 (UTC) e chiamata \textit{the Epoch}. Questo tempo viene + anche chiamato anche GMT (Greenwich Mean Time) dato che l'UTC corrisponde + all'ora locale di Greenwich. È il tempo su cui viene mantenuto l'orologio + del kernel, e viene usato ad esempio per indicare le date di modifica dei + file o quelle di avvio dei processi. Per memorizzare questo tempo è stato + riservato il tipo primitivo \type{time\_t}. +\item[\textit{process time}]: detto talvolta \textsl{tempo di processore}. + Viene misurato in \textit{clock tick}. Un tempo questo corrispondeva al + numero di interruzioni effettuate dal timer di sistema, adesso lo standard + POSIX richiede che esso sia pari al valore della costante + \macro{CLOCKS\_PER\_SEC}, che deve essere definita come 1000000, qualunque + sia la risoluzione reale dell'orologio di sistema e la frequenza delle + interruzioni del timer.\footnote{quest'ultima, come accennato in + \secref{sec:proc_hierarchy}, è invece data dalla costante \macro{HZ}.} Il + dato primitivo usato per questo tempo è \type{clock\_t}, che ha quindi una + risoluzione del microsecondo. Il numero di tick al secondo può essere + ricavato anche attraverso \func{sysconf} (vedi \secref{sec:sys_sysconf}). Il + vecchio simbolo \macro{CLK\_TCK} definito in \file{time.h} è ormai + considerato obsoleto. +\end{description} In genere si usa il \textit{calendar time} per esprimere le date dei file e le informazioni analoghe che riguardano i cosiddetti \textsl{tempi di orologio}, @@ -1596,10 +1706,11 @@ tempo locale, utilizzando le opportune informazioni di localizzazione mantenuto dal sistema e non è detto che corrisponda al tempo tenuto dall'orologio hardware del calcolatore. -Anche il \textit{process time} di solito si esprime in secondi, ma provvede una -precisione ovviamente superiore al \textit{calendar time} (la cui granularità -minima è il secondo) e viene usato per tenere conto dei tempi di esecuzione -dei processi. Per ciascun processo il kernel calcola tre tempi diversi: +Anche il \textit{process time} di solito si esprime in secondi, ma provvede +una precisione ovviamente superiore al \textit{calendar time} (che è mantenuto +dal sistema con una granularità di un secondo) e viene usato per tenere conto +dei tempi di esecuzione dei processi. Per ciascun processo il kernel calcola +tre tempi diversi: \begin{description*} \item[\textit{clock time}]: il tempo \textsl{reale} (viene chiamato anche \textit{wall clock time}) passato dall'avvio del processo. Chiaramente tale @@ -1613,8 +1724,335 @@ dei processi. Per ciascun processo il kernel calcola tre tempi diversi: In genere la somma di \textit{user time} e \textit{system time} indica il tempo di processore totale in cui il sistema è stato effettivamente impegnato -nell'eseguire un certo processo e viene chiamato \textit{CPU time}. +nell'eseguire un certo processo e viene chiamato \textit{CPU time} o +\textsl{tempo di CPU}. + + + +\subsection{La gestione del \textit{process time}} +\label{sec:sys_cpu_times} + +Di norma tutte le operazioni del sistema fanno sempre riferimento al +\textit{calendar time}, l'uso del \textit{process time} è riservato a quei +casi in cui serve conoscere i tempi di esecuzione di un processo (ad esempio +per valutarne l'efficienza). In tal caso infatti fare ricorso al +\textit{calendar time} è inutile in quanto il tempo può essere trascorso mentre +un altro processo era in esecuzione o in attesa del risultato di una +operazione di I/O. + +La funzione più semplice per leggere il \textit{process time} di un processo è +\func{clock}, che da una valutazione approssimativa del tempo di CPU +utilizzato dallo stesso; il suo prototipo è: +\begin{prototype}{time.h}{clock\_t clock(void)} + Legge il valore corrente del tempo di CPU. + + \bodydesc{La funzione ritorna il tempo di CPU usato dal programma e -1 in + caso di errore.} +\end{prototype} + +La funzione restituisce il tempo in tick, quindi se si vuole il tempo in +secondi occorre moltiplicare il risultato per la costante +\macro{CLOCKS\_PER\_SEC}.\footnote{le \acr{glibc} seguono lo standard ANSI C, + POSIX richiede che \macro{CLOCKS\_PER\_SEC} sia definito pari a 1000000 + indipendetemente dalla risoluzione del timer di sistema.} In genere +\type{clock\_t} viene rappresentato come intero a 32 bit, il che comporta un +valore massimo corrispondente a circa 72 minuti, dopo i quali il contatore +riprenderà lo stesso valore iniziale. + +Come accennato in \secref{sec:sys_unix_time} il tempo di CPU è la somma di +altri due tempi, l'\textit{user time} ed il \textit{system time} che sono +quelli effettivamente mantenuti dal kernel per ciascun processo. Questi +possono essere letti attraverso la funzione \func{times}, il cui prototipo è: +\begin{prototype}{sys/times.h}{clock\_t times(struct tms *buf)} + Legge in \param{buf} il valore corrente dei tempi di processore. + + \bodydesc{La funzione ritorna il numero di clock tick dall'avvio del sistema + in caso di successo e -1 in caso di errore.} +\end{prototype} + +La funzione restituisce i valori di process time del processo corrente in una +struttura di tipo \var{tms}, la cui definizione è riportata in +\secref{fig:sys_tms_struct}. La struttura prevede quattro campi; i primi due, +\var{tms\_utime} e \var{tms\_stime}, sono l'\textit{user time} ed il +\textit{system time} del processo, così come definiti in +\secref{sec:sys_unix_time}. + +\begin{figure}[!htb] + \footnotesize + \centering + \begin{minipage}[c]{15cm} + \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{} +struct tms { + clock_t tms_utime; /* user time */ + clock_t tms_stime; /* system time */ + clock_t tms_cutime; /* user time of children */ + clock_t tms_cstime; /* system time of children */ +}; + \end{lstlisting} + \end{minipage} + \normalsize + \caption{La struttura \var{tms} dei tempi di processore associati a un + processo.} + \label{fig:sys_tms_struct} +\end{figure} + +Gli altri due campi mantengono rispettivamente la somma dell'\textit{user + time} ed del \textit{system time} di tutti i processi figli che sono +terminati; il kernel cioè somma in \var{tms\_cutime} il valore di +\var{tms\_utime} e \var{tms\_cutime} per ciascun figlio del quale è stato +ricevuto lo stato di terminazione, e lo stesso vale per \var{tms\_cstime}. + +Si tenga conto che l'aggiornamento di \var{tms\_cutime} e \var{tms\_cstime} +viene eseguito solo quando una chiamata a \func{wait} o \func{waitpid} è +ritornata. Per questo motivo se un processo figlio termina prima di ricevere +lo stato di teminazione di tutti i suoi figli, questi processi ``nipoti'' non +verranno considerati nel calcolo di questi tempi. + + + +\subsection{Le funzioni per il \textit{calendar time}} +\label{sec:sys_time_base} + +Come anticipato in \secref{sec:sys_unix_time} il \textit{calendar time} è +mantenuto dal kernel in una variabile di tipo \type{time\_t}, che usualmente +corrisponde ad un tipo nativo (in Linux è un intero a 32 bit). Il valore +corrente del \textit{calendar time}, che indicheremo come \textsl{tempo di + sistema}, può essere ottenuto con la funzione \func{time} che lo restituisce +in nel suddetto formato; il suo prototipo è: +\begin{prototype}{time.h}{time\_t time(time\_t *t)} + Legge il valore corrente del \textit{calendar time}. + + \bodydesc{La funzione ritorna il valore del \textit{calendar time} in caso + di successo e -1 in caso di errore, che può essere solo \macro{EFAULT}.} +\end{prototype} +\noindent dove \param{t}, se non nullo, deve essere l'indirizzo di una +variabile su cui duplicare il valore di ritorno. + +Analoga a \func{time} è la funzione \func{stime} che serve per effettuare +l'operazione inversa, e cioè per settare il tempo di sistema qualora questo +sia necessario; il suo prototipo è: +\begin{prototype}{time.h}{int stime(time\_t *t)} + Setta a \param{t} il valore corrente del \textit{calendar time}. + + \bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore, + che può essere \macro{EFAULT} o \macro{EPERM}.} +\end{prototype} +\noindent dato che modificare l'ora ha un impatto su tutto il sistema +il cambiamento dell'orologio è una operazione privilegiata e questa funzione +può essere usata solo da un processo con i privilegi di amministratore, +altrimenti la chiamata fallirà con un errore di \macro{EPERM}. + +Data la scarsa precisione nell'uso di \type{time\_t} (che ha una risoluzione +massima di un secondo) quando si devono effettuare operazioni sui tempi di +norma l'uso delle funzioni precedenti è sconsigliato, ed esse sono di solito +sostituite da \func{gettimeofday} e \func{settimeofday},\footnote{le due + funzioni \func{time} e \func{stime} sono più antiche e derivano da SVr4, + \func{gettimeofday} e \func{settimeofday} sono state introdotte da BSD, ed + in BSD4.3 sono indicate come sostitute delle precedenti.} mentre i cui +prototipi sono: +\begin{functions} + \headdecl{sys/time.h} + \headdecl{time.h} + + \funcdecl{int gettimeofday(struct timeval *tv, struct timezone *tz)} + + Legge il tempo corrente del sistema. + + \funcdecl{int settimeofday(const struct timeval *tv, const struct timezone + *tz)} + + Setta il tempo di sistema. + + \bodydesc{Entrambe le funzioni restituiscono 0 in caso di successo e -1 in + caso di errore, nel qual caso \var{errno} può assumere il valori + \macro{EINVAL} \macro{EFAULT} e per \func{settimeofday} anche + \macro{EPERM}.} +\end{functions} + +Queste funzioni utilizzano una struttura di tipo \var{timeval}, la cui +definizione, insieme a quella della analoga \var{timespec}, è riportata in +\figref{fig:sys_timeval_struct}. Le \acr{glibc} infatti provvedono queste due +rappresentazioni alternative del \textit{calendar time} che rispetto a +\type{time\_t} consentono rispettivamente precisioni del microsecondo e del +nanosecondo.\footnote{la precisione è solo teorica, la precisione reale della + misura del tempo dell'orologio di sistema non dipende dall'uso di queste + strutture.} + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{} +struct timeval +{ + long tv_sec; /* seconds */ + long tv_usec; /* microseconds */ +}; +struct timespec { + time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +}; + \end{lstlisting} + \end{minipage} + \normalsize + \caption{Le strutture \var{timeval} e \var{timespec} usate per una + rappresentazione ad alta risoluzione del \textit{calendar time}.} + \label{fig:sys_timeval_struct} +\end{figure} + +Come nel caso di \func{stime} anche \func{settimeofday} (e qualunque funzione +vada a modificare l'orologio di sistema, come quelle che tratteremo in +seguito) può essere utilizzata solo da un processo coi privilegi di +amministratore. Il secondo parametro di entrambe le funzioni è una struttura +\var{timezone}, che storicamente veniva utilizzata per specificare appunto la +\textit{timezone}, cioè l'insieme del fuso orario e delle convenzioni per +l'ora legale che permettevano il passaggio dal tempo universale all'ora +locale. Questo parametro è obsoleto e in Linux non è mai stato utilizzato e +non è supportato né dalle vecchie \textsl{libc5}, né dalle \textsl{glibc}: +pertanto deve essere sempre settato a \macro{NULL}. + +Modificare l'orologio di sistema con queste funzioni è comunque problematico, +in quanto esse effettuano un cambiamento immediato. Ad esempio se si porta +avanti l'orologio si possono perdere delle esecuzioni di \cmd{cron} +programmate nell'intervallo che si è saltato. Per questo motivo la modalità +più corretta per settare l'ora è quella di usare la funzione \func{adjtime}, +il cui prototipo è: +\begin{prototype}{sys/time.h} +{int adjtime(const struct timeval *delta, struct timeval *olddelta)} + + Aggiusta del valore \param{delta} l'orologio di sistema. + + \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di + errore, nel qual caso \var{errno} assumerà il valore \macro{EPERM}.} +\end{prototype} + +Questa funzione permette di avere un aggiustamento graduale del tempo di +sistema in modo che esso sia sempre monotonicamente crescente. Il valore di +\param{delta} esprime il valore di cui si vuole spostare l'orologio; se è +positivo l'orologio sarà accelerato per un certo tempo in modo da guadagnare +il tempo richiesto, altrimenti sarà rallentato. Il secondo parametro viene +usato, se non nullo, per ricevere il valore dell'ultimo aggiustamento +effettuto. + +Linux poi prevede un'altra funzione, \func{adjtimex}, che consente un +aggiustamento molto più dettagliato, permettendo ad esempio anche di +modificare anche la velocità dell'orologio di sistema. La funzione utilizza il +meccanismo di David L. Mills, descritto nell'RFC~1305, che è alla base del +protocollo NTP; la funzione è specifica di Linux e non deve essere usata se la +portabilità è un requisito, le \acr{glibc} provvedono anhe un suo omonimo +\func{ntp\_adjtime}. Il suo prototipo è: +\begin{prototype}{sys/timex.h} +{int adjtimex(struct timex *buf)} + + Aggiusta del valore \param{delta} l'orologio di sistema. + + \bodydesc{La funzione restituisce lo stato dell'orologio (un valore $>0$) in + caso di successo e -1 in caso di errore, nel qual caso \var{errno} + assumerà il valore \macro{EPERM}.} +\end{prototype} + +La funzione richiede una struttura di tipo \var{timex}, la cui definizione, +così come effettuata in \file{sys/timex.h}, è riportata in +\figref{fig:sys_timex_struct}. L'azione della funzione dipende dal valore del +campo \var{mode}, che specifica quale parametro dell'orologio di sistema, +specificato in un opportuno campo di \var{timex}, deve essere settato. Un +valore nullo serve per leggere i parametri correnti; i valori diversi da zero +devono essere specificati come OR binario delle costanti riportate in +\secref{tab:sys_timex_mode}. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{} +struct timex { + unsigned int modes; /* mode selector */ + long int offset; /* time offset (usec) */ + long int freq; /* frequency offset (scaled ppm) */ + long int maxerror; /* maximum error (usec) */ + long int esterror; /* estimated error (usec) */ + int status; /* clock command/status */ + long int constant; /* pll time constant */ + long int precision; /* clock precision (usec) (read only) */ + long int tolerance; /* clock frequency tolerance (ppm) (read only) */ + struct timeval time; /* (read only) */ + long int tick; /* (modified) usecs between clock ticks */ + long int ppsfreq; /* pps frequency (scaled ppm) (ro) */ + long int jitter; /* pps jitter (us) (ro) */ + int shift; /* interval duration (s) (shift) (ro) */ + long int stabil; /* pps stability (scaled ppm) (ro) */ + long int jitcnt; /* jitter limit exceeded (ro) */ + long int calcnt; /* calibration intervals (ro) */ + long int errcnt; /* calibration errors (ro) */ + long int stbcnt; /* stability limit exceeded (ro) */ +}; + \end{lstlisting} + \end{minipage} + \normalsize + \caption{La struttura \var{timex} per il controllo dell'orologio di sistema.} + \label{fig:sys_timex_struct} +\end{figure} + +La trattazione completa di questa funzione necessita di una lettura +approfondita del meccanismo descritto nell'RFC~1305, ci limitiamo a descrivere +in \tabref{tab:sys_timex_mode} i principali valori utilizzabili, un elenco più +dettagliato del significato dei vari campi può essere ritrovato in +\cite{glibc}. + +\begin{table}[htb] + \footnotesize + \centering + \begin{tabular}[c]{|l|c| p{10cm}|} + \hline + \textbf{Nome} & \textbf{Valore} & \textbf{Significato}\\ + \hline + \hline + \macro{ADJ\_OFFSET} & 0x0001 & Setta la differenza fra il tempo + reale e l'orologio di sistema, che + deve essere indicata in microsecondi + nel campo \var{offset} di + \var{timex}.\\ + \macro{ADJ\_FREQUENCY} & 0x0002 & Setta la differenze in frequenza + fra il tempo reale e l'orologio di + sistema, che deve essere indicata + in parti per milione nel campo + \var{frequency} di \var{timex}.\\ + \macro{ADJ\_MAXERROR} & 0x0004 & Setta il valore massimo dell'errore + sul tempo, espresso in microsecondi + nel campo \var{maxerror} di + \var{timex}.\\ + \macro{ADJ\_ESTERROR} & 0x0008 & Setta la stima dell'errore + sul tempo, espresso in microsecondi + nel campo \var{esterror} di + \var{timex}.\\ + \macro{ADJ\_STATUS} & 0x0010 & Setta alcuni + valori di stato interni usati dal + sistema nella gestione + dell'orologio specificati nel campo + \var{status} di \var{timex}.\\ + \macro{ADJ\_TIMECONST} & 0x0020 & Setta la larghezza di banda del PLL + implementato dal kernel, + specificato nel campo + \var{constant} di \var{timex}.\\ + \macro{ADJ\_TICK} & 0x4000 & Setta il valore dei tick del timer + in microsecondi, espresso nel campo + \var{tick} di \var{timex}.\\ + \macro{ADJ\_OFFSET\_SINGLESHOT}&0x8001&Setta uno spostamento una tantum + dell'orologio secondo il valore del + campo \var{offset} simulando il + comportamento di \func{adjtime}.\\ + \hline + \end{tabular} + \caption{Costanti per l'assegnazione del valore del campo \var{mode} della + struttura \var{timex}.} + \label{tab:sys_timex_mode} +\end{table} + +La funzione ritorna un valore positivo che esprime lo stato dell'orologio di +sistema; questo può + + +\subsection{La gestione delle date.} +\label{sec:sys_date}