effettivamente tre variabili di tipo \ctyp{FILE *} che possono essere
usate come tutte le altre, ad esempio si può effettuare una redirezione
dell'output di un programma con il semplice codice:
-\begin{lstlisting}[stepnumber=0,frame=]{}
- fclose(stdout);
- stdout = fopen("standard-output-file", "w");
-\end{lstlisting}
+\includecodesnip{listati/redir_stdout.c}
ma in altri sistemi queste variabili possono essere definite da macro, e
se si hanno problemi di portabilità e si vuole essere sicuri, diventa
opportuno usare la funzione \func{freopen}.
blocchi di dati binari in maniera compatta e veloce; un primo caso di uso
tipico è quello in cui si salva un vettore (o un certo numero dei suoi
elementi) con una chiamata del tipo:
-%\footnotesize
-\begin{lstlisting}[stepnumber=0,frame=]{}
-int WriteVect(FILE *stream, double *vec, size_t nelem)
-{
- int size, nread;
- size = sizeof(*vec);
- if ( (nread = fwrite(vec, size, nelem, stream)) != nelem) {
- perror("Write error");
- }
- return nread;
-}
-\end{lstlisting}
-%\normalsize
+\includecodesnip{listati/WriteVect.c}
in questo caso devono essere specificate le dimensioni di ciascun
elemento ed il numero di quelli che si vogliono scrivere. Un secondo
caso è invece quello in cui si vuole trasferire su file una struttura;
si avrà allora una chiamata tipo:
-%\footnotesize
-\begin{lstlisting}[stepnumber=0,frame=]{}
-struct histogram {
- int nbins;
- double max, min;
- double *bin;
-} histo;
-
-int WriteStruct(FILE *stream, struct histogram *histo)
-{
- if ( fwrite(histo, sizeof(*histo), 1, stream) !=1) {
- perror("Write error");
- }
- return nread;
-}
-\end{lstlisting}
-%\normalsize
+\includecodesnip{listati/WriteStruct.c}
in cui si specifica la dimensione dell'intera struttura ed un solo
elemento.
necessaria a contenere la linea. In tutti i casi si ottiene dalla funzione un
puntatore all'inizio del testo della linea letta. Un esempio di codice può
essere il seguente:
-\begin{lstlisting}[stepnumber=0,frame=]{}
- size_t n = 0;
- char *ptr = NULL;
- int nread;
- FILE * file;
- ...
- nread = getline(&ptr, &n, file);
-\end{lstlisting}
+\includecodesnip{listati/getline.c}
e per evitare memory leak\index{memory leak} occorre ricordarsi di liberare
\var{ptr} con una \func{free}.
--- /dev/null
+struct histogram {
+ int nbins;
+ double max, min;
+ double *bin;
+} histo;
+
+int WriteStruct(FILE *stream, struct histogram *histo)
+{
+ if ( fwrite(histo, sizeof(*histo), 1, stream) !=1) {
+ perror("Write error");
+ }
+ return nread;
+}
--- /dev/null
+int WriteVect(FILE *stream, double *vec, size_t nelem)
+{
+ int size, nread;
+ size = sizeof(*vec);
+ if ( (nread = fwrite(vec, size, nelem, stream)) != nelem) {
+ perror("Write error");
+ }
+ return nread;
+}
--- /dev/null
+ /* convert string to number */
+ err = strtol(argv[optind], NULL, 10);
+ /* testing error condition on conversion */
+ if (err==LONG_MIN) {
+ perror("Underflow on error code");
+ return 1;
+ } else if (err==LONG_MIN) {
+ perror("Overflow on error code");
+ return 1;
+ }
+ /* conversion is fine */
+ if (message) {
+ printf("Error message for %d is %s\n", err, strerror(err));
+ }
+ if (label) {
+ printf("Error label for %d is %s\n", err, err_code[err]);
+ }
--- /dev/null
+ const char *sys_errlist[];
+ int sys_nerr;
--- /dev/null
+get_child_max(void)
+{
+#ifdef CHILD_MAX
+ return CHILD_MAX;
+#else
+ int val = sysconf(_SC_CHILD_MAX);
+ if (val < 0) {
+ perror("fatal error");
+ exit(-1);
+ }
+ return val;
+}
--- /dev/null
+ size_t n = 0;
+ char *ptr = NULL;
+ int nread;
+ FILE * file;
+ ...
+ nread = getline(&ptr, &n, file);
--- /dev/null
+struct group {
+ char *gr_name; /* group name */
+ char *gr_passwd; /* group password */
+ gid_t gr_gid; /* group id */
+ char **gr_mem; /* group members */
+};
--- /dev/null
+struct itimerval
+{
+ struct timeval it_interval; /* next value */
+ struct timeval it_value; /* current value */
+};
--- /dev/null
+struct passwd {
+ char *pw_name; /* user name */
+ char *pw_passwd; /* user password */
+ uid_t pw_uid; /* user id */
+ gid_t pw_gid; /* group id */
+ char *pw_gecos; /* real name */
+ char *pw_dir; /* home directory */
+ char *pw_shell; /* shell program */
+};
--- /dev/null
+ fclose(stdout);
+ stdout = fopen("standard-output-file", "w");
--- /dev/null
+struct rlimit {
+ rlim_t rlim_cur;
+ rlim_t rlim_max;
+};
--- /dev/null
+struct rusage {
+ struct timeval ru_utime; /* user time used */
+ struct timeval ru_stime; /* system time used */
+ long ru_maxrss; /* maximum resident set size */
+ long ru_ixrss; /* integral shared memory size */
+ long ru_idrss; /* integral unshared data size */
+ long ru_isrss; /* integral unshared stack size */
+ long ru_minflt; /* page reclaims */
+ long ru_majflt; /* page faults */
+ long ru_nswap; /* swaps */
+ long ru_inblock; /* block input operations */
+ long ru_oublock; /* block output operations */
+ long ru_msgsnd; /* messages sent */
+ long ru_msgrcv; /* messages received */
+ long ru_nsignals; ; /* signals received */
+ long ru_nvcsw; /* voluntary context switches */
+ long ru_nivcsw; /* involuntary context switches */
+};
--- /dev/null
+ typedef void (* sighandler_t)(int)
--- /dev/null
+ extern const char *const sys_siglist[];
--- /dev/null
+ void (*signal(int signum, void (*handler)(int)))int)
--- /dev/null
+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; /* inode totali nel filesystem */
+ long f_ffree; /* inode 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 */
+};
--- /dev/null
+extern char *tzname[2];
+extern long timezone;
+extern int daylight;
--- /dev/null
+struct timeval
+{
+ long tv_sec; /* seconds */
+ long tv_usec; /* microseconds */
+};
+struct timespec {
+ time_t tv_sec; /* seconds */
+ long tv_nsec; /* nanoseconds */
+};
--- /dev/null
+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) */
+};
--- /dev/null
+struct tm {
+ int tm_sec; /* seconds */
+ int tm_min; /* minutes */
+ int tm_hour; /* hours */
+ int tm_mday; /* day of the month */
+ int tm_mon; /* month */
+ int tm_year; /* year */
+ int tm_wday; /* day of the week */
+ int tm_yday; /* day in the year */
+ int tm_isdst; /* daylight saving time */
+ long int tm_gmtoff; /* Seconds east of UTC. */
+ const char *tm_zone; /* Timezone abbreviation. */
+};
--- /dev/null
+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 */
+};
--- /dev/null
+int sig_handler(); /* handler function */
+int main()
+{
+ ...
+ signal(SIGINT, sig_handler); /* establish handler */
+ ...
+}
+
+int sig_handler()
+{
+ signal(SIGINT, sig_handler); /* restablish handler */
+ ... /* process signal */
+}
--- /dev/null
+struct utsname {
+ char sysname[];
+ char nodename[];
+ char release[];
+ char version[];
+ char machine[];
+#ifdef _GNU_SOURCE
+ char domainname[];
+#endif
+};
--- /dev/null
+struct utmp
+{
+ short int ut_type; /* Type of login. */
+ pid_t ut_pid; /* Process ID of login process. */
+ char ut_line[UT_LINESIZE]; /* Devicename. */
+ char ut_id[4]; /* Inittab ID. */
+ char ut_user[UT_NAMESIZE]; /* Username. */
+ char ut_host[UT_HOSTSIZE]; /* Hostname for remote login. */
+ struct exit_status ut_exit; /* Exit status of a process marked
+ as DEAD_PROCESS. */
+ long int ut_session; /* Session ID, used for windowing. */
+ struct timeval ut_tv; /* Time entry was made. */
+ int32_t ut_addr_v6[4]; /* Internet address of remote host. */
+ char __unused[20]; /* Reserved for future use. */
+};
La funzione permette, a seconda del valore di \param{which}, di leggere la
priorità di un processo, di un gruppo di processi (vedi
\secref{sec:sess_proc_group}) o di un utente, specificando un corrispondente
-valore per \param{who}; un valore nullo di quest'ultimo indica il processo, il
-gruppo di processi o l'utente correnti.
+valore per \param{who} secondo la legenda di \tabref{tab:proc_getpriority}; un
+valore nullo di quest'ultimo indica il processo, il gruppo di processi o
+l'utente correnti.
\begin{table}[htb]
\centering
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
- \begin{lstlisting}{}
-int sig_handler(); /* handler function */
-int main()
-{
- ...
- signal(SIGINT, sig_handler); /* establish handler */
- ...
-}
-
-int sig_handler()
-{
- signal(SIGINT, sig_handler); /* restablish handler */
- ... /* process signal */
-}
- \end{lstlisting}
+ \includecodesample{listati/unreliable_sig.c}
\end{minipage}
\normalsize
\caption{Esempio di codice di un gestore di segnale per la semantica
Raccogliamo qui infine usa serie di segnali che hanno scopi differenti non
classificabili in maniera omogenea. Questi segnali sono:
\begin{basedescript}{\desclabelwidth{2.0cm}}
-\item[\const{SIGUSR1}] Vedi \const{SIGUSR2}.
-\item[\const{SIGUSR2}] Insieme a \const{SIGUSR1} è un segnale a disposizione
- dell'utente che li può usare per quello che vuole. Possono essere utili per
- implementare una comunicazione elementare fra processi diversi, o per
- eseguire a richiesta una operazione utilizzando un gestore. L'azione
- predefinita è di terminare il processo.
+\item[\const{SIGUSR1}] Insieme a \const{SIGUSR2} è un segnale a disposizione
+ dell'utente che lo può usare per quello che vuole. Viene generato solo
+ attraverso l'invocazione della funzione \func{kill}. Entrambi i segnali
+ possono essere utili per implementare una comunicazione elementare fra
+ processi diversi, o per eseguire a richiesta una operazione utilizzando un
+ gestore. L'azione predefinita è di terminare il processo.
+\item[\const{SIGUSR2}] È il secondo segnale a dispozione degli utenti. Vedi
+ quanto appena detto per \const{SIGUSR1}.
\item[\const{SIGWINCH}] Il nome sta per \textit{window (size) change} e viene
generato in molti sistemi (GNU/Linux compreso) quando le dimensioni (in
righe e colonne) di un terminale vengono cambiate. Viene usato da alcuni
\func{strsignal} e \func{psignal} è quello di fare usare la variabile
\var{sys\_siglist}, che è definita in \file{signal.h} e può essere acceduta
con la dichiarazione:
-\begin{lstlisting}[stepnumber=0,frame=]{}
- extern const char *const sys_siglist[]
-\end{lstlisting}
+\includecodesnip{listati/siglist.c}
l'array \var{sys\_siglist} contiene i puntatori alle stringhe di descrizione,
indicizzate per numero di segnale, per cui una chiamata del tipo di \code{char
*decr = strsignal(SIGINT)} può essere sostituita dall'equivalente \code{char
una estensione GNU, definita dalle \acr{glibc}, che permette di riscrivere il
prototipo di \func{signal} nella forma appena vista, molto più leggibile di
quanto non sia la versione originaria, che di norma è definita come:
-\begin{lstlisting}[stepnumber=0,frame=]{}
- void (*signal(int signum, void (*handler)(int)))int)
-\end{lstlisting}
+\includecodesnip{listati/signal.c}
questa infatti, per la poca chiarezza della sintassi del C quando si vanno a
trattare puntatori a funzioni, è molto meno comprensibile. Da un confronto
con il precedente prototipo si può dedurre la definizione di
\type{sighandler\_t} che è:
-\begin{lstlisting}[stepnumber=0,frame=]{}
- typedef void (* sighandler_t)(int)
-\end{lstlisting}
+\includecodesnip{listati/sighandler_t.c}
e cioè un puntatore ad una funzione \ctyp{void} (cioè senza valore di ritorno)
e che prende un argomento di tipo \ctyp{int}.\footnote{si devono usare le
parentesi intorno al nome della funzione per via delle precedenze degli
L'uso di \func{signal} è soggetto a problemi di compatibilità, dato che essa
si comporta in maniera diversa per sistemi derivati da BSD o da System V. In
questi ultimi infatti la funzione è conforme al comportamento originale dei
-primi Unix in cui il gestore viene disinstallato alla sua chiamata,
-secondo la semantica inaffidabile; Linux seguiva questa convenzione fino alle
-\acr{libc5}. Al contrario BSD segue la semantica affidabile, non
-disinstallando il gestore e bloccando il segnale durante l'esecuzione
-dello stesso. Con l'utilizzo delle \acr{glibc} dalla versione 2 anche Linux è
-passato a questo comportamento; quello della versione originale della
-funzione, il cui uso è deprecato per i motivi visti in
-\secref{sec:sig_semantics}, può essere ottenuto chiamando \func{sysv\_signal}.
-In generale, per evitare questi problemi, tutti i nuovi programmi dovrebbero
-usare \func{sigaction}.
+primi Unix in cui il gestore viene disinstallato alla sua chiamata, secondo la
+semantica inaffidabile; anche Linux seguiva questa convenzione con le vecchie
+librerie del C come le \acr{libc4} e le \acr{libc5}.\footnote{nelle
+ \acr{libc5} esiste però la possibilità di includere \file{bsd/signal.h} al
+ posto di \file{signal.h}, nel qual caso la funzione \func{signal} viene
+ ridefinita per seguire la semantica affidabile usata da BSD.}
+
+Al contrario BSD segue la semantica affidabile, non disinstallando il gestore
+e bloccando il segnale durante l'esecuzione dello stesso. Con l'utilizzo delle
+\acr{glibc} dalla versione 2 anche Linux è passato a questo comportamento. Il
+comportamento della versione originale della funzione, il cui uso è deprecato
+per i motivi visti in \secref{sec:sig_semantics}, può essere ottenuto
+chiamando \func{sysv\_signal}, uno volta che si sia definita la macro
+\macro{\_XOPEN\_SOURCE}. In generale, per evitare questi problemi, l'uso di
+\func{signal} (ed ogni eventuale ridefinizine della stessa) è da evitare;
+tutti i nuovi programmi dovrebbero usare \func{sigaction}.
È da tenere presente che, seguendo lo standard POSIX, il comportamento di un
processo che ignora i segnali \const{SIGFPE}, \const{SIGILL}, o
-\const{SIGSEGV} (qualora non originino da una \func{kill} o una \func{raise})
-è indefinito. Un gestore che ritorna da questi segnali può dare luogo ad
-un ciclo infinito.
+\const{SIGSEGV} (qualora questi non originino da una chiamata ad una
+\func{kill} o ad una \func{raise}) è indefinito. Un gestore che ritorna da
+questi segnali può dare luogo ad un ciclo infinito.
\subsection{Le funzioni \func{kill} e \func{raise}}
Il valore dell'argomento \param{pid} specifica il processo (o i processi) di
destinazione a cui il segnale deve essere inviato e può assumere i valori
riportati in \tabref{tab:sig_kill_values}.
+
+Si noti pertanto che la funzione \code{raise(sig)} può essere definita in
+termini di \func{kill}, ed è sostanzialmente equivalente ad una
+\code{kill(getpid(), sig)}. Siccome \func{raise}, che è definita nello
+standard ISO C, non esiste in alcune vecchie versioni di Unix, in generale
+l'uso di \func{kill} finisce per essere più portabile.
+
+Una seconda funzione che può essere definita in termini di \func{kill} è
+\funcd{killpg}, che è sostanzialmente equivalente a
+\code{kill(-pidgrp, signal)}; il suo prototipo è:
+\begin{prototype}{signal.h}{int killpg(pid\_t pidgrp, int signal)}
+
+ Invia il segnale \param{signal} al process group \param{pidgrp}.
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore, gli errori sono gli stessi di \func{kill}.}
+\end{prototype}
+\noindent e che permette di inviare un segnale a tutto un \textit{process
+ group} (vedi \secref{sec:sess_proc_group}).
+
\begin{table}[htb]
\footnotesize
\centering
\label{tab:sig_kill_values}
\end{table}
-Si noti pertanto che la funzione \code{raise(sig)} può essere definita in
-termini di \func{kill}, ed è sostanzialmente equivalente ad una
-\code{kill(getpid(), sig)}. Siccome \func{raise}, che è definita nello
-standard ISO C, non esiste in alcune vecchie versioni di Unix, in generale
-l'uso di \func{kill} finisce per essere più portabile.
-
-Una seconda funzione che può essere definita in termini di \func{kill} è
-\funcd{killpg}, che è sostanzialmente equivalente a
-\code{kill(-pidgrp, signal)}; il suo prototipo è:
-\begin{prototype}{signal.h}{int killpg(pid\_t pidgrp, int signal)}
-
- Invia il segnale \param{signal} al process group \param{pidgrp}.
- \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
- errore, gli errori sono gli stessi di \func{kill}.}
-\end{prototype}
-e che permette di inviare un segnale a tutto un \textit{process group} (vedi
-\secref{sec:sess_proc_group}).
-
Solo l'amministratore può inviare un segnale ad un processo qualunque, in
tutti gli altri casi l'user-ID reale o l'user-ID effettivo del processo
chiamante devono corrispondere all'user-ID reale o all'user-ID salvato della
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
- \begin{lstlisting}[stepnumber=0]{}
-struct itimerval
-{
- struct timeval it_interval; /* next value */
- struct timeval it_value; /* current value */
-};
- \end{lstlisting}
+ \includestruct{listati/itimerval.h}
\end{minipage}
\normalsize
\caption{La struttura \structd{itimerval}, che definisce i valori dei timer
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "gapil"
+%%% TeX-master: "gapil"
%%% End:
In generale si dovrebbe fare uso di \func{sysconf} solo quando la relativa
macro non è definita, quindi con un codice analogo al seguente:
-%\footnotesize
-\begin{lstlisting}[stepnumber=0,frame=]{}
-get_child_max(void)
-{
-#ifdef CHILD_MAX
- return CHILD_MAX;
-#else
- int val = sysconf(_SC_CHILD_MAX);
- if (val < 0) {
- perror("fatal error");
- exit(-1);
- }
- return val;
-}
-\end{lstlisting}
-%\normalsize
+\includecodesnip{listati/get_child_max.c}
ma in realtà in Linux queste macro sono comunque definite, indicando però un
limite generico. Per questo motivo è sempre meglio usare i valori restituiti
da \func{sysconf}.
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
- \begin{lstlisting}[stepnumber=0]{}
-struct utsname {
- char sysname[];
- char nodename[];
- char release[];
- char version[];
- char machine[];
-#ifdef _GNU_SOURCE
- char domainname[];
-#endif
-};
- \end{lstlisting}
+ \includestruct{listati/ustname.h}
\end{minipage}
\normalsize
\caption{La struttura \structd{utsname}.}
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
- \begin{lstlisting}[stepnumber=0]{}
-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; /* inode totali nel filesystem */
- long f_ffree; /* inode 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}
+ \includestruct{listati/statfs.h}
\end{minipage}
\normalsize
\caption{La struttura \structd{statfs}.}
\footnotesize
\centering
\begin{minipage}[c]{15cm}
- \begin{lstlisting}[stepnumber=0]{}
-struct passwd {
- char *pw_name; /* user name */
- char *pw_passwd; /* user password */
- uid_t pw_uid; /* user id */
- gid_t pw_gid; /* group id */
- char *pw_gecos; /* real name */
- char *pw_dir; /* home directory */
- char *pw_shell; /* shell program */
-};
- \end{lstlisting}
+ \includestruct{listati/passwd.h}
\end{minipage}
\normalsize
\caption{La struttura \structd{passwd} contenente le informazioni relative ad
\footnotesize
\centering
\begin{minipage}[c]{15cm}
- \begin{lstlisting}[stepnumber=0]{}
-struct group {
- char *gr_name; /* group name */
- char *gr_passwd; /* group password */
- gid_t gr_gid; /* group id */
- char **gr_mem; /* group members */
-};
- \end{lstlisting}
+ \includestruct{listati/group.h}
\end{minipage}
\normalsize
\caption{La struttura \structd{group} contenente le informazioni relative ad
corrispondenti ai file \file{/var/run/utmp} e \file{/var/log/wtmp} visti in
precedenza.
+\begin{figure}[!htb]
+ \footnotesize
+ \centering
+ \begin{minipage}[c]{15cm}
+ \includestruct{listati/utmp.h}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{utmp} contenente le informazioni di una voce
+ del database di \textit{accounting}.}
+ \label{fig:sys_utmp_struct}
+\end{figure}
+
Una volta aperto il file si può eseguire una scansione leggendo o scrivendo
una voce con le funzioni \funcd{getutent}, \funcd{getutid}, \funcd{getutline}
e \funcd{pututline}, i cui prototipi sono:
\end{functions}
Tutte queste funzioni fanno riferimento ad una struttura di tipo \struct{utmp},
-la cui definizione in Linux è riportata in \secref{fig:sys_utmp_struct}. Le
+la cui definizione in Linux è riportata in \figref{fig:sys_utmp_struct}. Le
prime tre funzioni servono per leggere una voce dal database; \func{getutent}
legge semplicemente la prima voce disponibile; le altre due permettono di
eseguire una ricerca.
-\begin{figure}[!htb]
- \footnotesize
- \centering
- \begin{minipage}[c]{15cm}
- \begin{lstlisting}[stepnumber=0]{}
-struct utmp
-{
- short int ut_type; /* Type of login. */
- pid_t ut_pid; /* Process ID of login process. */
- char ut_line[UT_LINESIZE]; /* Devicename. */
- char ut_id[4]; /* Inittab ID. */
- char ut_user[UT_NAMESIZE]; /* Username. */
- char ut_host[UT_HOSTSIZE]; /* Hostname for remote login. */
- struct exit_status ut_exit; /* Exit status of a process marked
- as DEAD_PROCESS. */
- long int ut_session; /* Session ID, used for windowing. */
- struct timeval ut_tv; /* Time entry was made. */
- int32_t ut_addr_v6[4]; /* Internet address of remote host. */
- char __unused[20]; /* Reserved for future use. */
-};
- \end{lstlisting}
- \end{minipage}
- \normalsize
- \caption{La struttura \structd{utmp} contenente le informazioni di una voce
- del database di \textit{accounting}.}
- \label{fig:sys_utmp_struct}
-\end{figure}
-
Con \func{getutid} si può cercare una voce specifica, a seconda del valore del
campo \var{ut\_type} dell'argomento \param{ut}. Questo può assumere i valori
riportati in \tabref{tab:sys_ut_type}, quando assume i valori
\footnotesize
\centering
\begin{minipage}[c]{15cm}
- \begin{lstlisting}[stepnumber=0]{}
-struct rusage {
- struct timeval ru_utime; /* user time used */
- struct timeval ru_stime; /* system time used */
- long ru_maxrss; /* maximum resident set size */
- long ru_ixrss; /* integral shared memory size */
- long ru_idrss; /* integral unshared data size */
- long ru_isrss; /* integral unshared stack size */
- long ru_minflt; /* page reclaims */
- long ru_majflt; /* page faults */
- long ru_nswap; /* swaps */
- long ru_inblock; /* block input operations */
- long ru_oublock; /* block output operations */
- long ru_msgsnd; /* messages sent */
- long ru_msgrcv; /* messages received */
- long ru_nsignals; ; /* signals received */
- long ru_nvcsw; /* voluntary context switches */
- long ru_nivcsw; /* involuntary context switches */
-};
- \end{lstlisting}
+ \includestruct{listati/rusage.h}
\end{minipage}
\normalsize
\caption{La struttura \structd{rusage} per la lettura delle informazioni dei
\figref{fig:sys_rlimit_struct}, ed i cui campi corrispondono appunto a limite
corrente e limite massimo.
-\begin{figure}[!htb]
- \footnotesize
- \centering
- \begin{minipage}[c]{15cm}
- \begin{lstlisting}[stepnumber=0]{}
-struct rlimit {
- rlim_t rlim_cur;
- rlim_t rlim_max;
-};
- \end{lstlisting}
- \end{minipage}
- \normalsize
- \caption{La struttura \structd{rlimit} per impostare i limiti di utilizzo
- delle risorse usate da un processo.}
- \label{fig:sys_rlimit_struct}
-\end{figure}
-
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 permettere di leggere
e di impostare i limiti di utilizzo delle risorse da parte di un processo
ed \errval{EFAULT}.}
\end{functions}
+\begin{figure}[!htb]
+ \footnotesize
+ \centering
+ \begin{minipage}[c]{15cm}
+ \includestruct{listati/rlimit.h}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{rlimit} per impostare i limiti di utilizzo
+ delle risorse usate da un processo.}
+ \label{fig:sys_rlimit_struct}
+\end{figure}
+
+
+
Entrambe le funzioni permettono di specificare, attraverso l'argomento
\param{resource}, su quale risorsa si vuole operare: i possibili valori di
questo argomento sono elencati in \secref{tab:sys_rlimit_values}. L'acceso
\footnotesize
\centering
\begin{minipage}[c]{15cm}
- \begin{lstlisting}[stepnumber=0]{}
-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}
+ \includestruct{listati/tms.h}
\end{minipage}
\normalsize
\caption{La struttura \structd{tms} dei tempi di processore associati a un
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
- \begin{lstlisting}[stepnumber=0]{}
-struct timeval
-{
- long tv_sec; /* seconds */
- long tv_usec; /* microseconds */
-};
-struct timespec {
- time_t tv_sec; /* seconds */
- long tv_nsec; /* nanoseconds */
-};
- \end{lstlisting}
+ \includestruct{listati/timeval.h}
\end{minipage}
\normalsize
\caption{Le strutture \structd{timeval} e \structd{timespec} usate per una
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
- \begin{lstlisting}[stepnumber=0]{}
-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}
+ \includestruct{listati/timex.h}
\end{minipage}
\normalsize
\caption{La struttura \structd{timex} per il controllo dell'orologio di
time}, che permette appunto di \textsl{suddividere} il \textit{calendar
time} usuale in ore, minuti, secondi, ecc.
-\begin{figure}[!htb]
- \footnotesize \centering
- \begin{minipage}[c]{15cm}
- \begin{lstlisting}[stepnumber=0]{}
-struct tm {
- int tm_sec; /* seconds */
- int tm_min; /* minutes */
- int tm_hour; /* hours */
- int tm_mday; /* day of the month */
- int tm_mon; /* month */
- int tm_year; /* year */
- int tm_wday; /* day of the week */
- int tm_yday; /* day in the year */
- int tm_isdst; /* daylight saving time */
- long int tm_gmtoff; /* Seconds east of UTC. */
- const char *tm_zone; /* Timezone abbreviation. */
-};
- \end{lstlisting}
- \end{minipage}
- \normalsize
- \caption{La struttura \structd{tm} per una rappresentazione del tempo in
- termini di ora, minuti, secondi, ecc.}
- \label{fig:sys_tm_struct}
-\end{figure}
-
Questo viene effettuato attraverso una opportuna struttura \struct{tm}, la cui
definizione è riportata in \figref{fig:sys_tm_struct}, ed è in genere questa
struttura che si utilizza quando si deve specificare un tempo a partire dai
restituisce direttamente il valore o -1 in caso di errore.}
\end{functions}
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includestruct{listati/tm.h}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \structd{tm} per una rappresentazione del tempo in
+ termini di ora, minuti, secondi, ecc.}
+ \label{fig:sys_tm_struct}
+\end{figure}
+
+
+
Le prime due funzioni, \func{asctime} e \func{ctime} servono per poter
stampare in forma leggibile un tempo; esse restituiscono il puntatore ad una
stringa, allocata staticamente, nella forma:
\footnotesize
\centering
\begin{minipage}[c]{15cm}
- \begin{lstlisting}[stepnumber=0]{}
-extern char *tzname[2];
-extern long timezone;
-extern int daylight;
- \end{lstlisting}
+ \includestruct{listati/time_zone_var.c}
\end{minipage}
\normalsize
\caption{Le variabili globali usate per la gestione delle \textit{time
Il messaggio può essere riportato anche usando altre variabili globali
dichiarate in \file{errno.h}:
-\begin{verbatim}
- const char *sys_errlist[];
- int sys_nerr;
-\end{verbatim}
+\includecodesnip{listati/errlist.c}
la prima contiene i puntatori alle stringhe di errore indicizzati da
\var{errno}; la seconda esprime il valore più alto per un codice di errore,
l'utilizzo di questa stringa è sostanzialmente equivalente a quello di
\func{strerror}.
\begin{figure}[!htb]
- \footnotesize
- \begin{lstlisting}{}
- /* convert string to number */
- err = strtol(argv[optind], NULL, 10);
- /* testing error condition on conversion */
- if (err==LONG_MIN) {
- perror("Underflow on error code");
- return 1;
- } else if (err==LONG_MIN) {
- perror("Overflow on error code");
- return 1;
- }
- /* conversion is fine */
- if (message) {
- printf("Error message for %d is %s\n", err, strerror(err));
- }
- if (label) {
- printf("Error label for %d is %s\n", err, err_code[err]);
- }
- \end{lstlisting}
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \includecodesample{listati/errcode_mess.c}
+ \end{minipage}
+ \normalsize
\caption{Codice per la stampa del messaggio di errore standard.}
\label{fig:sys_err_mess}
\end{figure}