X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=system.tex;h=40ec611f1ab333141f99d5893149cba116a13fee;hp=657c0d645cc5bada0c1e7b00bf16aa52ef387ce4;hb=989ba37f5c3e6190b8f500db103529c3253ebb4d;hpb=3425ef5d361d8af2b3d61a3f43ae36f032f4524c diff --git a/system.tex b/system.tex index 657c0d6..40ec611 100644 --- a/system.tex +++ b/system.tex @@ -1,4 +1,4 @@ -\chapter{La gestione del sistema, delle risorse, e degli errori} +fo \chapter{La gestione del sistema, delle risorse, e degli errori} \label{cha:system} In questo capitolo tratteremo varie interfacce che attengono agli aspetti più @@ -1225,18 +1225,18 @@ eseguire una ricerca. \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. */ + 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} @@ -1340,75 +1340,303 @@ poi aggiunge chiamando \func{updwtmp}. \section{Limitazione ed uso delle risorse} \label{sec:sys_res_limits} -In questa sezione esamineremo le funzioni che permettono di esaminare e -controllare come le varie risorse del sistema (CPU, memoria, ecc.) vengono -utilizzate dai singoli processi, e le modalità con cui è possibile imporre dei -limiti sul loro utilizzo. +Dopo aver esaminato le funzioni che permettono di controllare le varie +caratteristiche, capacità e limiti del sistema a livello globale, in questa +sezione tratteremo le varie funzioni che vengono usate per quantificare le +risorse (CPU, memoria, ecc.) utilizzate da ogni singolo processo e quelle che +permettono di imporre a ciascuno di essi vincoli e limiti di utilizzo. \subsection{L'uso delle risorse} \label{sec:sys_resource_use} +Come abbiamo accennato in \secref{sec:proc_wait4} le informazioni riguardo +l'utilizzo delle risorse da parte di un processo è mantenuto in una struttura +di tipo \code{struct }\type{rusage}, la cui definizione (che si trova in +\file{sys/resource.h}) è riportata in \figref{fig:sys_rusage_struct}. +\begin{figure}[!htb] + \footnotesize + \centering + \begin{minipage}[c]{15cm} + \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{} +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} + \end{minipage} + \normalsize + \caption{La struttura \var{rusage} per la lettura delle informazioni dei + delle risorse usate da un processo.} + \label{fig:sys_rusage_struct} +\end{figure} -\subsection{Limiti sulle risorse} -\label{sec:sys_resource_limit} +La struttura è ripresa da BSD 4.3, ma attualmente (con i kernel della serie +2.4.x) i soli campi che sono mantenuti sono: \var{ru\_utime}, \var{ru\_stime}, +\var{ru\_minflt}, \var{ru\_majflt}, e \var{ru\_nswap}. I primi due indicano +rispettivamente il tempo impiegato dal processo nell'eseguire le istruzioni in +user space, e quello impiegato dal kernel nelle system call eseguite per conto +del processo. + +Gli altri tre campi servono a quantificare l'uso della memoria virtuale e +corrispondono rispettivamente al numero di \textit{page fault}\index{page + fault} (vedi \secref{sec:proc_mem_gen}) avvenuti senza richiedere I/O (i +cosiddetti \textit{minor page fault}), a quelli che invece han richiesto I/O +(detti invece \textit{major page fault}) ed al numero di volte che il processo +è stato completamente tolto dalla memoria per essere inserito nello swap. + +In genere includere esplicitamente \file{} non è più necessario, +ma aumenta la portabilità, e serve comunque quando, come nella maggior parte +dei casi, si debba accedere ai campi di \var{rusage} relativi ai tempi di +utilizzo del processore, che sono definiti come \code{struct }\type{timeval}. + + +Questa è la stessa struttura utilizzata da \func{wait4} per ricavare la +quantità di risorse impiegato dal processo di cui si è letto lo stato di +terminazione, ma essa può anche essere letta direttamente utilizzando la +funzione \func{getrusage}, il cui prototipo è: +\begin{functions} + \headdecl{sys/time.h} + \headdecl{sys/resource.h} + \headdecl{unistd.h} + + \funcdecl{int getrusage(int who, struct rusage *usage)} + Legge la quantità di risorse usate da un processo. -\subsection{Le risorse di memoria} -\label{sec:sys_memory_res} + \bodydesc{La funzione ritorna 0 in caso di successo e -1 in caso di errore, + nel qual caso \var{errno} può essere \macro{EINVAL} o \macro{EFAULT}.} +\end{functions} +L'argomento \param{who} permette di specificare il processo di cui si vuole +leggere l'uso delle risorse; esso può assumere solo i due valori +\macro{RUSAGE\_SELF} per indicare il processo corrente e +\macro{RUSAGE\_CHILDREN} per indicare l'insieme dei processi figli di cui si è +ricevuto lo stato di terminazione. -\subsection{Le risorse di processore} -\label{sec:sys_cpu_load} +\subsection{Limiti sulle risorse} +\label{sec:sys_resource_limit} +Come accennato nell'introduzione oltre a leggere l'uso delle risorse da parte +di un processo si possono anche imporre dei limiti sulle sue capacità. Ogni +processo ha in generale due limiti associati ad ogni risorsa; questi sono +detti il \textsl{limite corrente} (o \textit{current limit}) che esprime il +valore che attualmente il processo non può superare, ed il \textsl{limite + massimo} (o \textit{maximum limit}) che esprime il valore massimo che può +assumere il \textsl{limite corrente}. + +In generale il primo viene chiamato un limite \textsl{soffice} (o \textit{soft + limit}) dato che il suo valore può essere aumentato, mentre il secondo è +detto \textsl{duro} (o \textit{hard limit}), in quanto un processo normale non +può modificarne il valore. Il valore di questi limiti è mantenuto in una +struttura \var{rlimit}, la cui definizione è riportata in +\figref{fig:sys_rlimit_struct}, ed i cui campi corrispondono appunto a limite +corrente e massimo. \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{} -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 */ -}; + struct rlimit { + rlim_t rlim_cur; + rlim_t rlim_max; + }; \end{lstlisting} \end{minipage} \normalsize - \caption{La struttura \var{rusage} per la lettura delle informazioni dei + \caption{La struttura \var{rlimit} per impostare i limiti di utilizzo delle risorse usate da un processo.} - \label{fig:sys_rusage_struct} + \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 far leggere o settare +i limiti di utilizzo delle risorse da parte di un processo le \acr{glibc} +prevedono due funzioni, \func{getrlimit} e \func{setrlimit}, i cui prototipi +sono: +\begin{functions} + \headdecl{sys/time.h} + \headdecl{sys/resource.h} + \headdecl{unistd.h} + + \funcdecl{int getrlimit(int resource, struct rlimit *rlim)} + + Legge il limite corrente per la risorsa \param{resource}. + + \funcdecl{int setrlimit(int resource, const struct rlimit *rlim)} + + Setta il limite per la risorsa \param{resource}. + + \bodydesc{Le funzioni ritornano 0 in caso di successo e -1 in caso di + errore, nel qual caso \var{errno} viene settata ai valori: + \begin{errlist} + \item[\macro{INVAL}] I valori per \param{resource} non sono validi. + \item[\macro{EPERM}] Un processo senza i privilegi di amministratore ha + cercato di innalzare i propri limiti. + \end{errlist} + ed \macro{EFAULT}.} +\end{functions} + +Entrambe le funzioni permettono di specificare su quale risorsa si vuole +operare attraverso \param{resource}, i cui possibili valori sono elencati in +\secref{tab:sys_rlimit_values}, e utilizzano una struttura \var{rlimit} per +specificarne i valori. + +\begin{table}[htb] + \footnotesize + \centering + \begin{tabular}[c]{|l|p{12cm}|} + \hline + \textbf{Valore} & \textbf{Significato}\\ + \hline + \hline + \macro{RLIMIT\_CPU} & Il massimo tempo di CPU che il processo può + usare. Il superamento del limite comporta + l'emissione di un segnale di \macro{SIGXCPU}.\\ + \macro{RLIMIT\_FSIZE} & La massima dimensione di un file che un processo + può usare. Se il processo cerca di scrivere + oltre questa dimensione riceverà un segnale di + \macro{SIGXFSZ}.\\ + \macro{RLIMIT\_DATA} & La massima dimensione della memoria dati di un + processo. Il tentatico di allocare più memoria + causa il fallimento della funzione di + allocazione. \\ + \macro{RLIMIT\_STACK} & La massima dimensione dello stack del + processo. Se il processo esegue operazioni che + estendano lo stack oltre questa dimensione + riceverà un segnale di \macro{SIGSEGV}.\\ + \macro{RLIMIT\_CORE} & La massima dimensione di un file di \textit{core + dump} creato da un processo. Nel caso le + dimensioni dovessero essere maggiori il file non + verrebbe generato.\footnotemark\\ + \macro{RLIMIT\_RSS} & L'ammontare massimo di memoria fisica dato al + processo. Il limite è solo una indicazione per + il kernel, qualora ci fosse un surplus di + memoria questa verrebbe assegnata.\\ + \macro{RLIMIT\_NPROC} & Il numero massimo di processi che possono essere + creati sullo stesso user id. Se il limite viene + raggiunto \func{fork} fallirà con un + \macro{EAGAIN}.\\ + \macro{RLIMIT\_NOFILE} & Il numero massimo di file che il processo può + aprire. L'apertura di un ulteriore file fallirà + con un errore \macro{EMFILE}.\\ + \macro{RLIMIT\_MEMLOCK}& L'ammontare massimo di memoria che può essere + bloccata (vedi \secref{sec:proc_mem_lock}).\\ + \macro{RLIMIT\_AS} & La dimensione massima di tutta la memoria che il + processo può ottenere. Se il processo tenta di + allocarne di più funzioni come \func{brk}, + \func{malloc} o \func{mmap} falliranno. \\ + \hline + \end{tabular} + \caption{Valori possibili dell'argomento \param{resource} delle funzioni + \func{getrlimit} e \func{setrlimit}.} + \label{tab:sys_rlimit_values} +\end{table} + +\footnotetext{Settare questo limite a zero è la maniera più semplice per + evitare la creazione di \file{core} file.} + +È inoltre definita la costante \macro{RLIM\_INFINITY} che permette di +sbloccare l'uso di una risorsa, ma solo un processo con i privilegi di +amministratore può innalzare un limite al di sopra del valore corrente del +limite massimo. Si tenga conto infine che tutti i limiti vengono ereditati dal +processo padre attraverso una \func{fork} (vedi \secref{sec:proc_fork}) e +mantenuti attraverso una \func{exec} (vedi \secref{sec:proc_exec}). + + +\subsection{Le risorse relative alla memoria} +\label{sec:sys_memory_res} + +La gestione della memoria è già stata affrontata in dettaglio in +\secref{sec:proc_memory}; abbiamo visto allora che il kernel provvede il +meccanismo della memoria virtuale attraverso la divisione della memoria fisica +in pagine. + +In genere questo è del tutto trasparente al singolo processo, ma in certi +casi, come per l'I/O mappato in memoria (vedi \ref{sec:file_memory_map}) che +usa lo stesso meccanismo per accedere ai file, è necessario conoscere le +dimensioni delle pagine usate dal kernel. Lo stesso vale quando si vuole +gestire in maniera ottimale l'interazione della memoria allocata con il +meccanismo della paginazione. + +Di solito la dimensione delle pagine di memoria è fissata dall'architettura +hardware, per cui in genere la dimensione delle pagine di memoria era una +costante definita in fase di compilazione, ma oggi alcune architetture (ad +esempio su Sun Sparc) permettono di variare questa dimensione, e non volendo +dover fornire binari diversi per ogni possibile modello, è necessario poter +utilizzare una funzione. + +In genere questa dimensione può essere ottenuta attraverso una chiamata a +\func{sysconf} come \func{sysconf(\_SC\_PAGESIZE)}, ma in BSD 4.2 è stata +introdotta una apposita funzione, \func{getpagesize}, che restituisce la +dimensione delle pagine di memoria; il suo prototipo è: +\begin{prototype}{unistd.h}{int getpagesize(void)} + Legge le dimensioni delle pagine di memoria. + + \bodydesc{La funzione ritorna la dimensione di una pagina in byte, e non + sono previsti errori.} +\end{prototype} + +La funzione è prevista in SVr4, 4.4BSD e SUSv2, anche se questo ultimo +standard la etichetta come obsoleta, mentre lo standard POSIX 1003.1-2001 la +ha eliminata. In Linux è implementata come una system call nelle architetture +in cui essa serve, in genere restituisce il valore del simbolo +\macro{PAGE\_SIZE} del kernel, anche se le versioni delle librerie del C +precedenti le \acr{glibc} 2.1 implementavano questa funzione restituendo un +valore statico. + +Le \acr{glibc} forniscono, come specifica estensione GNU, altre due funzioni, +\func{get\_phys\_pages} e \func{get\_avphys\_pages} che permettono di ottenere +informazioni riguardo la memoria; i loro prototipi sono: +\begin{functions} + \headdecl{sys/sysinfo.h} + + \funcdecl{long int get\_phys\_pages(void)} + + Legge il numero totale di pagine di memorie disponibili per il sistema. + + \funcdecl{long int get\_avphys\_pages(void)} + + Legge il numero. + + \bodydesc{} +\end{functions} + + + +\subsection{Le risorse di processore} +\label{sec:sys_cpu_load} + -\var{tms\_utime}, \var{tms\_stime}, \var{tms\_cutime}, \var{tms\_uetime} \section{La gestione dei tempi del sistema} \label{sec:sys_time} -In questa sezione tratteremo le varie funzioni per la gestione delle -date e del tempo in un sistema unix-like, e quelle per convertire i vari -tempi nelle differenti rappresentazioni che vengono utilizzate. +In questa sezione tratteremo le varie funzioni per la gestione delle date e +del tempo in un sistema unix-like, e quelle per convertire i vari tempi nelle +differenti rappresentazioni che vengono utilizzate. \subsection{La misura del tempo in Unix} @@ -1471,6 +1699,14 @@ nell'eseguire un certo processo e viene chiamato \textit{CPU time}. +\subsection{I tempi di processore} +\label{sec:sys_cpu_times} + + +\var{tms\_utime}, \var{tms\_stime}, \var{tms\_cutime}, \var{tms\_uetime} + + + \section{La gestione degli errori} \label{sec:sys_errors}