contengono le costanti necessarie definite come macro di preprocessore, per la
seconda invece sono ovviamente necessarie delle funzioni. La situazione è
complicata dal fatto che ci sono molti casi in cui alcuni di questi limiti
-sono fissi in una implementazione mentre possono variare in un altra. Tutto
+sono fissi in un'implementazione mentre possono variare in un altra. Tutto
questo crea una ambiguità che non è sempre possibile risolvere in maniera
chiara; in generale quello che succede è che quando i limiti del sistema sono
fissi essi vengono definiti come macro di preprocessore nel file
\hline
\macro{MB\_LEN\_MAX}& 16 & massima dimensione di un
carattere esteso\\
- \macro{CHAR\_BIT} & 8 & bit di \type{char}\\
- \macro{UCHAR\_MAX}& 255 & massimo di \type{unsigned char}\\
- \macro{SCHAR\_MIN}& -128 & minimo di \type{signed char}\\
- \macro{SCHAR\_MAX}& 127 & massimo di \type{signed char}\\
- \macro{CHAR\_MIN} &\footnotemark& minimo di \type{char}\\
- \macro{CHAR\_MAX} &\footnotemark& massimo di \type{char}\\
- \macro{SHRT\_MIN} & -32768 & minimo di \type{short}\\
- \macro{SHRT\_MAX} & 32767 & massimo di \type{short}\\
- \macro{USHRT\_MAX}& 65535 & massimo di \type{unsigned short}\\
- \macro{INT\_MAX} & 2147483647 & minimo di \type{int}\\
- \macro{INT\_MIN} &-2147483648 & minimo di \type{int}\\
- \macro{UINT\_MAX} & 4294967295 & massimo di \type{unsigned int}\\
- \macro{LONG\_MAX} & 2147483647 & massimo di \type{long}\\
- \macro{LONG\_MIN} &-2147483648 & minimo di \type{long}\\
- \macro{ULONG\_MAX}& 4294967295 & massimo di \type{unsigned long}\\
+ \macro{CHAR\_BIT} & 8 & bit di \ctyp{char}\\
+ \macro{UCHAR\_MAX}& 255 & massimo di \ctyp{unsigned char}\\
+ \macro{SCHAR\_MIN}& -128 & minimo di \ctyp{signed char}\\
+ \macro{SCHAR\_MAX}& 127 & massimo di \ctyp{signed char}\\
+ \macro{CHAR\_MIN} &\footnotemark& minimo di \ctyp{char}\\
+ \macro{CHAR\_MAX} &\footnotemark& massimo di \ctyp{char}\\
+ \macro{SHRT\_MIN} & -32768 & minimo di \ctyp{short}\\
+ \macro{SHRT\_MAX} & 32767 & massimo di \ctyp{short}\\
+ \macro{USHRT\_MAX}& 65535 & massimo di \ctyp{unsigned short}\\
+ \macro{INT\_MAX} & 2147483647 & minimo di \ctyp{int}\\
+ \macro{INT\_MIN} &-2147483648 & minimo di \ctyp{int}\\
+ \macro{UINT\_MAX} & 4294967295 & massimo di \ctyp{unsigned int}\\
+ \macro{LONG\_MAX} & 2147483647 & massimo di \ctyp{long}\\
+ \macro{LONG\_MIN} &-2147483648 & minimo di \ctyp{long}\\
+ \macro{ULONG\_MAX}& 4294967295 & massimo di \ctyp{unsigned long}\\
\hline
\end{tabular}
\caption{Costanti definite in \file{limits.h} in conformità allo standard
a seconda che il sistema usi caratteri con segno o meno.}
A questi valori lo standard ISO C90 ne aggiunge altri tre, relativi al tipo
-\type{long long} introdotto con il nuovo standard, i relativi valori sono in
+\ctyp{long long} introdotto con il nuovo standard, i relativi valori sono in
\tabref{tab:sys_isoc90_macro}.
\begin{table}[htb]
\textbf{Macro}&\textbf{Valore}&\textbf{Significato}\\
\hline
\hline
- \macro{LLONG\_MAX}& 9223372036854775807& massimo di \type{long long}\\
- \macro{LLONG\_MIN}&-9223372036854775808& minimo di \type{long long}\\
+ \macro{LLONG\_MAX}& 9223372036854775807& massimo di \ctyp{long long}\\
+ \macro{LLONG\_MIN}&-9223372036854775808& minimo di \ctyp{long long}\\
\macro{ULLONG\_MAX}&18446744073709551615&
- massimo di \type{unsigned long long}\\
+ massimo di \ctyp{unsigned long long}\\
\hline
\end{tabular}
\caption{Macro definite in \file{limits.h} in conformità allo standard
\hline
\hline
\end{tabular}
- \caption{Macro .}
+ \caption{Costanti per i limiti del sistema.}
\label{tab:sys_generic_macro}
\end{table}
In generale si dovrebbe fare uso di \func{sysconf} solo quando la relativa
macro non è definita, quindi con un codice analogo al seguente:
-\footnotesize
+%\footnotesize
\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
get_child_max(void)
{
return val;
}
\end{lstlisting}
-\normalsize
+%\normalsize
ma in realtà in Linux queste macro sono comunque definite e indicando un
limite generico, per cui è sempre meglio usare i valori restituiti da
quest'ultima.
\subsection{La funzione \func{uname}}
\label{sec:sys_uname}
-Una altra funzione che si può utilizzare per raccogliere informazioni sia
+Un'altra funzione che si può utilizzare per raccogliere informazioni sia
riguardo al sistema che al computer su cui esso sta girando è \func{uname}, il
suo prototipo è:
\begin{prototype}{sys/utsname.h}{int uname(struct utsname *info)}
La funzione, che viene usata dal comando \cmd{uname}, restituisce le
informazioni richieste nella struttura \param{info}; anche questa struttura è
-definita in \file{sys/utsname.h} come:
-\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-struct utsname {
- char sysname[_UTSNAME_LENGTH];
- char nodename[_UTSNAME_LENGTH];
- char release[_UTSNAME_LENGTH];
- char version[_UTSNAME_LENGTH];
- char machine[_UTSNAME_LENGTH];
-#ifdef _GNU_SOURCE
- char domainname[_UTSNAME_DOMAIN_LENGTH];
-#endif
-};
-\end{lstlisting}
-e le informazioni memorizzate nei suoi membri indicano rispettivamente:
+definita in \file{sys/utsname.h}, secondo quanto mostrato in
+\secref{fig:sys_utsname}, e le informazioni memorizzate nei suoi membri
+indicano rispettivamente:
\begin{itemize*}
\item il nome del sistema operativo;
\item il nome della release del kernel;
\item il nome della stazione;
\item il nome del domino.
\end{itemize*}
-(l'ultima informazione è stata aggiunta di recente e non è prevista dallo
-standard POSIX).
+l'ultima informazione è stata aggiunta di recente e non è prevista dallo
+standard POSIX, essa è accessibile, come mostrato in \figref{fig:sig_stack_t},
+solo definendo \macro{\_GNU\_SOURCE}.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct utsname {
+ char sysname[];
+ char nodename[];
+ char release[];
+ char version[];
+ char machine[];
+#ifdef _GNU_SOURCE
+ char domainname[];
+#endif
+};
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \var{utsname}.}
+ \label{fig:sys_utsname}
+\end{figure}
+
+In generale si tenga presente che le dimensioni delle stringe di una
+\var{utsname} non è specificata, e che esse sono sempre terminate con
+\macro{NULL}; il manuale delle \acr{glibc} indica due diverse dimensioni,
+\macro{\_UTSNAME\_LENGTH} per i campi standard e
+\macro{\_UTSNAME\_DOMAIN\_LENGTH} per quello specifico per il nome di dominio;
+altri sistemi usano nomi diversi come \macro{SYS\_NMLN} o \macro{\_SYS\_NMLN}
+or \macro{UTSLEN} che possono avere valori diversi; nel caso di Linux
+\func{uname} corrisponde in realtà a 3 system call diverse, le prime due usano
+delle lunghezze delle stringhe di 9 e 65 byte; la terza 65, restituisce anche
+l'ultimo campo con una lunghezza di 257 byte.
\section{Opzioni e configurazione del sistema}
arriva ad identificare un parametro specifico è passato alla funzione
attraverso l'array \param{name}, di lunghezza \param{nlen}, che contiene la
sequenza dei vari nodi da attraversare. Ogni parametro ha un valore in un
-formato specifico chee può essere un intero, una stringa o anche una struttura
+formato specifico che può essere un intero, una stringa o anche una struttura
complessa, per questo motivo il valori vengono passati come puntatori
-\type{void}.
+\ctyp{void}.
L'indirizzo a cui il valore corrente del parametro deve essere letto è
specificato da \param{oldvalue}, e lo spazio ivi disponibile è specificato da
accessibili i vari parametri a qualunque comando di shell e di permettere la
navigazione dell'albero dei valori.
-Alcune delle corrispondenze con i valori di \func{sysctl} sono riportate nei
-commenti in \file{linux/sysctl.h}, la informazione disponibile in
-\file{/proc/sys} è riportata inoltre nella documentazione inclusa nei sorgenti
-del kernel, nella directory \file{Documentation/sysctl}.
+Alcune delle corrispondenze dei file presenti in \file{/proc/sys} con i valori
+di \func{sysctl} sono riportate nei commenti del codice che può essere trovato
+in \file{linux/sysctl.h},\footnote{indicando un file di definizioni si fa
+ riferimento alla directory standard dei file di include, che in ogni
+ distribuzione che si rispetti è \file{/usr/include}.} la informazione
+disponibile in \file{/proc/sys} è riportata inoltre nella documentazione
+inclusa nei sorgenti del kernel, nella directory \file{Documentation/sysctl}.
+
+Ma oltre alle informazioni ottenibili da \func{sysctl} dentro \file{proc}
+sono disponibili moltissime altre informazioni, fra cui ad esempio anche
+quelle fornite da \func{uname} (vedi \secref{sec:sys_config}) che sono
+mantenute nei file \file{ostype}, \file{hostname}, \file{osrelease},
+\file{version} e \file{domainname} di \file{/proc/kernel/}.
+
\subsection{La gestione delle proprietà dei filesystem}
occorre prima rendere disponibile al sistema il filesystem su cui essi sono
memorizzati; l'operazione di attivazione del filesystem è chiamata
\textsl{montaggio}, per far questo in Linux\footnote{la funzione è specifica
- di Linux e non è portabile} si usa la funzione \func{mount} il cui prototipo
+ di Linux e non è portabile.} si usa la funzione \func{mount} il cui prototipo
è:
\begin{prototype}{sys/mount.h}
{mount(const char *source, const char *target, const char *filesystemtype,
\item[\macro{EINVAL}] il device \param{source} presenta un
\textit{superblock} non valido, o si è cercato di rimontare un filesystem
non ancora montato, o di montarlo senza che \param{target} sia un
- \type{mount point} o di spostarlo quando \param{target} non è un
- \type{mount point} o è \file{/}.
+ \textit{mount point} o di spostarlo quando \param{target} non è un
+ \textit{mount point} o è \file{/}.
\item[\macro{EACCES}] non si ha il permesso di accesso su uno dei componenti
del pathname, o si è cercato di montare un filesystem disponibile in sola
lettura senza averlo specificato o il device \param{source} è su un
valori riportati in \ntab.
\begin{table}[htb]
+ \footnotesize
\centering
\begin{tabular}[c]{|l|r|l|}
\hline
specificate dagli altri bit), anche in questo caso il valore di \param{source}
viene ignorato.
-
Una volta che non si voglia più utilizzare un certo filesystem è possibile
\textsl{smontarlo} usando la funzione \func{umount}, il cui prototipo è:
\begin{prototype}{sys/mount.h}{umount(const char *target)}
\macro{ENAMETOOLONG}, \macro{ENOENT} o \macro{ELOOP}.}
\end{prototype}
\noindent la funzione prende il nome della directory su cui il filesystem è
-montato e non il file o il dispositivo che è stato montato\footnote{questo è
+montato e non il file o il dispositivo che è stato montato,\footnote{questo è
vero a partire dal kernel 2.3.99-pre7, prima esistevano due chiamate
separate e la funzione poteva essere usata anche specificando il file di
- dispositivo.}, in quanto con il kernel 2.4.x è possibile montare lo stesso
+ dispositivo.} in quanto con il kernel 2.4.x è possibile montare lo stesso
dispositivo in più punti. Nel caso più di un filesystem sia stato montato
sullo stesso \textit{mount point} viene smontato quello che è stato montato
-per ultimo.
+per ultimo.
Si tenga presente che la funzione fallisce quando il filesystem è
\textsl{occupato}, questo avviene quando ci sono ancora file aperti sul
evitando l'errore di \macro{EBUSY}. In tutti i casi prima dello smontaggio
viene eseguita una sincronizzazione dei dati.
-Altre due funzioni specifiche di Linux\footnote{esse si trovano anche su BSD,
- ma con una struttura diversa}, utili per ottenere in maniera diretta
+Altre due funzioni specifiche di Linux,\footnote{esse si trovano anche su BSD,
+ ma con una struttura diversa.} utili per ottenere in maniera diretta
informazioni riguardo al filesystem su cui si trova un certo file, sono
\func{statfs} e \func{fstatfs}, i cui prototipi sono:
\begin{functions}
- \headdecl{sys/vfs.h} \funcdecl{int statfs(const char *path, struct statfs
- *buf)} \funcdecl{int fstatfs(int fd, struct statfs *buf)} Restituisce in
- \param{buf} le informazioni relative al filesystem su cui è posto il file
- specificato.
+ \headdecl{sys/vfs.h}
+ \funcdecl{int statfs(const char *path, struct statfs *buf)}
+
+ \funcdecl{int fstatfs(int fd, struct statfs *buf)}
+
+ Restituisce in \param{buf} le informazioni relative al filesystem su cui è
+ posto il file specificato.
- \bodydesc{Li funzioni restituiscono 0 in caso di successo e -1 in caso di
+ \bodydesc{Le funzioni ritornano 0 in caso di successo e -1 in caso di
errore, nel qual caso \var{errno} viene settato ai valori:
\begin{errlist}
\item[\macro{ENOSYS}] il filesystem su cui si trova il file specificato non
Queste funzioni permettono di ottenere una serie di informazioni generali
riguardo al filesystem su cui si trova il file specificato; queste vengono
-restituite una struttura \param{buf} definita come:
-\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+restituite una struttura \param{buf} di tipo \type{statfs} definita come in
+\ref{fig:sys_statfs}, ed i campi che sono indefiniti per il filesystem in
+esame sono settati a zero. I valori del campo \var{f\_type} sono definiti per
+i vari filesystem nei relativi file di header dei sorgenti del kernel da
+costanti del tipo \macro{XXX\_SUPER\_MAGIC}, dove \macro{XXX} in genere è il
+nome del filesystem stesso.
+
+\begin{figure}[!htb]
+ \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_spare[6]; /* riservati per uso futuro */
};
\end{lstlisting}
-ed i campi che sono indefiniti per il filesystem in esame sono settati a zero.
-I valori del campo \var{f\_type} sono definiti per i vari filesystem nei
-relativi file di header dei sorgenti del kernel da costanti del tipo
-\macro{XXX\_SUPER\_MAGIC}, dove \macro{XXX} in genere è il nome del filesystem
-stesso.
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \var{statfs}.}
+ \label{fig:sys_statfs}
+\end{figure}
+
Le \acr{glibc} provvedono infine una serie di funzioni per la gestione dei due
file standard \file{/etc/fstab} e \file{/etc/mtab}, che convenzionalmente sono
effettua il montaggio di un filesystem; in realtà in questi casi è molto più
semplice invocare direttamente il programma \cmd{mount}, per cui ne
tralasceremo la trattazione, rimandando al manuale delle \acr{glibc}
-\cite{libc} per la documentazione completa.
+\cite{glibc} per la documentazione completa.
\subsection{La gestione di utenti e gruppi}
oggi la maggior parte delle distribuzioni di Linux usa la libreria PAM (sigla
che sta \textit{Pluggable Authentication Method}) che permette di separare
completamente i meccanismi di gestione degli utenti (autenticazione,
-riconoscimeto, ecc.) dal
+riconoscimento, ecc.) dalle modalità in cui i relativi dati vengono mantenuti.
+
+In questo paragrafo ci limiteremo comunque alle funzioni classiche per la
+lettura delle informazioni relative a utenti e gruppi previste dallo standard
+POSIX.1, che fanno riferimento a quanto memorizzato nei due file appena
+citati, il cui formato è descritto dalle relative pagine del manuale (cioè
+\cmd{man 5 passwd} e \cmd{man 5 group}).
+
+Per leggere le informazioni relative ad un utente si possono usare due
+funzioni, \func{getpwuid} e \func{getpwnam}, i cui prototipi sono:
+\begin{functions}
+ \headdecl{pwd.h}
+ \headdecl{sys/types.h}
+ \funcdecl{struct passwd *getpwuid(uid\_t uid)}
+
+ \funcdecl{struct passwd *getpwnam(const char *name)}
+
+ Restituiscono le informazioni relative all'utente specificato.
+
+ \bodydesc{Le funzioni ritornano il puntatore alla struttura contenente le
+ informazioni in caso di successo e \macro{NULL} nel caso non sia stato
+ trovato nessun utente corrispondente a quanto specificato.}
+\end{functions}
+
+Le due funzioni forniscono le informazioni memorizzate nel database degli
+utenti (che nelle versioni più recenti possono essere ottenute attraverso PAM)
+relative all'utente specificato attraverso il suo \acr{uid} o il nome di
+login. Entrambe le funzioni restituiscono un puntatore ad una struttura di
+tipo \type{passwd} la cui definizione (anch'essa eseguita in \file{pwd.h}) è
+riportata in \figref{fig:sys_passwd_struct}, dove è pure brevemente illustrato
+il significato dei vari campi.
+
+\begin{figure}[!htb]
+ \footnotesize
+ \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+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}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \var{passwd} contenente le informazioni relative ad un
+ utente del sistema.}
+ \label{fig:sys_passwd_struct}
+\end{figure}
+
+La struttura usata da entrambe le funzioni è allocata staticamente, per questo
+motivo viene sovrascritta ad ogni nuova invocazione, così come le stringhe a
+cui essa fa riferimento. Ovviamente queste funzioni non sono rientranti, ne
+esistono quindi anche due versioni alternative (denotate dalla solita
+estensione \code{\_r}), i cui prototipi sono:
+\begin{functions}
+ \headdecl{pwd.h}
+
+ \headdecl{sys/types.h}
+
+ \funcdecl{struct passwd *getpwuid\_r(uid\_t uid, struct passwd *password,
+ char *buffer, size\_t buflen, struct passwd **result)}
+
+ \funcdecl{struct passwd *getpwnam\_r(const char *name, struct passwd
+ *password, char *buffer, size\_t buflen, struct passwd **result)}
+
+ Restituiscono le informazioni relative all'utente specificato.
+
+ \bodydesc{Le funzioni ritornano 0 in caso di successo e un codice d'errore
+ altrimenti, nel qual caso \var{errno} sarà settato opportunamente.}
+\end{functions}
+
+In questo caso l'uso è molto più complesso, in quanto bisogna prima allocare
+la memoria necessaria a contenere le informazioni. In particolare i valori
+della struttura \var{passwd} saranno restituiti all'indirizzo \param{password}
+mentre la memoria allocata all'indirizzo \param{buffer}, per un massimo di
+\param{buflen} byte, sarà utilizzata per contenere le stringhe puntate dai
+campi di \param{password}; infine all'indirizzo puntato da \param{result}
+viene restituito il puntatore ai dati ottenuti, cioè \param{buffer} nel caso
+l'utente esista, o \macro{NULL} altrimenti. Qualora i dati non possano essere
+contenuti in \param{buflen} byte la funzione fallirà restituendo
+\macro{ERANGE} (e \param{result} sarà comunque settato a \macro{NULL}).
+
+Del tutto analoghe alle precedenti sono le funzioni \func{getgrnam} e
+\func{getgrgid} (e le relative analoghe rientranti con la stessa estensione
+\code{\_r}) che permettono di leggere le informazioni relative ai gruppi, i
+loro prototipi sono:
+\begin{functions}
+ \headdecl{grp.h}
+ \headdecl{sys/types.h}
+
+ \funcdecl{struct group *getgrgid(gid\_t gid)}
+
+ \funcdecl{struct group *getgrnam(const char *name)}
+
+ \funcdecl{struct group *getpwuid\_r(gid\_t gid, struct group *password,
+ char *buffer, size\_t buflen, struct group **result)}
+
+ \funcdecl{struct group *getpwnam\_r(const char *name, struct group
+ *password, char *buffer, size\_t buflen, struct group **result)}
+
+ Restituiscono le informazioni relative al gruppo specificato.
+
+ \bodydesc{Le funzioni ritornano 0 in caso di successo e un codice d'errore
+ altrimenti, nel qual caso \var{errno} sarà settato opportunamente.}
+\end{functions}
+Il comportamento di tutte queste funzioni è assolutamente identico alle
+precedenti che leggono le informazioni sugli utenti, l'unica differenza è che
+in questo caso le informazioni vengono restituite in una struttura di tipo
+\type{group}, la cui definizione è riportata in \figref{fig:sys_group_struct}.
+\begin{figure}[!htb]
+ \footnotesize
+ \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+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}
+ \end{minipage}
+ \normalsize
+ \caption{La struttura \var{group} contenente le informazioni relative ad un
+ gruppo del sistema.}
+ \label{fig:sys_group_struct}
+\end{figure}
+
+Le funzioni viste finora sono in grado di leggere le informazioni sia dal file
+delle password in \file{/etc/passwd} che con qualunque altro metodo sia stato
+utilizzato per mantenere il database degli utenti. Non permettono però di
+settare direttamente le password; questo è possibile con un'altra interfaccia
+al database degli utenti, derivata da SVID, che però funziona soltanto con un
+database che sia tenuto su un file che abbia il formato classico di
+\file{/etc/passwd}.
+
+Dato che ormai la gran parte delle distribuzioni di Linux utilizzano PAM, che
+come minimo usa almeno le \textit{shadow password}, quindi con delle modifiche
+rispetto al formato classico di \file{/etc/passwd}, le funzioni che danno la
+capacità scrivere delle voci nel database (\func{putpwent} e \func{putgrent})
+non permettono di specificarle in maniera completa. Per questo motivo l'uso di
+queste funzioni è deprecato in favore dell'uso di PAM, per cui ci limitiamo a
+elencarle in \tabref{tab:sys_passwd_func}, rimandando chi fosse interessato
+alle man page e al manuale delle \acr{glibc} per i dettagli del funzionamento.
+
+\begin{table}[htb]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Funzione} & \textbf{Significato}\\
+ \hline
+ \hline
+ \func{fgetpwent} & Legge una voce dal database utenti da un file
+ specificato aprendolo la prima volta.\\
+ \func{fgetpwent\_r}& Come la precedente, ma rientrante.\\
+ \func{getpwent} & Legge una voce dal database utenti (da
+ \file{/etc/passwd}) aprendolo la prima volta.\\
+ \func{getpwent\_r} & Come la precedente, ma rientrante.\\
+ \func{setpwent} & Ritorna all'inizio del database.\\
+ \func{putpwent} & Immette una voce nel database utenti.\\
+ \func{endpwent} & Chiude il database degli utenti.\\
+ \func{fgetgrent} & Legge una voce dal database dei gruppi da un file
+ specificato aprendolo la prima volta.\\
+ \func{fgetgrent\_r}& Come la precedente, ma rientrante.\\
+ \func{getgrent} & Legge una voce dal database dei gruppi (da
+ \file{/etc/passwd}) aprendolo la prima volta.\\
+ \func{getgrent\_r} & Come la precedente, ma rientrante.\\
+ \func{setgrent} & Immette una voce nel database dei gruppi.\\
+ \func{putgrent} & Immette una voce nel database dei gruppi.\\
+ \func{endgrent} & Chiude il database dei gruppi.\\
+ \hline
+ \end{tabular}
+ \caption{Funzioni per la manipolazione dei campi di un file usato come
+ database di utenti e gruppi nel formato di \file{/etc/passwd} e
+ \file{/etc/groups}.}
+ \label{tab:sys_passwd_func}
+\end{table}
+
+Un altro insieme di funzioni utili è quello che permette di accedere ai dati
+del database di \textit{accounting} degli utenti, che mantiene la traccia di
+chi si è collegato al sistema e di che è correntemente collegato, insieme alle
+informazioni, per ciascun terminale, di chi ci è collegato, da che ora,
+dell'\acr{uid} della shell di login, ed una serie di altre informazioni
+relativa al sistema come il run-level, l'orario dell'ultimo riavvio, ed altre.
+
+Le informazioni sono tenute nei due file \file{/var/run/utmp} (per chi sta
+utilizzando il sistema al momento corrente) e \file{/var/log/wtmp} (per la
+storia dei login precedenti). Questi file non devono mai essere letti
+direttamente, ma le informazioni che contengono possono essere ricavate
+attraverso le opportune funzioni di libreria. Queste sono analoghe alle
+precedenti per il database delle password, solo che la struttura del database
+è molto più complessa, dato che contiene vari tipi di informazione.
+
+Le prime tre funzioni, \func{utmpname}, \func{setutent} e \func{endutent},
+servono a aprire e chiudere il database, e a specificare il file su cui esso è
+mantenuto (in caso questo non venga specificato viene usato il valore standard
+\macro{\_PATH\_UTMP} che è definito in \file{paths.h}. Il loro prototipi sono:
+\begin{functions}
+ \headdecl{utmp.h}
+
+ \funcdecl{void utmpname(const char *file)} Specifica il file da usare come
+ database di \textit{accounting}.
+
+ \funcdecl{void setutent(void)} Apre il file del database di
+ \textit{accounting}, posizionandosi al suo inizio.
+
+ \funcdecl{void endutent(void)} Chiude il file del database di
+ \textit{accounting}.
+
+ \bodydesc{Le funzioni non ritornano codici di errore.}
+\end{functions}
+
+Una volta aperto il file si può eseguire una scansione leggendo o scrivendo
+una voce con le funzioni \func{getutent}, \func{getutid}, \func{getutline} e
+\func{pututline}, i cui prototipi sono:
+\begin{functions}
+ \headdecl{utmp.h}
+
+ \funcdecl{struct utmp *getutent(void)}
+ Legge una voce dal dalla posizione corrente nel database.
+
+ \funcdecl{struct utmp *getutid(struct utmp *ut)}
+ Esegue una ricerca dalla posizione corrente sulla base del contenuto di
+ \param{ut}.
+
+ \funcdecl{struct utmp *getutline(struct utmp *ut)}
+ Ricerca nel database la prima voce corrispondente ad un processo sulla linea
+ di terminale specificata tramite \param{ut}.
+
+ \funcdecl{struct utmp *pututline(struct utmp *ut)}
+ Scrive una voce nel database.
+
+ \bodydesc{Le funzioni ritornano il puntatore ad una struttura \var{utmp} in
+ caso di successo e \macro{NULL} in caso di errore.}
+\end{functions}
+
+Tutte queste funzioni fanno riferimento ad una struttura di tipo \var{utmp},
+la cui definizione in Linux è riportata in \secref{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}[labelstep=0]{}%,frame=,indent=1cm]{}
+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 \var{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 la voce relativa ad uno specifico tipo di
+login o di runlevel, a seconda del valore del campo \var{ut\_type}
+dell'argomento \param{ut}; questo può assumere i valori riportati in
+
+
+\begin{table}[htb]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Funzione} & \textbf{Significato}\\
+ \hline
+ \hline
+ \macro{EMPTY} & Non contiene informazioni valide. \\
+ \macro{RUN\_LVL} & Identica il runlevel del sistema. \\
+ \macro{BOOT\_TIME} & Identifica il tempo di avvio del sistema \\
+ \macro{OLD\_TIME} & Identifica quando è stato modificato l'orogio di
+ sistema. \\
+ \macro{NEW\_TIME} & Identifica da qaunto è stato modificato il
+ sistema. \\
+ \macro{INIT\_PROCESS} & Identifica un processo lanciato ad \cmd{init}. \\
+ \macro{LOGIN\_PROCESS}& Identifica un processo di login. \\
+ \macro{USER\_PROCESS} & Identifica un processo utente. \\
+ \macro{DEAD\_PROCESS} & Identifica un processo terminato. \\
+ \macro{ACCOUNTING} & ??? \\
+ \hline
+ \end{tabular}
+ \caption{Classificazione delle voci del database di accounting a seconda dei
+ possibili valori del campo \var{ut\_type}.}
+ \label{tab:sys_ut_type}
+\end{table}
-Lo standard POSIX.1 definisce una serie di funzioni
In questa sezione esamineremo le funzioni che permettono di esaminare e
controllare come le varie risorse del sistema (CPU, memoria, ecc.) vengono
-utilizzate dai processi, e le modalità con cui è possibile imporre dei limiti
-sul loro utilizzo.
+utilizzate dai singoli processi, e le modalità con cui è possibile imporre dei
+limiti sul loro utilizzo.
-
\subsection{Limiti sulle risorse}
\label{sec:sys_resource_limit}
\footnotesize
\centering
\begin{minipage}[c]{15cm}
- \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+ \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
struct rusage {
struct timeval ru_utime; /* user time used */
struct timeval ru_stime; /* system time used */
tempi nelle differenti rappresentazioni che vengono utilizzate.
-\subsection{La misura del tempo in unix}
+\subsection{La misura del tempo in Unix}
\label{sec:sys_unix_time}
-Storicamente i sistemi unix-like hanno sempre mantenuto due distinti
-valori per i tempi all'interno del sistema, essi sono rispettivamente
-chiamati \textit{calendar time} e \textit{process time}, secondo le
-definizioni:
+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
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}: talvolta anche detto tempo di CPU. Viene misurato
+\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 è
+ 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});
\secref{sec:sys_limits}).
\end{itemize}
-In genere si usa il \textit{calendar time} per tenere le date dei file e le
-informazioni analoghe che riguardano i tempi di ``orologio'', usati ad esempio
-per i demoni che compiono lavori amministrativi ad ore definite, come
-\cmd{cron}. Di solito questo vene convertito automaticamente dal valore in UTC
-al tempo locale, utilizzando le opportune informazioni di localizzazione
+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},
+che vengono usati ad esempio per i demoni che compiono lavori amministrativi
+ad ore definite, come \cmd{cron}.
+
+Di solito questo tempo viene convertito automaticamente dal valore in UTC al
+tempo locale, utilizzando le opportune informazioni di localizzazione
(specificate in \file{/etc/timezone}). E da tenere presente che questo tempo è
-mantenuto dal sistema e non corrisponde all'orologio hardware del calcolatore.
+mantenuto dal sistema e non è detto che corrisponda al tempo tenuto
+dall'orologio hardware del calcolatore.
-Il \textit{process time} di solito si esprime in secondi e viene usato appunto
-per tenere conto dei tempi di esecuzione dei processi. Per ciascun processo il
-kernel tiene tre di questi tempi:
-\begin{itemize*}
-\item \textit{clock time}
-\item \textit{user time}
-\item \textit{system time}
-\end{itemize*}
-il primo è il tempo ``reale'' (viene anche chiamato \textit{wall clock time})
-dall'avvio del processo, e misura il tempo trascorso fino alla sua
-conclusione; chiaramente un tale tempo dipende anche dal carico del sistema e
-da quanti altri processi stavano girando nello stesso periodo. Il secondo
-tempo è quello che la CPU ha speso nell'esecuzione delle istruzioni del
-processo in user space. Il terzo è il tempo impiegato dal kernel per eseguire
-delle system call per conto del processo medesimo (tipo quello usato per
-eseguire una \func{write} su un file). In genere la somma di user e system
-time viene chiamato \textit{CPU time}.
+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:
+\begin{description*}
+\item[\textit{clock time}]: il tempo \textsl{reale} (viene chiamato anche
+ \textit{wall clock time}) passato dall'avvio del processo. Chiaramente tale
+ tempo dipende anche dal carico del sistema e da quanti altri processi
+ stavano girando nello stesso periodo.
+\item[\textit{user time}]: il tempo che la CPU ha impiegato nell'esecuzione
+ delle istruzioni del processo in user space.
+\item[\textit{system time}]: il tempo che la CPU ha impiegato nel kernel per
+ eseguire delle system call per conto del processo.
+\end{description*}
+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}.
che c'è stato un errore, non il tipo di errore.
Per riportare il tipo di errore il sistema usa la variabile globale
-\var{errno}\footnote{L'uso di una variabile globale può comportare alcuni
+\var{errno},\footnote{L'uso di una variabile globale può comportare alcuni
problemi (ad esempio nel caso dei thread) ma lo standard ISO C consente
anche di definire \var{errno} come un \textit{modifiable lvalue}, quindi si
può anche usare una macro, e questo è infatti il modo usato da Linux per
- renderla locale ai singoli thread.}, definita nell'header \file{errno.h}; la
-variabile è in genere definita come \type{volatile} dato che può essere
-cambiata in modo asincrono da un segnale (per una descrizione dei segnali si
-veda \secref{cha:signals}), ma dato che un manipolatore di segnale scritto
-bene salva e ripristina il valore della variabile, di questo non è necessario
-preoccuparsi nella programmazione normale.
+ renderla locale ai singoli thread.} definita nell'header \file{errno.h}; la
+variabile è in genere definita come \ctyp{volatile} dato che può essere
+cambiata in modo asincrono da un segnale (si veda \ref{sec:sig_sigchld} per un
+esempio, ricordando quanto trattato in \ref{sec:proc_race_cond}), ma dato che
+un manipolatore di segnale scritto bene salva e ripristina il valore della
+variabile, di questo non è necessario preoccuparsi nella programmazione
+normale.
I valori che può assumere \var{errno} sono riportati in \capref{cha:errors},
nell'header \file{errno.h} sono anche definiti i nomi simbolici per le
essere modificata dal programma e che è utilizzabile solo fino ad una chiamata
successiva a \func{strerror}; nel caso si usino i thread è
provvista\footnote{questa funzione è una estensione GNU, non fa parte dello
- standard POSIX} una versione apposita:
+ standard POSIX.} una versione apposita:
\begin{prototype}{string.h}
{char *strerror\_r(int errnum, char *buff, size\_t size)}
Analoga a \func{strerror} ma ritorna il messaggio in un buffer
che utilizza un buffer che il singolo thread deve allocare, per evitare i
problemi connessi alla condivisione del buffer statico. Infine, per completare
la caratterizzazione dell'errore, si può usare anche la variabile
-globale\footnote{anche questa è una estensione GNU}
+globale\footnote{anche questa è un'estensione GNU.}
\var{program\_invocation\_short\_name} che riporta il nome del programma
attualmente in esecuzione.