From: Simone Piccardi Date: Fri, 4 Apr 2003 11:42:03 +0000 (+0000) Subject: Si prosegue con le modifiche per l'inclusione degli esempi di codice. X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=cf60963212306540ce7485ed7c86405e143a3352 Si prosegue con le modifiche per l'inclusione degli esempi di codice. --- diff --git a/filestd.tex b/filestd.tex index d69d7d4..b928e0d 100644 --- a/filestd.tex +++ b/filestd.tex @@ -117,10 +117,7 @@ Nelle \acr{glibc} \var{stdin}, \var{stdout} e \var{stderr} sono 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}. @@ -487,40 +484,12 @@ In genere si usano queste funzioni quando si devono trasferire su file 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. @@ -906,14 +875,7 @@ e \var{*n} 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}. diff --git a/listati/WriteStruct.c b/listati/WriteStruct.c new file mode 100644 index 0000000..60b0025 --- /dev/null +++ b/listati/WriteStruct.c @@ -0,0 +1,13 @@ +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; +} diff --git a/listati/WriteVect.c b/listati/WriteVect.c new file mode 100644 index 0000000..98cfd18 --- /dev/null +++ b/listati/WriteVect.c @@ -0,0 +1,9 @@ +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; +} diff --git a/listati/errcode_mess.c b/listati/errcode_mess.c new file mode 100644 index 0000000..61321bc --- /dev/null +++ b/listati/errcode_mess.c @@ -0,0 +1,17 @@ + /* 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]); + } diff --git a/listati/errlist.c b/listati/errlist.c new file mode 100644 index 0000000..848d8f2 --- /dev/null +++ b/listati/errlist.c @@ -0,0 +1,2 @@ + const char *sys_errlist[]; + int sys_nerr; diff --git a/listati/get_child_max.c b/listati/get_child_max.c new file mode 100644 index 0000000..9890abf --- /dev/null +++ b/listati/get_child_max.c @@ -0,0 +1,12 @@ +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; +} diff --git a/listati/getline.c b/listati/getline.c new file mode 100644 index 0000000..8606d62 --- /dev/null +++ b/listati/getline.c @@ -0,0 +1,6 @@ + size_t n = 0; + char *ptr = NULL; + int nread; + FILE * file; + ... + nread = getline(&ptr, &n, file); diff --git a/listati/group.h b/listati/group.h new file mode 100644 index 0000000..3f1a367 --- /dev/null +++ b/listati/group.h @@ -0,0 +1,6 @@ +struct group { + char *gr_name; /* group name */ + char *gr_passwd; /* group password */ + gid_t gr_gid; /* group id */ + char **gr_mem; /* group members */ +}; diff --git a/listati/itimerval.h b/listati/itimerval.h new file mode 100644 index 0000000..cdd0b5a --- /dev/null +++ b/listati/itimerval.h @@ -0,0 +1,5 @@ +struct itimerval +{ + struct timeval it_interval; /* next value */ + struct timeval it_value; /* current value */ +}; diff --git a/listati/passwd.h b/listati/passwd.h new file mode 100644 index 0000000..8be4a4b --- /dev/null +++ b/listati/passwd.h @@ -0,0 +1,9 @@ +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 */ +}; diff --git a/listati/redir_stdout.c b/listati/redir_stdout.c new file mode 100644 index 0000000..c16da3c --- /dev/null +++ b/listati/redir_stdout.c @@ -0,0 +1,2 @@ + fclose(stdout); + stdout = fopen("standard-output-file", "w"); diff --git a/listati/rlimit.h b/listati/rlimit.h new file mode 100644 index 0000000..f8628b8 --- /dev/null +++ b/listati/rlimit.h @@ -0,0 +1,4 @@ +struct rlimit { + rlim_t rlim_cur; + rlim_t rlim_max; +}; diff --git a/listati/rusage.h b/listati/rusage.h new file mode 100644 index 0000000..1307aef --- /dev/null +++ b/listati/rusage.h @@ -0,0 +1,18 @@ +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 */ +}; diff --git a/listati/sighandler_t.c b/listati/sighandler_t.c new file mode 100644 index 0000000..9fe01bc --- /dev/null +++ b/listati/sighandler_t.c @@ -0,0 +1 @@ + typedef void (* sighandler_t)(int) diff --git a/listati/siglist.c b/listati/siglist.c new file mode 100644 index 0000000..eb653ea --- /dev/null +++ b/listati/siglist.c @@ -0,0 +1 @@ + extern const char *const sys_siglist[]; diff --git a/listati/signal.c b/listati/signal.c new file mode 100644 index 0000000..4e5ce1d --- /dev/null +++ b/listati/signal.c @@ -0,0 +1 @@ + void (*signal(int signum, void (*handler)(int)))int) diff --git a/listati/statfs.h b/listati/statfs.h new file mode 100644 index 0000000..a48e1ee --- /dev/null +++ b/listati/statfs.h @@ -0,0 +1,12 @@ +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 */ +}; diff --git a/listati/time_zone_var.c b/listati/time_zone_var.c new file mode 100644 index 0000000..61fb5b7 --- /dev/null +++ b/listati/time_zone_var.c @@ -0,0 +1,3 @@ +extern char *tzname[2]; +extern long timezone; +extern int daylight; diff --git a/listati/timeval.h b/listati/timeval.h new file mode 100644 index 0000000..4283a69 --- /dev/null +++ b/listati/timeval.h @@ -0,0 +1,9 @@ +struct timeval +{ + long tv_sec; /* seconds */ + long tv_usec; /* microseconds */ +}; +struct timespec { + time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +}; diff --git a/listati/timex.h b/listati/timex.h new file mode 100644 index 0000000..05ff67e --- /dev/null +++ b/listati/timex.h @@ -0,0 +1,21 @@ +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) */ +}; diff --git a/listati/tm.h b/listati/tm.h new file mode 100644 index 0000000..d4c9ee2 --- /dev/null +++ b/listati/tm.h @@ -0,0 +1,13 @@ +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. */ +}; diff --git a/listati/tms.h b/listati/tms.h new file mode 100644 index 0000000..3c9422f --- /dev/null +++ b/listati/tms.h @@ -0,0 +1,6 @@ +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 */ +}; diff --git a/listati/unreliable_sig.c b/listati/unreliable_sig.c new file mode 100644 index 0000000..36490c7 --- /dev/null +++ b/listati/unreliable_sig.c @@ -0,0 +1,13 @@ +int sig_handler(); /* handler function */ +int main() +{ + ... + signal(SIGINT, sig_handler); /* establish handler */ + ... +} + +int sig_handler() +{ + signal(SIGINT, sig_handler); /* restablish handler */ + ... /* process signal */ +} diff --git a/listati/ustname.h b/listati/ustname.h new file mode 100644 index 0000000..aef0d4f --- /dev/null +++ b/listati/ustname.h @@ -0,0 +1,10 @@ +struct utsname { + char sysname[]; + char nodename[]; + char release[]; + char version[]; + char machine[]; +#ifdef _GNU_SOURCE + char domainname[]; +#endif +}; diff --git a/listati/utmp.h b/listati/utmp.h new file mode 100644 index 0000000..4d918b6 --- /dev/null +++ b/listati/utmp.h @@ -0,0 +1,15 @@ +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. */ +}; diff --git a/prochand.tex b/prochand.tex index d38c843..6cca82e 100644 --- a/prochand.tex +++ b/prochand.tex @@ -2065,8 +2065,9 @@ librerie, ma 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 diff --git a/signal.tex b/signal.tex index 525e859..c28a70c 100644 --- a/signal.tex +++ b/signal.tex @@ -105,21 +105,7 @@ verr \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 @@ -691,12 +677,14 @@ segnali sono: 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 @@ -740,9 +728,7 @@ Una modalit \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 @@ -879,16 +865,12 @@ In questa definizione si 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 @@ -918,22 +900,28 @@ mai notificati. 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}} @@ -998,6 +986,25 @@ esso sia realmente quello a cui si intendeva mandare il segnale. 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 @@ -1019,24 +1026,6 @@ riportati in \tabref{tab:sig_kill_values}. \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 @@ -1164,13 +1153,7 @@ questo modo il ciclo verr \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 @@ -2626,4 +2609,5 @@ dedicato alla gestione, che potrebbe riceverlo fra due chiamate successive. %%% Local Variables: %%% mode: latex %%% TeX-master: "gapil" +%%% TeX-master: "gapil" %%% End: diff --git a/system.tex b/system.tex index e5fe228..4d980b2 100644 --- a/system.tex +++ b/system.tex @@ -365,22 +365,7 @@ sostituendolo a \code{\_POSIX\_} per le macro definite dagli gli altri due. 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}. @@ -521,18 +506,7 @@ solo definendo \macro{\_GNU\_SOURCE}. \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}.} @@ -896,20 +870,7 @@ genere \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}.} @@ -983,17 +944,7 @@ il significato dei vari campi. \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 @@ -1070,14 +1021,7 @@ in questo caso le informazioni vengono restituite in una struttura di tipo \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 @@ -1206,6 +1150,18 @@ standard \const{\_PATH\_UTMP} (che 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: @@ -1230,39 +1186,11 @@ 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 @@ -1377,26 +1305,7 @@ di tipo \struct{rusage}, la cui definizione (che si trova in \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 @@ -1469,23 +1378,6 @@ struttura \struct{rlimit}, la cui definizione \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 @@ -1514,6 +1406,20 @@ prototipi sono: 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 @@ -1808,14 +1714,7 @@ struttura di tipo \struct{tms}, la cui definizione \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 @@ -1908,17 +1807,7 @@ nanosecondo.\footnote{la precisione \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 @@ -1971,29 +1860,7 @@ effettuato. \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 @@ -2128,31 +1995,6 @@ stata introdotta una ulteriore rappresentazione, detta \textit{broken-down 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 @@ -2192,6 +2034,19 @@ tempo in una stringa contenente data ed ora, i loro prototipi sono: 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: @@ -2242,11 +2097,7 @@ verr \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 @@ -2460,36 +2311,18 @@ punti e da uno spazio, il messaggio 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}