From b2fde72b2f308cb35873f1fd050501af6a742bc0 Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sat, 30 Aug 2008 22:10:21 +0000 Subject: [PATCH] Alcune indicizzazioni ulteriori, trattata _FORTIFY_SOURCE e messi ulteriori dettagli su alloca --- errors.tex | 4 +- fileadv.tex | 40 ++++++----- filedir.tex | 29 ++++---- filestd.tex | 56 ++++++++------- fileunix.tex | 28 ++++---- intro.tex | 127 +++++++++++++++++++-------------- ipc.tex | 94 +++++++++++++------------ network.tex | 11 +-- process.tex | 131 +++++++++++++++++++--------------- prochand.tex | 59 +++++++++------- session.tex | 6 +- signal.tex | 194 +++++++++++++++++++++++++++------------------------ sockctrl.tex | 50 ++++++------- socket.tex | 2 +- system.tex | 100 ++++++++++++++------------ thread.tex | 10 ++- 16 files changed, 515 insertions(+), 426 deletions(-) diff --git a/errors.tex b/errors.tex index 1b739be..41a3a1e 100644 --- a/errors.tex +++ b/errors.tex @@ -279,8 +279,8 @@ specificati nelle sezioni precedenti. avrebbe il blocco. \item \errcode{EFAULT} \textit{Bad address}. Una stringa passata come argomento è fuori dello spazio di indirizzi del processo, in genere questa - situazione provoca direttamente l'emissione di un segnale di \textit{segment - violation} (\const{SIGSEGV}). + situazione provoca direttamente l'emissione di un segnale di + \itindex{segment~violation} \textit{segment violation} (\const{SIGSEGV}). \item \errcode{EINVAL} \textit{Invalid argument}. Errore utilizzato per segnalare vari tipi di problemi dovuti all'aver passato un argomento sbagliato ad una funzione di libreria. diff --git a/fileadv.tex b/fileadv.tex index 88510e4..1c8cb6b 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -1764,11 +1764,12 @@ normalmente. In generale questa interfaccia è completamente astratta e può essere implementata sia direttamente nel kernel, che in user space attraverso l'uso -di thread. Per le versioni del kernel meno recenti esiste una implementazione -di questa interfaccia fornita delle \acr{glibc}, che è realizzata -completamente in user space, ed è accessibile linkando i programmi con la -libreria \file{librt}. Nelle versioni più recenti (a partire dalla 2.5.32) è -stato introdotto direttamente nel kernel un nuovo layer per l'I/O asincrono. +di \itindex{thread} \textit{thread}. Per le versioni del kernel meno recenti +esiste una implementazione di questa interfaccia fornita delle \acr{glibc}, +che è realizzata completamente in user space, ed è accessibile linkando i +programmi con la libreria \file{librt}. Nelle versioni più recenti (a partire +dalla 2.5.32) è stato introdotto direttamente nel kernel un nuovo layer per +l'I/O asincrono. Lo standard prevede che tutte le operazioni di I/O asincrono siano controllate attraverso l'uso di una apposita struttura \struct{aiocb} (il cui nome sta per @@ -1839,9 +1840,9 @@ quello che indica le modalit fig.~\ref{fig:sig_sigval}) come valore del campo \var{si\_value} di \struct{siginfo\_t}. \item[\const{SIGEV\_THREAD}] La notifica viene effettuata creando un nuovo - thread che esegue la funzione specificata da \var{sigev\_notify\_function} - con argomento \var{sigev\_value}, e con gli attributi specificati da - \var{sigev\_notify\_attribute}. + \itindex{thread} \textit{thread} che esegue la funzione specificata da + \var{sigev\_notify\_function} con argomento \var{sigev\_value}, e con gli + attributi specificati da \var{sigev\_notify\_attribute}. \end{basedescript} Le due funzioni base dell'interfaccia per l'I/O asincrono sono @@ -2232,14 +2233,15 @@ multiplo della dimensione di una pagina di memoria. \label{tab:file_mmap_prot} \end{table} -Il valore dell'argomento \param{prot} indica la protezione\footnote{in Linux - la memoria reale è divisa in pagine: ogni processo vede la sua memoria - attraverso uno o più segmenti lineari di memoria virtuale. Per ciascuno di - questi segmenti il kernel mantiene nella \itindex{page~table} \textit{page - table} la mappatura sulle pagine di memoria reale, ed le modalità di - accesso (lettura, esecuzione, scrittura); una loro violazione causa quella - che si chiama una \textit{segment violation}, e la relativa emissione del - segnale \const{SIGSEGV}.} da applicare al segmento di memoria e deve essere +Il valore dell'argomento \param{prot} indica la protezione\footnote{come + accennato in sez.~\ref{sec:proc_memory} in Linux la memoria reale è divisa + in pagine: ogni processo vede la sua memoria attraverso uno o più segmenti + lineari di memoria virtuale. Per ciascuno di questi segmenti il kernel + mantiene nella \itindex{page~table} \textit{page table} la mappatura sulle + pagine di memoria reale, ed le modalità di accesso (lettura, esecuzione, + scrittura); una loro violazione causa quella una \itindex{segment~violation} + \textit{segment violation}, e la relativa emissione del segnale + \const{SIGSEGV}.} da applicare al segmento di memoria e deve essere specificato come maschera binaria ottenuta dall'OR di uno o più dei valori riportati in tab.~\ref{tab:file_mmap_prot}; il valore specificato deve essere compatibile con la modalità di accesso con cui si è aperto il file. @@ -2298,9 +2300,9 @@ tab.~\ref{tab:file_mmap_flag}. un \const{SIGSEGV}.\\ \const{MAP\_LOCKED} & Se impostato impedisce lo swapping delle pagine mappate.\\ - \const{MAP\_GROWSDOWN} & Usato per gli \itindex{stack} stack. Indica - che la mappatura deve essere effettuata con gli - indirizzi crescenti verso il basso.\\ + \const{MAP\_GROWSDOWN} & Usato per gli \itindex{stack} \textit{stack}. + Indica che la mappatura deve essere effettuata + con gli indirizzi crescenti verso il basso.\\ \const{MAP\_ANONYMOUS} & La mappatura non è associata a nessun file. Gli argomenti \param{fd} e \param{offset} sono ignorati.\footnotemark\\ diff --git a/filedir.tex b/filedir.tex index d4a7015..9dfa3c3 100644 --- a/filedir.tex +++ b/filedir.tex @@ -797,9 +797,10 @@ puntatore alla struttura; si tenga presente per staticamente, per cui viene sovrascritta tutte le volte che si ripete la lettura di una voce sullo stesso stream. -Di questa funzione esiste anche una versione rientrante, \func{readdir\_r}, -che non usa una struttura allocata staticamente, e può essere utilizzata anche -con i thread; il suo prototipo è: +Di questa funzione esiste anche una versione \index{funzioni!rientranti} +rientrante, \func{readdir\_r}, che non usa una struttura allocata +staticamente, e può essere utilizzata anche con i \itindex{thread} +\textit{thread}; il suo prototipo è: \begin{functions} \headdecl{sys/types.h} \headdecl{dirent.h} @@ -1239,10 +1240,10 @@ invocazioni della funzione continueranno a restituire nomi unici fino ad un massimo di \const{TMP\_MAX} volte. Al nome viene automaticamente aggiunto come prefisso la directory specificata da \const{P\_tmpdir}. -Di questa funzione esiste una versione rientrante, \func{tmpnam\_r}, che non -fa nulla quando si passa \val{NULL} come argomento. Una funzione simile, -\funcd{tempnam}, permette di specificare un prefisso per il file -esplicitamente, il suo prototipo è: +Di questa funzione esiste una versione \index{funzioni!rientranti} rientrante, +\func{tmpnam\_r}, che non fa nulla quando si passa \val{NULL} come argomento. +Una funzione simile, \funcd{tempnam}, permette di specificare un prefisso per +il file esplicitamente, il suo prototipo è: \begin{prototype}{stdio.h}{char *tempnam(const char *dir, const char *pfx)} Restituisce il puntatore ad una stringa contente un nome di file valido e non esistente al momento dell'invocazione. @@ -1253,11 +1254,11 @@ esplicitamente, il suo prototipo \end{prototype} La funzione alloca con \code{malloc} la stringa in cui restituisce il nome, -per cui è sempre rientrante, occorre però ricordarsi di disallocare il -puntatore che restituisce. L'argomento \param{pfx} specifica un prefisso di -massimo 5 caratteri per il nome provvisorio. La funzione assegna come -directory per il file temporaneo (verificando che esista e sia accessibili), -la prima valida delle seguenti: +per cui è sempre \index{funzioni!rientranti} rientrante, occorre però +ricordarsi di disallocare il puntatore che restituisce. L'argomento +\param{pfx} specifica un prefisso di massimo 5 caratteri per il nome +provvisorio. La funzione assegna come directory per il file temporaneo +(verificando che esista e sia accessibili), la prima valida delle seguenti: \begin{itemize*} \item La variabile di ambiente \const{TMPNAME} (non ha effetto se non è definita o se il programma chiamante è \itindex{suid~bit} \acr{suid} o @@ -1296,8 +1297,8 @@ POSIX definisce la funzione \funcd{tmpfile}, il cui prototipo automaticamente cancellato alla sua chiusura o all'uscita dal programma. Lo standard non specifica in quale directory verrà aperto il file, ma le \acr{glibc} prima tentano con \const{P\_tmpdir} e poi con \file{/tmp}. Questa -funzione è rientrante e non soffre di problemi di \itindex{race~condition} -\textit{race condition}. +funzione è \index{funzioni!rientranti} rientrante e non soffre di problemi di +\itindex{race~condition} \textit{race condition}. Alcune versioni meno recenti di Unix non supportano queste funzioni; in questo caso si possono usare le vecchie funzioni \funcd{mktemp} e \func{mkstemp} che diff --git a/filestd.tex b/filestd.tex index 1c69ca2..d7e4b67 100644 --- a/filestd.tex +++ b/filestd.tex @@ -541,8 +541,8 @@ eventuali differenze. Le \acr{glibc} definiscono altre due funzioni per l'I/O binario, \funcd{fread\_unlocked} e \funcd{fwrite\_unlocked} che evitano il lock implicito dello stream, usato per dalla librerie per la gestione delle -applicazioni multi-thread (si veda sez.~\ref{sec:file_stream_thread} per i -dettagli), i loro prototipi sono: +applicazioni \itindex{thread} \textit{multi-thread} (si veda +sez.~\ref{sec:file_stream_thread} per i dettagli), i loro prototipi sono: \begin{functions} \headdecl{stdio.h} @@ -1319,7 +1319,7 @@ sistemi pi In questa sezione esamineremo alcune funzioni avanzate che permettono di eseguire operazioni particolari sugli stream, come leggerne gli attributi, controllarne le modalità di bufferizzazione, gestire direttamente i lock -impliciti per la programmazione multi thread. +impliciti per la programmazione \itindex{thread} \textit{multi-thread}. \subsection{Le funzioni di controllo} @@ -1540,29 +1540,32 @@ scrittura), e tutto l'input non ancora letto (se compresi gli eventuali caratteri rimandati indietro con \func{ungetc}. -\subsection{Gli stream e i thread} +\subsection{Gli \textit{stream} e i \textit{thread}} \label{sec:file_stream_thread} -Gli stream possono essere usati in applicazioni multi-thread allo stesso -modo in cui sono usati nelle applicazioni normali, ma si deve essere +\itindbeg{thread} + +Gli stream possono essere usati in applicazioni \textit{multi-thread} allo +stesso modo in cui sono usati nelle applicazioni normali, ma si deve essere consapevoli delle possibili complicazioni anche quando non si usano i -thread, dato che l'implementazione delle librerie è influenzata -pesantemente dalle richieste necessarie per garantirne l'uso con i thread. +\textit{thread}, dato che l'implementazione delle librerie è influenzata +pesantemente dalle richieste necessarie per garantirne l'uso con i +\textit{thread}. Lo standard POSIX richiede che le operazioni sui file siano atomiche rispetto -ai thread, per questo le operazioni sui buffer effettuate dalle funzioni di -libreria durante la lettura e la scrittura di uno stream devono essere -opportunamente protette (in quanto il sistema assicura l'atomicità solo per le -system call). Questo viene fatto associando ad ogni stream un opportuno blocco -che deve essere implicitamente acquisito prima dell'esecuzione di qualunque -operazione. - -Ci sono comunque situazioni in cui questo non basta, come quando un thread -necessita di compiere più di una operazione sullo stream atomicamente, per -questo motivo le librerie provvedono anche delle funzioni \funcd{flockfile}, -\funcd{ftrylockfile} e \funcd{funlockfile}, che permettono la gestione -esplicita dei blocchi sugli stream; esse sono disponibili definendo -\macro{\_POSIX\_THREAD\_SAFE\_FUNCTIONS} ed i loro prototipi sono: +ai \textit{thread}, per questo le operazioni sui buffer effettuate dalle +funzioni di libreria durante la lettura e la scrittura di uno stream devono +essere opportunamente protette (in quanto il sistema assicura l'atomicità solo +per le system call). Questo viene fatto associando ad ogni stream un opportuno +blocco che deve essere implicitamente acquisito prima dell'esecuzione di +qualunque operazione. + +Ci sono comunque situazioni in cui questo non basta, come quando un +\textit{thread} necessita di compiere più di una operazione sullo stream +atomicamente, per questo motivo le librerie provvedono anche delle funzioni +\funcd{flockfile}, \funcd{ftrylockfile} e \funcd{funlockfile}, che permettono +la gestione esplicita dei blocchi sugli stream; esse sono disponibili +definendo \macro{\_POSIX\_THREAD\_SAFE\_FUNCTIONS} ed i loro prototipi sono: \begin{functions} \headdecl{stdio.h} @@ -1581,8 +1584,8 @@ eseguire tutte le operazioni volute, per poi rilasciarlo. Ma, vista la complessità delle strutture di dati coinvolte, le operazioni di blocco non sono del tutto indolori, e quando il locking dello stream non è -necessario (come in tutti i programmi che non usano i thread), tutta la -procedura può comportare dei costi pesanti in termini di prestazioni. Per +necessario (come in tutti i programmi che non usano i \textit{thread}), tutta +la procedura può comportare dei costi pesanti in termini di prestazioni. Per questo motivo abbiamo visto come alle usuali funzioni di I/O non formattato siano associate delle versioni \code{\_unlocked} (alcune previste dallo stesso standard POSIX, altre aggiunte come estensioni dalle \acr{glibc}) che possono @@ -1593,8 +1596,8 @@ con prestazioni molto pi accade per \func{getc} e \func{putc}) sono realizzate come macro. La sostituzione di tutte le funzioni di I/O con le relative versioni -\code{\_unlocked} in un programma che non usa i thread è però un lavoro -abbastanza noioso; per questo motivo le \acr{glibc} forniscono al +\code{\_unlocked} in un programma che non usa i \textit{thread} è però un +lavoro abbastanza noioso; per questo motivo le \acr{glibc} forniscono al programmatore pigro un'altra via\footnote{anche questa mutuata da estensioni introdotte in Solaris.} da poter utilizzare per disabilitare in blocco il locking degli stream: l'uso della funzione \funcd{\_\_fsetlocking}, il cui @@ -1620,6 +1623,9 @@ che pu di blocco dello stream. \end{basedescript} +\itindend{thread} + + %%% Local Variables: %%% mode: latex diff --git a/fileunix.tex b/fileunix.tex index f0534ed..2e22dab 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -381,9 +381,10 @@ ritorno il file descriptor con il valore pi anche in FreeBSD, senza limiti di allineamento dei buffer. In Linux è stata introdotta con il kernel 2.4.10, le versioni precedenti la ignorano.} -\footnotetext[7]{introdotto con il kernel 2.6.23, per evitare una \textit{race - condition} che si può verificare con i thread, fra l'apertura del file e - l'impostazione della suddetta modalità con \func{fcntl}.} +\footnotetext[7]{introdotto con il kernel 2.6.23, per evitare una + \itindex{race~condition} \textit{race condition} che si può verificare con i + \itindex{thread} \textit{thread}, fra l'apertura del file e l'impostazione + della suddetta modalità con \func{fcntl}.} Questa caratteristica permette di prevedere qual è il valore del file descriptor che si otterrà al ritorno di \func{open}, e viene talvolta usata da @@ -1072,9 +1073,10 @@ parallelo alla chiamata a \func{open}, e questo lascia aperta la possibilit di una \itindex{race~condition} \textit{race condition}. Inoltre come già accennato, la directory di lavoro corrente è una proprietà -del singolo processo; questo significa che quando si lavora con i thread essa -sarà la stessa per tutti, ma esistono molti casi in cui sarebbe invece utile -che ogni singolo thread avesse la sua directory di lavoro. +del singolo processo; questo significa che quando si lavora con i +\itindex{thread} \textit{thread} essa sarà la stessa per tutti, ma esistono +molti casi in cui sarebbe invece utile che ogni singolo \itindex{thread} +\textit{thread} avesse la sua directory di lavoro. Per risolvere questi problemi, riprendendo una interfaccia già presente in Solaris, a fianco delle normali funzioni che operano sui file (come @@ -1097,13 +1099,13 @@ stesso. L'idea è che si apra prima la directory che si vuole usare come base dei pathname relativo, e si passi il file descriptor alla funzione che userà quella directory come punto di partenza per la risoluzione.\footnote{in questo - modo, anche quando si lavora con i thread, si può mantenere anche una - directory di lavoro diversa per ciascuno di essi.} Con queste funzioni si -possono anche ottenere grossi aumenti di prestazioni quando si devono eseguire -operazioni su delle sezioni di albero dei file che prevedono gerarchie molto -profonde e grandi quantità di file e directory, dato che basta eseguire la -risoluzione di un pathname una sola volta (nell'apertura della directory) e -non per ciascun file che essa contiene. + modo, anche quando si lavora con i \itindex{thread} \textit{thread}, si può + mantenere anche una directory di lavoro diversa per ciascuno di essi.} Con +queste funzioni si possono anche ottenere grossi aumenti di prestazioni quando +si devono eseguire operazioni su delle sezioni di albero dei file che +prevedono gerarchie molto profonde e grandi quantità di file e directory, dato +che basta eseguire la risoluzione di un pathname una sola volta (nell'apertura +della directory) e non per ciascun file che essa contiene. La sintassi generale di queste nuove funzioni è che esse prendano come primo argomento il file descriptor della directory da usare come base, mentre gli diff --git a/intro.tex b/intro.tex index 4e77602..4866730 100644 --- a/intro.tex +++ b/intro.tex @@ -578,12 +578,12 @@ mirante a standardizzare l'interfaccia con il sistema operativo. Ma gli standard POSIX non si limitano alla standardizzazione delle funzioni di libreria, e in seguito sono stati prodotti anche altri standard per la shell e i comandi di sistema (1003.2), per le estensioni \textit{real-time} e per i -thread (rispettivamente 1003.1d e 1003.1c) per i socket (1003.1g) e vari -altri. In tab.~\ref{tab:intro_posix_std} è riportata una classificazione -sommaria dei principali documenti prodotti, e di come sono identificati fra -IEEE ed ISO; si tenga conto inoltre che molto spesso si usa l'estensione IEEE -anche come aggiunta al nome POSIX; ad esempio è più comune parlare di POSIX.4 -come di POSIX.1b. +\itindex{thread} \textit{thread} (rispettivamente 1003.1d e 1003.1c) per i +socket (1003.1g) e vari altri. In tab.~\ref{tab:intro_posix_std} è riportata +una classificazione sommaria dei principali documenti prodotti, e di come sono +identificati fra IEEE ed ISO; si tenga conto inoltre che molto spesso si usa +l'estensione IEEE anche come aggiunta al nome POSIX; ad esempio è più comune +parlare di POSIX.4 come di POSIX.1b. Si tenga presente inoltre che nuove specifiche e proposte di standardizzazione si aggiungono continuamente, mentre le versioni precedenti vengono riviste; @@ -606,7 +606,7 @@ possono recuperare varie (e di norma piuttosto intricate) informazioni POSIX.2 & 1003.2 & 9945-2& Comandi \\ POSIX.3 & 2003 &TR13210& Metodi di test \\ POSIX.4 & 1003.1b & --- & Estensioni real-time \\ - POSIX.4a& 1003.1c & --- & Thread \\ + POSIX.4a& 1003.1c & --- & \itindex{thread} Thread \\ POSIX.4b& 1003.1d &9945-1& Ulteriori estensioni real-time \\ POSIX.5 & 1003.5 & 14519& Interfaccia per il linguaggio ADA \\ POSIX.6 & 1003.2c,1e& 9945-2& Sicurezza \\ @@ -632,11 +632,12 @@ sistema e che sono definite nello standard POSIX.2. Nelle versioni più recenti del kernel e delle librerie sono inoltre supportate ulteriori funzionalità aggiunte dallo standard POSIX.1c per quanto riguarda i -\textit{thread} (vedi cap.~\ref{cha:threads}), e dallo standard POSIX.1b per -quanto riguarda i segnali e lo \itindex{scheduler} scheduling real-time -(sez.~\ref{sec:sig_real_time} e sez.~\ref{sec:proc_real_time}), la misura del -tempo, i meccanismi di intercomunicazione (sez.~\ref{sec:ipc_posix}) e l'I/O -asincrono (sez.~\ref{sec:file_asyncronous_io}). +\itindex{thread} \textit{thread} (vedi cap.~\ref{cha:threads}), e dallo +standard POSIX.1b per quanto riguarda i segnali e lo \itindex{scheduler} +scheduling real-time (sez.~\ref{sec:sig_real_time} e +sez.~\ref{sec:proc_real_time}), la misura del tempo, i meccanismi di +intercomunicazione (sez.~\ref{sec:ipc_posix}) e l'I/O asincrono +(sez.~\ref{sec:file_asyncronous_io}). Lo standard principale resta comunque POSIX.1, che continua ad evolversi; la versione più nota, cui gran parte delle implementazioni fanno riferimento, e @@ -797,7 +798,7 @@ in esse definite, sono illustrate nel seguente elenco: \item un valore maggiore o uguale a ``\texttt{199506L}'' rende disponibili le funzionalità previste dallo standard POSIX.1 specificate nell'edizione del 1996 (\textit{ISO/IEC 9945-1:1996}), ed in particolare le definizioni - dello standard POSIX.1c per i \textit{thread}; + dello standard POSIX.1c per i \itindex{thread} \textit{thread}; \item a partire dalla versione 2.3.3 delle \acr{glibc} un valore maggiore o uguale a ``\texttt{200112L}'' rende disponibili le funzionalità di base previste dallo standard POSIX.1-2001, escludendo le estensioni XSI; @@ -820,11 +821,13 @@ in esse definite, sono illustrate nel seguente elenco: Si tenga inoltre presente che la preferenza verso le versioni delle funzioni usate da BSD viene mantenuta soltanto se nessuna delle ulteriori macro di - specificazione di standard successivi (\macro{\_SVID\_SOURCE}, - \macro{\_POSIX\_SOURCE}, \macro{\_POSIX\_C\_SOURCE}, + specificazione di standard successivi (vale a dire una fra + \macro{\_POSIX\_C\_SOURCE}, \macro{\_POSIX\_SOURCE}, \macro{\_SVID\_SOURCE}, \macro{\_XOPEN\_SOURCE}, \macro{\_XOPEN\_SOURCE\_EXTENDED} o \macro{\_GNU\_SOURCE}) è stata a sua volta attivata, nel qual caso queste - hanno la precedenza. + hanno la precedenza. Se però si definisce \macro{\_BSD\_SOURCE} dopo aver + definito una di queste macro, l'effetto sarà quello di dare la precedenza + alle funzioni in forma BSD. \item[\macro{\_SVID\_SOURCE}] definendo questa macro si rendono disponibili le funzionalità derivate da SVID. Esse comprendono anche quelle definite negli @@ -833,10 +836,11 @@ in esse definite, sono illustrate nel seguente elenco: \item[\macro{\_XOPEN\_SOURCE}] definendo questa macro si rendono disponibili le funzionalità descritte nella \textit{X/Open Portability Guide}. Anche - queste sono un sovrainsieme di quelle definite in POSIX.1 e POSIX.2 ed in - effetti sia \macro{\_POSIX\_SOURCE} che \macro{\_POSIX\_C\_SOURCE} vengono - automaticamente definite. Sono incluse anche ulteriori funzionalità - disponibili in BSD e SVID: + queste sono un sovrainsieme di quelle definite negli standard POSIX.1 e + POSIX.2 ed in effetti sia \macro{\_POSIX\_SOURCE} che + \macro{\_POSIX\_C\_SOURCE} vengono automaticamente definite. Sono incluse + anche ulteriori funzionalità disponibili in BSD e SVID, più una serie di + estensioni a secondo dei seguenti valori: \begin{itemize} \item la definizione della macro ad un valore qualunque attiva le funzionalità specificate negli standard POSIX.1, POSIX.2 e XPG4; @@ -868,9 +872,9 @@ in esse definite, sono illustrate nel seguente elenco: compatibilità. \item[\macro{\_GNU\_SOURCE}] definendo questa macro si rendono disponibili - tutte le funzionalità disponibili nei vari standard oltre a varie - estensioni. Gli standard coperti sono: ISO C89, ISO C99, POSIX.1, POSIX.2, - BSD, SVID, X/Open, SUS. + tutte le funzionalità disponibili nei vari standard oltre a varie estensioni + specifiche presenti solo nelle \acr{glibc} ed in Linux. Gli standard coperti + sono: ISO C89, ISO C99, POSIX.1, POSIX.2, BSD, SVID, X/Open, SUS. L'uso di \macro{\_GNU\_SOURCE} è equivalente alla definizione contemporanea delle macro: \macro{\_BSD\_SOURCE}, \macro{\_SVID\_SOURCE}, @@ -879,22 +883,26 @@ in esse definite, sono illustrate nel seguente elenco: ``\texttt{199506L}'' per le versioni delle \acr{glibc} precedenti la 2.5), \macro{\_XOPEN\_SOURCE\_EXTENDED} e \macro{\_XOPEN\_SOURCE} con valore 600 (o 500 per le versioni delle \acr{glibc} precedenti la 2.2); oltre a queste - vengono pure attivate le ulteriori \macro{\_ATFILE\_SOURCE} e + vengono pure attivate le ulteriori due macro \macro{\_ATFILE\_SOURCE} e \macro{\_LARGEFILE64\_SOURCE} che definiscono funzioni previste esclusivamente dalle \acr{glibc}. \end{basedescript} Benché Linux supporti in maniera estensiva gli standard più diffusi, esistono -comunque delle estensioni specifiche e delle funzionalità specifiche, non -presenti in altri standard e lo stesso vale per le \acr{glibc} stesse, che -definiscono anche delle ulteriori funzioni di libreria. Ovviamente l'uso di -queste funzionalità deve essere evitato se si ha a cuore la portabilità, ma -qualora questo non sia un requisito esse possono rivelarsi molto utili. +comunque delle estensioni e funzionalità specifiche, non presenti in altri +standard e lo stesso vale per le \acr{glibc} stesse, che definiscono anche +delle ulteriori funzioni di libreria. Ovviamente l'uso di queste funzionalità +deve essere evitato se si ha a cuore la portabilità, ma qualora questo non sia +un requisito esse possono rivelarsi molto utili. Come per l'aderenza ai vari standard, le funzionalità aggiuntive possono essere rese esplicitamente disponibili tramite la definizione di opportune -macro di preprocessore, che si sono illustrate nel seguente elenco: +macro di preprocessore, alcune di queste vengono attivate con la definizione +di \macro{\_GNU\_SOURCE}, mentre altre devono essere attivate esplicitamente, +inoltre alcune estensioni possono essere attivate indipendentemente tramite +una opportuna macro; queste estensioni sono illustrate nel seguente elenco: + \begin{basedescript}{\desclabelwidth{3cm}\desclabelstyle{\nextlinelabel}} \item[\macro{\_LARGEFILE\_SOURCE}] definendo questa macro si rendono @@ -937,32 +945,45 @@ macro di preprocessore, che si sono illustrate nel seguente elenco: macro non ha nessun effetto. \item[\macro{\_ATFILE\_SOURCE}] definendo questa macro si rendono disponibili - le funzioni - -\item[\macro{\_FORTIFY\_SOURCE}] definendo questa macro si rendono - disponibili le estensioni delle funzioni di creazione di file e directory - che consentono una specificazione coerente dei pathname relativi illustrate - in sez.~\ref{sec:file_openat}. - -\item[\macro{\_REENTRANT}] definendo questa macro si rendono disponibili + le estensioni delle funzioni di creazione di file e directory che risolvono + i problemi di sicurezza insiti nell'uso di pathname relativi con programmi + \itindex{thread} \textit{multi-thread} illustrate in + sez.~\ref{sec:file_openat}. + +\item[\macro{\_REENTRANT}] definendo questa macro, o la equivalente + \macro{\_THREAD\_SAFE} (fornita per compatibilità) si rendono disponibili le + versioni \index{funzioni!rientranti} rientranti (vedi + sez.~\ref{sec:proc_reentrant}) di alcune funzioni, necessarie quando si + usano i \itindex{thread} \textit{thread}. Alcune di queste funzioni sono + anche previste nello standard POSIX.1c, ma ve ne sono altre che sono + disponibili soltanto su alcuni sistemi, o specifiche del \acr{glibc}, e + possono essere utilizzate una volta definita la macro. + +\item[\macro{\_FORTIFY\_SOURCE}] definendo questa macro viene abilitata + l'inserimento di alcuni controlli per alcune funzioni di allocazione e + manipolazione di memoria e stringhe che consentono di rilevare + automaticamente alcuni errori di \textit{buffer overflow} nell'uso delle + stesse. La funzionalità è stata introdotta a partire dalla versione 2.3.4 + delle \acr{glibc} e richiede anche il supporto da parte del compilatore, che + è disponibile solo a partire dalla versione 4.0 del \texttt{gcc}. + + Le funzioni di libreria che vengono messe sotto controllo quando questa + funzionalità viene attivata sono, al momento della stesura di queste note, + le seguenti: \func{memcpy}, \func{mempcpy}, \func{memmove}, \func{memset}, + \func{stpcpy}, \func{strcpy}, \func{strncpy}, \func{strcat}, \func{strncat}, + \func{sprintf}, \func{snprintf}, \func{vsprintf}, \func{vsnprintf}, e + \func{gets}. + + La macro prevede due valori, con \texttt{1} vengono eseguiti dei controlli + di base che non cambiano il comportamento dei programmi se si richiede una + ottimizzazione di livello uno o superiore,\footnote{vale a dire se si usa + l'opzione \texttt{-O1} o superiore del \texttt{gcc}.} mentre con il + valore \texttt{2} vengono aggiunti maggiori controlli. \end{basedescript} -In particolare è da sottolineare che le \acr{glibc} supportano alcune -estensioni specifiche GNU, che non sono comprese in nessuno degli standard -citati. Per poterle utilizzare esse devono essere attivate esplicitamente -definendo la macro \macro{\_GNU\_SOURCE} prima di includere i vari header -file. - - % vedi anche man feature_test_macros -%% \subsection{Gli standard di GNU/Linux} -%% \label{sec:intro_linux_std} - -% TODO Da fare (o cassare, a seconda del tempo e della voglia). - - % LocalWords: like kernel multitasking scheduler preemptive sez swap is cap VM % LocalWords: everything bootstrap init shell Windows Foundation system call @@ -983,7 +1004,9 @@ file. % LocalWords: LARGEFILE Support LFS dell' black rectangle node fill cpu draw % LocalWords: ellipse mem anchor west proc SysV SV Definition SCO Austin XSI % LocalWords: Technical TC SUS Opengroup features STRICT std ATFILE fseeko -% LocalWords: ftello fseek ftell lseek FORTIFY REENTRANT +% LocalWords: ftello fseek ftell lseek FORTIFY REENTRANT SAFE overflow memcpy +% LocalWords: mempcpy memmove memset stpcpy strcpy strncpy strcat strncat gets +% LocalWords: sprintf snprintf vsprintf vsnprintf %%% Local Variables: %%% mode: latex diff --git a/ipc.tex b/ipc.tex index 105c757..8fb7ab8 100644 --- a/ipc.tex +++ b/ipc.tex @@ -175,10 +175,10 @@ evidente \itindex{race~condition} \textit{race condition} in caso di accesso simultaneo a detto file.\footnote{il problema potrebbe essere superato determinando in anticipo un nome appropriato per il file temporaneo, che verrebbe utilizzato dai vari sotto-processi, e cancellato alla fine della - loro esecuzione; ma a questo le cose non sarebbero più tanto semplici.} -L'uso di una pipe invece permette di risolvere il problema in maniera semplice -ed elegante, oltre ad essere molto più efficiente, dato che non si deve -scrivere su disco. + loro esecuzione; ma a questo punto le cose non sarebbero più tanto + semplici.} L'uso di una pipe invece permette di risolvere il problema in +maniera semplice ed elegante, oltre ad essere molto più efficiente, dato che +non si deve scrivere su disco. Il programma ci servirà anche come esempio dell'uso delle funzioni di duplicazione dei file descriptor che abbiamo trattato in @@ -2605,12 +2605,12 @@ indirizzo come arrotondamento, in Linux L'uso di \const{SHM\_RDONLY} permette di agganciare il segmento in sola lettura (si ricordi che anche le pagine di memoria hanno dei permessi), in tal -caso un tentativo di scrivere sul segmento comporterà una violazione di -accesso con l'emissione di un segnale di \const{SIGSEGV}. Il comportamento -usuale di \func{shmat} è quello di agganciare il segmento con l'accesso in -lettura e scrittura (ed il processo deve aver questi permessi in -\var{shm\_perm}), non è prevista la possibilità di agganciare un segmento in -sola scrittura. +caso un tentativo di scrivere sul segmento comporterà una +\itindex{segment~violation} violazione di accesso con l'emissione di un +segnale di \const{SIGSEGV}. Il comportamento usuale di \func{shmat} è quello +di agganciare il segmento con l'accesso in lettura e scrittura (ed il processo +deve aver questi permessi in \var{shm\_perm}), non è prevista la possibilità +di agganciare un segmento in sola scrittura. In caso di successo la funzione aggiorna anche i seguenti campi di \struct{shmid\_ds}: @@ -3258,8 +3258,9 @@ una interfaccia completamente nuova, che tratteremo in questa sezione. Oggi Linux supporta tutti gli oggetti definito nello standard POSIX per l'IPC, ma a lungo non è stato così; la memoria condivisa è presente a partire dal kernel 2.4.x, i semafori sono forniti dalle \acr{glibc} nella sezione che -implementa i thread POSIX di nuova generazione che richiedono il kernel 2.6, -le code di messaggi sono supportate a partire dal kernel 2.6.6. +implementa i \itindex{thread} \textit{thread} POSIX di nuova generazione che +richiedono il kernel 2.6, le code di messaggi sono supportate a partire dal +kernel 2.6.6. La caratteristica fondamentale dell'interfaccia POSIX è l'abbandono dell'uso degli identificatori e delle chiavi visti nel SysV IPC, per passare ai @@ -3710,15 +3711,15 @@ della stessa struttura per l'invio dei segnali usati per l'I/O asincrono. Attraverso questa struttura si possono impostare le modalità con cui viene effettuata la notifica; in particolare il campo \var{sigev\_notify} deve essere posto a \const{SIGEV\_SIGNAL}\footnote{il meccanismo di notifica basato - sui thread, specificato tramite il valore \const{SIGEV\_THREAD}, non è - implementato.} ed il campo \var{sigev\_signo} deve indicare il valore del -segnale che sarà inviato al processo. Inoltre il campo \var{sigev\_value} è il -puntatore ad una struttura \struct{sigval\_t} (definita in -fig.~\ref{fig:sig_sigval}) che permette di restituire al gestore del segnale un -valore numerico o un indirizzo,\footnote{per il suo uso si riveda la - trattazione fatta in sez.~\ref{sec:sig_real_time} a proposito dei segnali - real-time.} posto che questo sia installato nella forma estesa vista in -sez.~\ref{sec:sig_sigaction}. + sui \itindex{thread} \textit{thread}, specificato tramite il valore + \const{SIGEV\_THREAD}, non è implementato.} ed il campo \var{sigev\_signo} +deve indicare il valore del segnale che sarà inviato al processo. Inoltre il +campo \var{sigev\_value} è il puntatore ad una struttura \struct{sigval\_t} +(definita in fig.~\ref{fig:sig_sigval}) che permette di restituire al gestore +del segnale un valore numerico o un indirizzo,\footnote{per il suo uso si + riveda la trattazione fatta in sez.~\ref{sec:sig_real_time} a proposito dei + segnali real-time.} posto che questo sia installato nella forma estesa vista +in sez.~\ref{sec:sig_sigaction}. La funzione registra il processo chiamante per la notifica se \param{notification} punta ad una struttura \struct{sigevent} opportunamente @@ -3946,15 +3947,16 @@ restituendo al chiamante il valore di ritorno. \label{sec:ipc_posix_sem} Fino alla serie 2.4.x del kernel esisteva solo una implementazione parziale -dei semafori POSIX che li realizzava solo a livello di thread e non di -processi,\footnote{questo significava che i semafori erano visibili solo - all'interno dei thread creati da un singolo processo, e non potevano essere - usati come meccanismo di sincronizzazione fra processi diversi.} fornita -attraverso la sezione delle estensioni \textit{real-time} delle -\acr{glibc}.\footnote{quelle che si accedono collegandosi alla libreria - \texttt{librt}.} Esisteva inoltre una libreria che realizzava (parzialmente) -l'interfaccia POSIX usando le funzioni dei semafori di SysV IPC (mantenendo -così tutti i problemi sottolineati in sez.~\ref{sec:ipc_sysv_sem}). +dei semafori POSIX che li realizzava solo a livello di \itindex{thread} +\textit{thread} e non di processi,\footnote{questo significava che i semafori + erano visibili solo all'interno dei \itindex{thread} \textit{thread} creati + da un singolo processo, e non potevano essere usati come meccanismo di + sincronizzazione fra processi diversi.} fornita attraverso la sezione delle +estensioni \textit{real-time} delle \acr{glibc}.\footnote{quelle che si + accedono collegandosi alla libreria \texttt{librt}.} Esisteva inoltre una +libreria che realizzava (parzialmente) l'interfaccia POSIX usando le funzioni +dei semafori di SysV IPC (mantenendo così tutti i problemi sottolineati in +sez.~\ref{sec:ipc_sysv_sem}). A partire dal kernel 2.5.7 è stato introdotto un meccanismo di sincronizzazione completamente nuovo, basato sui cosiddetti @@ -4162,11 +4164,11 @@ fosse occupato;\footnote{si ricordi che in generale un semaforo viene usato La funzione incrementa di uno il valore corrente del semaforo indicato dall'argomento \param{sem}, se questo era nullo la relativa risorsa risulterà -sbloccata, cosicché un altro processo (o thread) eventualmente bloccato in una -\func{sem\_wait} sul semaforo potrà essere svegliato e rimesso in esecuzione. -Si tenga presente che la funzione è sicura \index{funzioni~sicure} per l'uso -all'interno di un gestore di segnali (si ricordi quanto detto in -sez.~\ref{sec:sig_signal_handler}). +sbloccata, cosicché un altro processo (o \itindex{thread} \textit{thread}) +eventualmente bloccato in una \func{sem\_wait} sul semaforo potrà essere +svegliato e rimesso in esecuzione. Si tenga presente che la funzione è sicura +\index{funzioni!sicure} per l'uso all'interno di un gestore di segnali (si +ricordi quanto detto in sez.~\ref{sec:sig_signal_handler}). Se invece di operare su un semaforo se ne vuole solamente leggere il valore, si può usare la funzione \funcd{sem\_getvalue}, il cui prototipo è: @@ -4290,15 +4292,16 @@ prototipo La funzione inizializza un semaforo all'indirizzo puntato dall'argomento \param{sem}, e come per \func{sem\_open} consente di impostare un valore iniziale con \param{value}. L'argomento \param{pshared} serve ad indicare se -il semaforo deve essere utilizzato dai \itindex{thread} thread di uno stesso -processo (con un valore nullo) o condiviso fra processi diversi (con un valore -non nullo). +il semaforo deve essere utilizzato dai \itindex{thread} \textit{thread} di uno +stesso processo (con un valore nullo) o condiviso fra processi diversi (con un +valore non nullo). -Qualora il semaforo debba essere condiviso dai \itindex{thread} thread di uno -stesso processo (nel qual caso si parla di \textit{thread-shared semaphore}), -occorrerà che \param{sem} sia l'indirizzo di una variabile visibile da tutti i -\itindex{thread} thread, si dovrà usare cioè una variabile globale o una -variabile allocata dinamicamente nello \itindex{heap} heap. +Qualora il semaforo debba essere condiviso dai \itindex{thread} +\textit{thread} di uno stesso processo (nel qual caso si parla di +\textit{thread-shared semaphore}), occorrerà che \param{sem} sia l'indirizzo +di una variabile visibile da tutti i \itindex{thread} \textit{thread}, si +dovrà usare cioè una variabile globale o una variabile allocata dinamicamente +nello \itindex{heap} heap. Qualora il semaforo debba essere condiviso fra più processi (nel qual caso si parla di \textit{process-shared semaphore}) la sola scelta possibile per @@ -4340,8 +4343,9 @@ La funzione prende come unico argomento l'indirizzo di un semaforo che deve essere stato inizializzato con \func{sem\_init}; non deve quindi essere applicata a semafori creati con \func{sem\_open}. Inoltre si deve essere sicuri che il semaforo sia effettivamente inutilizzato, la distruzione di un -semaforo su cui sono presenti processi (o thread) in attesa (cioè bloccati in -una \func{sem\_wait}) provoca un comportamento indefinito. +semaforo su cui sono presenti processi (o \itindex{thread} \textit{thread}) in +attesa (cioè bloccati in una \func{sem\_wait}) provoca un comportamento +indefinito. Si tenga presente infine che utilizzare un semaforo che è stato distrutto con \func{sem\_destroy} di nuovo può dare esito a comportamenti indefiniti. Nel diff --git a/network.tex b/network.tex index d431cd4..2307640 100644 --- a/network.tex +++ b/network.tex @@ -73,11 +73,12 @@ una risposta alla richiesta. Una volta completata la risposta il server diventa di nuovo disponibile. Un \textsl{server concorrente} al momento di trattare la richiesta crea un -processo figlio (o un thread) incaricato di fornire i servizi richiesti, per -porsi immediatamente in attesa di ulteriori richieste. In questo modo, con -sistemi multitasking, più richieste possono essere soddisfatte -contemporaneamente. Una volta che il processo figlio ha concluso il suo lavoro -esso di norma viene terminato, mentre il server originale resta sempre attivo. +processo figlio (o un \itindex{thread} \textit{thread}) incaricato di fornire +i servizi richiesti, per porsi immediatamente in attesa di ulteriori +richieste. In questo modo, con sistemi multitasking, più richieste possono +essere soddisfatte contemporaneamente. Una volta che il processo figlio ha +concluso il suo lavoro esso di norma viene terminato, mentre il server +originale resta sempre attivo. \subsection{Il modello \textit{peer-to-peer}} diff --git a/process.tex b/process.tex index 30913ae..601c225 100644 --- a/process.tex +++ b/process.tex @@ -35,8 +35,8 @@ ciascun processo vedr tutte le parti uguali siano condivise), avrà un suo spazio di indirizzi, variabili proprie e sarà eseguito in maniera completamente indipendente da tutti gli altri.\footnote{questo non è del tutto vero nel caso di un programma - \textit{multi-thread}, ma la gestione dei \textit{thread} in Linux sarà - trattata a parte.} + \textit{multi-thread}, ma la gestione dei \itindex{thread} \textit{thread} + in Linux sarà trattata a parte in cap.~\ref{cha:threads}.} \subsection{La funzione \func{main}} @@ -373,12 +373,12 @@ Inoltre per certe applicazioni gli algoritmi di gestione della memoria Benché lo spazio di indirizzi virtuali copra un intervallo molto ampio, solo una parte di essi è effettivamente allocato ed utilizzabile dal processo; il tentativo di accedere ad un indirizzo non allocato è un tipico errore che si -commette quando si è manipolato male un puntatore e genera quello che viene -chiamato un \textit{segmentation fault}. Se si tenta cioè di leggere o -scrivere da un indirizzo per il quale non esiste un'associazione della pagina -virtuale, il kernel risponde al relativo \itindex{page~fault} \textit{page - fault} mandando un segnale \const{SIGSEGV} al processo, che normalmente ne -causa la terminazione immediata. +commette quando si è manipolato male un puntatore e genera quella che viene +chiamata una \itindex{segment~violation} \textit{segment violation}. Se si +tenta cioè di leggere o scrivere da un indirizzo per il quale non esiste +un'associazione della pagina virtuale, il kernel risponde al relativo +\itindex{page~fault} \textit{page fault} mandando un segnale \const{SIGSEGV} +al processo, che normalmente ne causa la terminazione immediata. È pertanto importante capire come viene strutturata \index{memoria~virtuale} \textsl{la memoria virtuale} di un processo. Essa viene divisa in @@ -443,12 +443,13 @@ seguenti segmenti: automaticamente il codice necessario, seguendo quella che viene chiamata una \textit{calling convention}; quella standard usata con il C ed il C++ è detta \textit{cdecl} e prevede che gli argomenti siano caricati nello - stack dal chiamante da destra a sinistra, e che si il chiamante stesso ad - eseguire la ripulitura dello stack al ritorno della funzione, se ne - possono però utilizzare di alternative (ad esempio nel pascal gli - argomenti sono inseriti da sinistra a destra ed è compito del chiamato - ripulire lo stack), in genere non ci si deve preoccupare di questo - fintanto che non si mescolano funzioni scritte con linguaggi diversi.} + \textit{stack} dal chiamante da destra a sinistra, e che si il chiamante + stesso ad eseguire la ripulitura dello \textit{stack} al ritorno della + funzione, se ne possono però utilizzare di alternative (ad esempio nel + pascal gli argomenti sono inseriti da sinistra a destra ed è compito del + chiamato ripulire lo \textit{stack}), in genere non ci si deve preoccupare + di questo fintanto che non si mescolano funzioni scritte con linguaggi + diversi.} La dimensione di questo segmento aumenta seguendo la crescita dello \itindex{stack} \textit{stack} del programma, ma non viene ridotta quando @@ -623,13 +624,13 @@ variabile di ambiente \val{MALLOC\_CHECK\_} che quando viene definita mette in uso una versione meno efficiente delle funzioni suddette, che però è più tollerante nei confronti di piccoli errori come quello di chiamate doppie a \func{free}. In particolare: -\begin{itemize*} +\begin{itemize} \item se la variabile è posta a zero gli errori vengono ignorati; \item se è posta ad 1 viene stampato un avviso sullo \textit{standard error} (vedi sez.~\ref{sec:file_std_stream}); \item se è posta a 2 viene chiamata \func{abort}, che in genere causa l'immediata conclusione del programma. -\end{itemize*} +\end{itemize} Il problema più comune e più difficile da risolvere che si incontra con le funzioni di allocazione è quando non viene opportunamente liberata la memoria @@ -689,7 +690,6 @@ ricompilare il programma,\footnote{esempi sono \textit{Dmalloc} \textit{Electric Fence} di Bruce Perens.} di eseguire diagnostiche anche molto complesse riguardo l'allocazione della memoria. - Una possibile alternativa all'uso di \func{malloc}, che non soffre dei problemi di \itindex{memory~leak} \textit{memory leak} descritti in precedenza, è la funzione \funcd{alloca}, che invece di allocare la memoria @@ -697,11 +697,10 @@ nello \itindex{heap} \textit{heap} usa il segmento di \itindex{stack} \textit{stack} della funzione corrente. La sintassi è identica a quella di \func{malloc}, il suo prototipo è: \begin{prototype}{stdlib.h}{void *alloca(size\_t size)} - Alloca \param{size} byte nello stack. + Alloca \param{size} byte nello \textit{stack}. - \bodydesc{La funzione restituisce il puntatore alla zona di memoria allocata - in caso di successo e \val{NULL} in caso di fallimento, nel qual caso - \var{errno} assumerà il valore \errval{ENOMEM}.} + \bodydesc{La funzione restituisce il puntatore alla zona di memoria + allocata.} \end{prototype} La funzione alloca la quantità di memoria (non inizializzata) richiesta @@ -729,16 +728,6 @@ suo utilizzo quindi limita la portabilit non può essere usata nella lista degli argomenti di una funzione, perché lo spazio verrebbe allocato nel mezzo degli stessi. -% Questo è riportato solo dal manuale delle glibc, nelle pagine di manuale non c'è -% traccia di tutto ciò -% -%Inoltre se si -%cerca di allocare troppa memoria non si ottiene un messaggio di errore, ma un -%segnale di \textit{segment violation} analogo a quello che si avrebbe da una -%ricorsione infinita. -% TODO inserire più informazioni su alloca come da man page - - Inoltre non è chiaramente possibile usare \func{alloca} per allocare memoria che deve poi essere usata anche al di fuori della funzione in cui essa viene chiamata, dato che all'uscita dalla funzione lo spazio allocato diventerebbe @@ -746,14 +735,29 @@ libero, e potrebbe essere sovrascritto all'invocazione di nuove funzioni. Questo è lo stesso problema che si può avere con le variabili automatiche, su cui torneremo in sez.~\ref{sec:proc_auto_var}. +Infine non esiste un modo di sapere se l'allocazione ha avuto successo, la +funzione infatti viene realizzata inserendo del codice \textit{inline} nel +programma\footnote{questo comporta anche il fatto che non è possibile + sostituirla con una propria versione o modificarne il comportamento + collegando il proprio programma con un'altra libreria.} che si limita a +modificare il puntatore nello \itindex{stack} \textit{stack} e non c'è modo di +sapere se se ne sono superate le dimensioni, per cui in caso di fallimento +nell'allocazione il comportamento del programma può risultare indefinito, +dando luogo ad una \itindex{segment~violation} \textit{segment violation} la +prima volta che cercherà di accedere alla memoria non effettivamente +disponibile. Le due funzioni seguenti\footnote{le due funzioni sono state definite con BSD - 4.3, non fanno parte delle librerie standard del C e mentre sono state - esplicitamente escluse dallo standard POSIX.} vengono utilizzate soltanto -quando è necessario effettuare direttamente la gestione della memoria -associata allo spazio dati di un processo, ad esempio qualora si debba -implementare la propria versione delle funzioni di allocazione della memoria. -La prima funzione è \funcd{brk}, ed il suo prototipo è: + 4.3, sono marcate obsolete in SUSv2 e non fanno parte delle librerie + standard del C e mentre sono state esplicitamente rimosse dallo standard + POSIX/1-2001.} vengono utilizzate soltanto quando è necessario effettuare +direttamente la gestione della memoria associata allo spazio dati di un +processo, ad esempio qualora si debba implementare la propria versione delle +funzioni di allocazione della memoria. Per poterle utilizzare è necessario +definire una della macro di funzionalità (vedi +sez.~\ref{sec:intro_gcc_glibc_std}) fra \macro{\_BSD\_SOURCE}, +\macro{\_SVID\_SOURCE} e \macro{\_XOPEN\_SOURCE} (ad un valore maggiore o +ugiale di 500). La prima funzione è \funcd{brk}, ed il suo prototipo è: \begin{prototype}{unistd.h}{int brk(void *end\_data\_segment)} Sposta la fine del segmento dei dati. @@ -761,15 +765,22 @@ La prima funzione fallimento, nel qual caso \var{errno} assumerà il valore \errval{ENOMEM}.} \end{prototype} -La funzione è un'interfaccia diretta all'omonima system call ed imposta -l'indirizzo finale del \index{segmento!dati} segmento dati di un processo -all'indirizzo specificato da \param{end\_data\_segment}. Quest'ultimo deve -essere un valore ragionevole, ed inoltre la dimensione totale del segmento non -deve comunque eccedere un eventuale limite (si veda -sez.~\ref{sec:sys_resource_limit}) imposto sulle dimensioni massime dello -spazio dati del processo. - -Una seconda funzione per la manipolazione delle dimensioni +La funzione è un'interfaccia all'omonima system call ed imposta l'indirizzo +finale del \index{segmento!dati} segmento dati di un processo all'indirizzo +specificato da \param{end\_data\_segment}. Quest'ultimo deve essere un valore +ragionevole, ed inoltre la dimensione totale del segmento non deve comunque +eccedere un eventuale limite (si veda sez.~\ref{sec:sys_resource_limit}) +imposto sulle dimensioni massime dello spazio dati del processo. + +Il valore di ritorno della funzione fa riferimento alla versione fornita dalle +\acr{glibc}, in realtà in Linux la \textit{system call} corrispondente +restituisce come valore di ritorno il nuovo valore della fine del +\index{segmento!dati} segmento dati in caso di successo e quello corrente in +caso di fallimento, è la funzione di interfaccia usata dalle \acr{glibc} che +fornisce i valori di ritorno appena descritti, questo può non accadere se si +usano librerie diverse. + +Una seconda funzione per la manipolazione diretta delle dimensioni \index{segmento!dati} del segmento dati\footnote{in questo caso si tratta soltanto di una funzione di libreria, e non di una system call.} è \funcd{sbrk}, ed il suo prototipo è: @@ -1136,17 +1147,6 @@ questo permette di identificare gli elementi che non sono opzioni, ma non effettua il riordinamento del vettore \param{argv}. -\subsection{Opzioni in formato esteso} -\label{sec:proc_opt_extended} - -Un'estensione di questo schema è costituita dalle cosiddette -\textit{long-options} espresse nella forma \cmd{-{}-option=parameter}, anche -la gestione di queste ultime è stata standardizzata attraverso l'uso di una -versione estesa di \func{getopt}. - -(NdA: questa parte verrà inserita in seguito). -% TODO opzioni in formato esteso - \subsection{Le variabili di ambiente} \label{sec:proc_environ} @@ -1368,6 +1368,21 @@ alla cancellazione di tutto l'ambiente per costruirne una versione ``\textsl{sicura}'' da zero. +\subsection{Opzioni in formato esteso} +\label{sec:proc_opt_extended} + +Oltre alla modalità ordinaria di gestione delle opzioni trattata in +sez.~\ref{sec:proc_opt_handling} le \acr{glibc} forniscono una modalità +alternativa costituita dalle cosiddette \textit{long-options}, che consente di +esprimere le opzioni in una forma più descrittiva che nel caso più generale è +qualcosa del tipo di ``\texttt{-{}-option-name=parameter}''. + +(NdA: questa parte verrà inserita in seguito). + +% TODO opzioni in formato esteso + + + \section{Problematiche di programmazione generica} \label{sec:proc_gen_prog} @@ -1755,7 +1770,7 @@ dichiarandole tutte come \direct{volatile}.\footnote{la direttiva % LocalWords: SUCCESS FAILURE void atexit stream fclose unistd descriptor init % LocalWords: SIGCHLD wait function glibc SunOS arg argp execve fig high kb Mb % LocalWords: memory alpha swap table printf Unit MMU paging fault SIGSEGV BSS -% LocalWords: multitasking segmentation text segment NULL Block Started Symbol +% LocalWords: multitasking text segment NULL Block Started Symbol % LocalWords: heap stack calling convention size malloc calloc realloc nmemb % LocalWords: ENOMEM ptr uClib cfree error leak smartpointers hook Dmalloc brk % LocalWords: Gray Watson Electric Fence Bruce Perens sbrk longjmp SUSv BSD ap diff --git a/prochand.tex b/prochand.tex index 88f897a..7ce8852 100644 --- a/prochand.tex +++ b/prochand.tex @@ -248,13 +248,13 @@ massimo di 32768. Oltre questo valore l'assegnazione riparte dal numero pi basso disponibile a partire da un minimo di 300,\footnote{questi valori, fino al kernel 2.4.x, sono definiti dalla macro \const{PID\_MAX} in \file{threads.h} e direttamente in \file{fork.c}, con il kernel 2.5.x e la - nuova interfaccia per i thread creata da Ingo Molnar anche il meccanismo di - allocazione dei \acr{pid} è stato modificato; il valore massimo è - impostabile attraverso il file \procfile{/proc/sys/kernel/pid\_max} e di - default vale 32768.} che serve a riservare i \acr{pid} più bassi ai processi -eseguiti direttamente dal kernel. Per questo motivo, come visto in -sez.~\ref{sec:proc_hierarchy}, il processo di avvio (\cmd{init}) ha sempre il -\acr{pid} uguale a uno. + nuova interfaccia per i \itindex{thread} \textit{thread} creata da Ingo + Molnar anche il meccanismo di allocazione dei \acr{pid} è stato modificato; + il valore massimo è impostabile attraverso il file + \procfile{/proc/sys/kernel/pid\_max} e di default vale 32768.} che serve a +riservare i \acr{pid} più bassi ai processi eseguiti direttamente dal kernel. +Per questo motivo, come visto in sez.~\ref{sec:proc_hierarchy}, il processo di +avvio (\cmd{init}) ha sempre il \acr{pid} uguale a uno. Tutti i processi inoltre memorizzano anche il \acr{pid} del genitore da cui sono stati creati, questo viene chiamato in genere \acr{ppid} (da @@ -331,7 +331,7 @@ Dopo il successo dell'esecuzione di una \func{fork} sia il processo padre che il processo figlio continuano ad essere eseguiti normalmente a partire dall'istruzione successiva alla \func{fork}; il processo figlio è però una copia del padre, e riceve una copia dei \index{segmento!testo} segmenti di -testo, \itindex{stack} stack e \index{segmento!dati} dati (vedi +testo, \itindex{stack} \textit{stack} e \index{segmento!dati} dati (vedi sez.~\ref{sec:proc_mem_layout}), ed esegue esattamente lo stesso codice del padre. Si tenga presente però che la memoria è copiata, non condivisa, pertanto padre e figlio vedono variabili diverse. @@ -949,8 +949,9 @@ funzione delle opportune opzioni tramite l'argomento \param{options}; questo deve essere specificato come maschera binaria dei flag riportati in tab.~\ref{tab:proc_waitpid_options},\footnote{oltre a queste in Linux sono previste del altre opzioni non standard, relative al comportamento con i - thread, che riprenderemo in sez.~\ref{sec:thread_xxx}.} che possono essere -combinati fra loro con un OR aritmetico. + \itindex{thread} \textit{thread}, che riprenderemo in + sez.~\ref{sec:thread_xxx}.} che possono essere combinati fra loro con un OR +aritmetico. L'uso dell'opzione \const{WNOHANG} consente di prevenire il blocco della funzione qualora nessun figlio sia uscito (o non si siano verificate le altre @@ -3496,10 +3497,11 @@ o periferiche) pu avviene nelle architetture NUMA). Infine se un gruppo di processi accede alle stesse risorse condivise (ad -esempio una applicazione con più thread) può avere senso usare lo stesso -processore in modo da sfruttare meglio l'uso della sua cache; questo -ovviamente riduce i benefici di un sistema multiprocessore nell'esecuzione -contemporanea dei thread, ma in certi casi (quando i thread sono inerentemente +esempio una applicazione con più \itindex{thread} \textit{thread}) può avere +senso usare lo stesso processore in modo da sfruttare meglio l'uso della sua +cache; questo ovviamente riduce i benefici di un sistema multiprocessore +nell'esecuzione contemporanea dei \itindex{thread} \textit{thread}, ma in +certi casi (quando i \itindex{thread} \textit{thread} sono inerentemente serializzati nell'accesso ad una risorsa) possono esserci sufficienti vantaggi nell'evitare la perdita della cache da rendere conveniente l'uso dell'affinità di processore. @@ -3698,19 +3700,22 @@ eseguire in maniera atomica le operazioni necessarie. \subsection{Le funzioni rientranti} \label{sec:proc_reentrant} +\index{funzioni!rientranti|(} + Si dice \textsl{rientrante} una funzione che può essere interrotta in qualunque punto della sua esecuzione ed essere chiamata una seconda volta da -un altro thread di esecuzione senza che questo comporti nessun problema -nell'esecuzione della stessa. La problematica è comune nella programmazione -multi-thread, ma si hanno gli stessi problemi quando si vogliono chiamare -delle funzioni all'interno dei gestori dei segnali. +un altro \itindex{thread} \textit{thread} di esecuzione senza che questo +comporti nessun problema nell'esecuzione della stessa. La problematica è +comune nella programmazione \itindex{thread} \textit{multi-thread}, ma si +hanno gli stessi problemi quando si vogliono chiamare delle funzioni +all'interno dei gestori dei segnali. Fintanto che una funzione opera soltanto con le variabili locali è rientrante; -queste infatti vengono allocate nello \itindex{stack} stack, ed un'altra -invocazione non fa altro che allocarne un'altra copia. Una funzione può non -essere rientrante quando opera su memoria che non è nello \itindex{stack} -stack. Ad esempio una funzione non è mai rientrante se usa una variabile -globale o statica. +queste infatti vengono allocate nello \itindex{stack} \textit{stack}, ed +un'altra invocazione non fa altro che allocarne un'altra copia. Una funzione +può non essere rientrante quando opera su memoria che non è nello +\itindex{stack} \textit{stack}. Ad esempio una funzione non è mai rientrante +se usa una variabile globale o statica. Nel caso invece la funzione operi su un oggetto allocato dinamicamente, la cosa viene a dipendere da come avvengono le operazioni: se l'oggetto è creato @@ -3724,16 +3729,20 @@ parte del programmatore. In genere le funzioni di libreria non sono rientranti, molte di esse ad esempio utilizzano variabili statiche, le \acr{glibc} però mettono a -disposizione due macro di compilatore, \macro{\_REENTRANT} e +disposizione due macro di compilatore,\footnote{si ricordi quanto illustrato + in sez.~\ref{sec:intro_gcc_glibc_std}.} \macro{\_REENTRANT} e \macro{\_THREAD\_SAFE}, la cui definizione attiva le versioni rientranti di varie funzioni di libreria, che sono identificate aggiungendo il suffisso \code{\_r} al nome della versione normale. +\index{funzioni!rientranti|)} + + % LocalWords: multitasking like VMS child process identifier pid sez shell fig % LocalWords: parent kernel init pstree keventd kswapd table struct linux call % LocalWords: nell'header scheduler system interrupt timer HZ asm Hertz clock % LocalWords: l'alpha tick fork wait waitpid exit exec image glibc int pgid ps -% LocalWords: sid threads thread Ingo Molnar ppid getpid getppid sys unistd LD +% LocalWords: sid thread Ingo Molnar ppid getpid getppid sys unistd LD % LocalWords: void ForkTest tempnam pathname sibling cap errno EAGAIN ENOMEM % LocalWords: stack read only copy write tab client spawn forktest sleep PATH % LocalWords: source LIBRARY scheduling race condition printf descriptor dup diff --git a/session.tex b/session.tex index 12bee81..ce8144a 100644 --- a/session.tex +++ b/session.tex @@ -1058,9 +1058,9 @@ stata allocata in precedenza ed essere lunga almeno che indica la dimensione che deve avere una stringa per poter contenere il nome di un terminale.} caratteri. -Esiste infine una versione rientrante \funcd{ttyname\_r} della funzione -\func{ttyname}, che non presenta il problema dell'uso di una zona di memoria -statica; il suo prototipo è: +Esiste infine una versione \index{funzioni!rientranti} rientrante +\funcd{ttyname\_r} della funzione \func{ttyname}, che non presenta il problema +dell'uso di una zona di memoria statica; il suo prototipo è: \begin{prototype}{unistd.h}{int ttyname\_r(int desc, char *buff, size\_t len)} Restituisce il nome del terminale associato al file \param{desc}. diff --git a/signal.tex b/signal.tex index b4086ed..0246606 100644 --- a/signal.tex +++ b/signal.tex @@ -262,10 +262,10 @@ un eventuale messaggio di errore. I segnali che rappresentano errori del programma (divisione per zero o violazioni di accesso) hanno anche la caratteristica di scrivere un file di \itindex{core~dump} \textit{core dump} che registra lo stato del processo (ed -in particolare della memoria e dello \itindex{stack} stack) prima della -terminazione. Questo può essere esaminato in seguito con un debugger per -investigare sulla causa dell'errore. Lo stesso avviene se i suddetti segnali -vengono generati con una \func{kill}. +in particolare della memoria e dello \itindex{stack} \textit{stack}) prima +della terminazione. Questo può essere esaminato in seguito con un debugger +per investigare sulla causa dell'errore. Lo stesso avviene se i suddetti +segnali vengono generati con una \func{kill}. \section{La classificazione dei segnali} @@ -349,8 +349,8 @@ In alcuni casi alla terminazione del processo file (posto nella directory corrente del processo e chiamato \file{core}) su cui viene salvata un'immagine della memoria del processo (il cosiddetto \itindex{core~dump} \textit{core dump}), che può essere usata da un debugger -per esaminare lo stato dello \itindex{stack} stack e delle variabili al -momento della ricezione del segnale. +per esaminare lo stato dello \itindex{stack} \textit{stack} e delle variabili +al momento della ricezione del segnale. \begin{table}[htb] \footnotesize @@ -459,16 +459,16 @@ programma al momento della terminazione. Questi segnali sono: file eseguibile è corrotto o si stanno cercando di eseguire dei dati. Quest'ultimo caso può accadere quando si passa un puntatore sbagliato al posto di un puntatore a funzione, o si eccede la scrittura di un vettore di - una variabile locale, andando a corrompere lo \itindex{stack} stack. Lo - stesso segnale viene generato in caso di overflow dello \itindex{stack} - stack o di problemi nell'esecuzione di un gestore. Se il gestore ritorna il - comportamento del processo è indefinito. -\item[\const{SIGSEGV}] Il nome deriva da \textit{segment violation}, e - significa che il programma sta cercando di leggere o scrivere in una zona di - memoria protetta al di fuori di quella che gli è stata riservata dal - sistema. In genere è il meccanismo della protezione della memoria che si - accorge dell'errore ed il kernel genera il segnale. Se il gestore - ritorna il comportamento del processo è indefinito. + una variabile locale, andando a corrompere lo \itindex{stack} + \textit{stack}. Lo stesso segnale viene generato in caso di overflow dello + \itindex{stack} \textit{stack} o di problemi nell'esecuzione di un gestore. + Se il gestore ritorna il comportamento del processo è indefinito. +\item[\const{SIGSEGV}] Il nome deriva da \itindex{segment~violation} + \textit{segment violation}, e significa che il programma sta cercando di + leggere o scrivere in una zona di memoria protetta al di fuori di quella che + gli è stata riservata dal sistema. In genere è il meccanismo della + protezione della memoria che si accorge dell'errore ed il kernel genera il + segnale. Se il gestore ritorna il comportamento del processo è indefinito. È tipico ottenere questo segnale dereferenziando un puntatore nullo o non inizializzato leggendo al di là della fine di un vettore. @@ -476,9 +476,9 @@ programma al momento della terminazione. Questi segnali sono: \const{SIGSEGV} questo è un segnale che viene generato di solito quando si dereferenzia un puntatore non inizializzato, la differenza è che \const{SIGSEGV} indica un accesso non permesso su un indirizzo esistente - (tipo fuori dallo heap o dallo \itindex{stack} stack), mentre \const{SIGBUS} - indica l'accesso ad un indirizzo non valido, come nel caso di un puntatore - non allineato. + (tipo fuori dallo heap o dallo \itindex{stack} \textit{stack}), mentre + \const{SIGBUS} indica l'accesso ad un indirizzo non valido, come nel caso di + un puntatore non allineato. \item[\const{SIGABRT}] Il nome deriva da \textit{abort}. Il segnale indica che il programma stesso ha rilevato un errore che viene riportato chiamando la funzione \func{abort} che genera questo segnale. @@ -1765,9 +1765,10 @@ tab.~\ref{tab:sig_sa_flag}. semantica inaffidabile.\\ \const{SA\_ONESHOT} & Nome obsoleto, sinonimo non standard di \const{SA\_RESETHAND}; da evitare.\\ - \const{SA\_ONSTACK} & Stabilisce l'uso di uno \itindex{stack} stack - alternativo per l'esecuzione del gestore (vedi - sez.~\ref{sec:sig_specific_features}).\\ + \const{SA\_ONSTACK} & Stabilisce l'uso di uno \itindex{stack} + \textit{stack} alternativo per l'esecuzione del + gestore (vedi + sez.~\ref{sec:sig_specific_features}).\\ \const{SA\_RESTART} & Riavvia automaticamente le \textit{slow system call} quando vengono interrotte dal suddetto segnale; riproduce cioè il comportamento standard @@ -1895,7 +1896,7 @@ estremamente semplice, le funzioni piccole ed usate di frequente (in particolare nel kernel, dove in certi casi le ottimizzazioni dal compilatore, tarate per l'uso in user space, non sono sempre adatte). In tal caso infatti le istruzioni per creare - un nuovo frame nello \itindex{stack} stack per chiamare la funzione + un nuovo frame nello \itindex{stack} \textit{stack} per chiamare la funzione costituirebbero una parte rilevante del codice, appesantendo inutilmente il programma. Originariamente questo comportamento veniva ottenuto con delle macro, ma queste hanno tutta una serie di problemi di sintassi nel passaggio @@ -2092,52 +2093,54 @@ escluderne l'avvenuto invio al momento della chiamata non significa nulla rispetto a quanto potrebbe essere in un qualunque momento successivo. Una delle caratteristiche di BSD, disponibile anche in Linux, è la possibilità -di usare uno \itindex{stack} stack alternativo per i segnali; è cioè possibile -fare usare al sistema un altro \itindex{stack} stack (invece di quello -relativo al processo, vedi sez.~\ref{sec:proc_mem_layout}) solo durante -l'esecuzione di un gestore. L'uso di uno stack alternativo è del tutto -trasparente ai gestori, occorre però seguire una certa procedura: +di usare uno \itindex{stack} \textit{stack} alternativo per i segnali; è cioè +possibile fare usare al sistema un altro \itindex{stack} \textit{stack} +(invece di quello relativo al processo, vedi sez.~\ref{sec:proc_mem_layout}) +solo durante l'esecuzione di un gestore. L'uso di uno \textit{stack} +alternativo è del tutto trasparente ai gestori, occorre però seguire una certa +procedura: \begin{enumerate} \item Allocare un'area di memoria di dimensione sufficiente da usare come - stack alternativo; + \textit{stack} alternativo; \item Usare la funzione \func{sigaltstack} per rendere noto al sistema - l'esistenza e la locazione dello stack alternativo; + l'esistenza e la locazione dello \textit{stack} alternativo; \item Quando si installa un gestore occorre usare \func{sigaction} specificando il flag \const{SA\_ONSTACK} (vedi tab.~\ref{tab:sig_sa_flag}) - per dire al sistema di usare lo stack alternativo durante l'esecuzione del - gestore. + per dire al sistema di usare lo \textit{stack} alternativo durante + l'esecuzione del gestore. \end{enumerate} In genere il primo passo viene effettuato allocando un'opportuna area di memoria con \code{malloc}; in \file{signal.h} sono definite due costanti, \const{SIGSTKSZ} e \const{MINSIGSTKSZ}, che possono essere utilizzate per allocare una quantità di spazio opportuna, in modo da evitare overflow. La -prima delle due è la dimensione canonica per uno \itindex{stack} stack di -segnali e di norma è sufficiente per tutti gli usi normali. +prima delle due è la dimensione canonica per uno \itindex{stack} +\textit{stack} di segnali e di norma è sufficiente per tutti gli usi normali. La seconda è lo spazio che occorre al sistema per essere in grado di lanciare -il gestore e la dimensione di uno stack alternativo deve essere sempre -maggiore di questo valore. Quando si conosce esattamente quanto è lo spazio -necessario al gestore gli si può aggiungere questo valore per allocare uno -\itindex{stack} stack di dimensione sufficiente. - -Come accennato, per poter essere usato, lo \itindex{stack} stack per i segnali -deve essere indicato al sistema attraverso la funzione \funcd{sigaltstack}; il -suo prototipo è: +il gestore e la dimensione di uno \textit{stack} alternativo deve essere +sempre maggiore di questo valore. Quando si conosce esattamente quanto è lo +spazio necessario al gestore gli si può aggiungere questo valore per allocare +uno \itindex{stack} \textit{stack} di dimensione sufficiente. + +Come accennato, per poter essere usato, lo \itindex{stack} \textit{stack} per +i segnali deve essere indicato al sistema attraverso la funzione +\funcd{sigaltstack}; il suo prototipo è: \begin{prototype}{signal.h} {int sigaltstack(const stack\_t *ss, stack\_t *oss)} -Installa un nuovo stack per i segnali. +Installa un nuovo \textit{stack} per i segnali. \bodydesc{La funzione restituisce zero in caso di successo e $-1$ per un errore, nel qual caso \var{errno} assumerà i valori: \begin{errlist} - \item[\errcode{ENOMEM}] la dimensione specificata per il nuovo stack è minore - di \const{MINSIGSTKSZ}. + \item[\errcode{ENOMEM}] la dimensione specificata per il nuovo + \textit{stack} è minore di \const{MINSIGSTKSZ}. \item[\errcode{EPERM}] uno degli indirizzi non è valido. - \item[\errcode{EFAULT}] si è cercato di cambiare lo stack alternativo mentre - questo è attivo (cioè il processo è in esecuzione su di esso). + \item[\errcode{EFAULT}] si è cercato di cambiare lo \textit{stack} + alternativo mentre questo è attivo (cioè il processo è in esecuzione su di + esso). \item[\errcode{EINVAL}] \param{ss} non è nullo e \var{ss\_flags} contiene un valore diverso da zero che non è \const{SS\_DISABLE}. \end{errlist}} @@ -2146,8 +2149,8 @@ Installa un nuovo stack per i segnali. La funzione prende come argomenti puntatori ad una struttura di tipo \var{stack\_t}, definita in fig.~\ref{fig:sig_stack_t}. I due valori \param{ss} e \param{oss}, se non nulli, indicano rispettivamente il nuovo -\itindex{stack} stack da installare e quello corrente (che viene restituito -dalla funzione per un successivo ripristino). +\itindex{stack} \textit{stack} da installare e quello corrente (che viene +restituito dalla funzione per un successivo ripristino). \begin{figure}[!htb] \footnotesize \centering @@ -2160,33 +2163,35 @@ dalla funzione per un successivo ripristino). \end{figure} Il campo \var{ss\_sp} di \struct{stack\_t} indica l'indirizzo base dello -\itindex{stack} stack, mentre \var{ss\_size} ne indica la dimensione; il campo -\var{ss\_flags} invece indica lo stato dello stack. Nell'indicare un nuovo -stack occorre inizializzare \var{ss\_sp} e \var{ss\_size} rispettivamente al -puntatore e alla dimensione della memoria allocata, mentre \var{ss\_flags} -deve essere nullo. Se invece si vuole disabilitare uno stack occorre indicare -\const{SS\_DISABLE} come valore di \var{ss\_flags} e gli altri valori saranno -ignorati. +\itindex{stack} \textit{stack}, mentre \var{ss\_size} ne indica la dimensione; +il campo \var{ss\_flags} invece indica lo stato dello \textit{stack}. +Nell'indicare un nuovo \textit{stack} occorre inizializzare \var{ss\_sp} e +\var{ss\_size} rispettivamente al puntatore e alla dimensione della memoria +allocata, mentre \var{ss\_flags} deve essere nullo. Se invece si vuole +disabilitare uno \textit{stack} occorre indicare \const{SS\_DISABLE} come +valore di \var{ss\_flags} e gli altri valori saranno ignorati. Se \param{oss} non è nullo verrà restituito dalla funzione indirizzo e -dimensione dello \itindex{stack} stack corrente nei relativi campi, mentre -\var{ss\_flags} potrà assumere il valore \const{SS\_ONSTACK} se il processo è -in esecuzione sullo stack alternativo (nel qual caso non è possibile -cambiarlo) e \const{SS\_DISABLE} se questo non è abilitato. - -In genere si installa uno \itindex{stack} stack alternativo per i segnali -quando si teme di avere problemi di esaurimento dello stack standard o di -superamento di un limite (vedi sez.~\ref{sec:sys_resource_limit}) imposto con -chiamate del tipo \code{setrlimit(RLIMIT\_STACK, \&rlim)}. In tal caso -infatti si avrebbe un segnale di \const{SIGSEGV}, che potrebbe essere gestito -soltanto avendo abilitato uno \itindex{stack} stack alternativo. - -Si tenga presente che le funzioni chiamate durante l'esecuzione sullo stack -alternativo continueranno ad usare quest'ultimo, che, al contrario di quanto -avviene per lo \itindex{stack} stack ordinario dei processi, non si accresce -automaticamente (ed infatti eccederne le dimensioni può portare a conseguenze -imprevedibili). Si ricordi infine che una chiamata ad una funzione della -famiglia \func{exec} cancella ogni stack alternativo. +dimensione dello \itindex{stack} \textit{stack} corrente nei relativi campi, +mentre \var{ss\_flags} potrà assumere il valore \const{SS\_ONSTACK} se il +processo è in esecuzione sullo \textit{stack} alternativo (nel qual caso non è +possibile cambiarlo) e \const{SS\_DISABLE} se questo non è abilitato. + +In genere si installa uno \itindex{stack} \textit{stack} alternativo per i +segnali quando si teme di avere problemi di esaurimento dello \textit{stack} +standard o di superamento di un limite (vedi +sez.~\ref{sec:sys_resource_limit}) imposto con chiamate del tipo +\code{setrlimit(RLIMIT\_STACK, \&rlim)}. In tal caso infatti si avrebbe un +segnale di \const{SIGSEGV}, che potrebbe essere gestito soltanto avendo +abilitato uno \itindex{stack} \textit{stack} alternativo. + +Si tenga presente che le funzioni chiamate durante l'esecuzione sullo +\textit{stack} alternativo continueranno ad usare quest'ultimo, che, al +contrario di quanto avviene per lo \itindex{stack} \textit{stack} ordinario +dei processi, non si accresce automaticamente (ed infatti eccederne le +dimensioni può portare a conseguenze imprevedibili). Si ricordi infine che +una chiamata ad una funzione della famiglia \func{exec} cancella ogni +\textit{stack} alternativo. Abbiamo visto in fig.~\ref{fig:sig_sleep_incomplete} come si possa usare \func{longjmp} per uscire da un gestore rientrando direttamente nel corpo @@ -2212,7 +2217,7 @@ due comportamenti il programma deve assumere; i loro prototipi sono: \headdecl{setjmp.h} \funcdecl{int sigsetjmp(sigjmp\_buf env, int savesigs)} Salva il contesto - dello stack per un \index{salto~non-locale} salto non-locale. + dello \textit{stack} per un \index{salto~non-locale} salto non-locale. \funcdecl{void siglongjmp(sigjmp\_buf env, int val)} Esegue un salto non-locale su un precedente contesto. @@ -2223,7 +2228,7 @@ due comportamenti il programma deve assumere; i loro prototipi sono: \end{functions} Le due funzioni prendono come primo argomento la variabile su cui viene -salvato il contesto dello \itindex{stack} stack per permettere il +salvato il contesto dello \itindex{stack} \textit{stack} per permettere il \index{salto~non-locale} salto non-locale; nel caso specifico essa è di tipo \type{sigjmp\_buf}, e non \type{jmp\_buf} come per le analoghe di sez.~\ref{sec:proc_longjmp} in quanto in questo caso viene salvata anche la @@ -2246,7 +2251,7 @@ corrispondenza all'interruzione in un punto qualunque del programma principale, ed ad esempio può essere problematico chiamare all'interno di un gestore di segnali la stessa funzione che dal segnale è stata interrotta. -\index{funzioni~sicure|(} +\index{funzioni!sicure|(} Il concetto è comunque più generale e porta ad una distinzione fra quelle che che POSIX chiama \textsl{funzioni insicure} (\textit{n'Usane function}) e @@ -2304,7 +2309,7 @@ riportata in fig.~\ref{fig:sig_safe_functions}. \label{fig:sig_safe_functions} \end{figure} -\index{funzioni~sicure|)} +\index{funzioni!sicure|)} Per questo motivo è opportuno mantenere al minimo indispensabile le operazioni effettuate all'interno di un gestore di segnali, qualora si debbano compiere @@ -2316,7 +2321,7 @@ che si \section{Funzionalità avanzate} -\label{sec:sig_real_time} +\label{sec:sig_advanced_signal} Tratteremo in questa ultima sezione alcune funzionalità avanzate relativa ai @@ -2473,9 +2478,9 @@ caratteristiche tipiche dei segnali real-time (priorit Lo standard POSIX.1b definisce inoltre delle nuove funzioni che permettono di gestire l'attesa di segnali specifici su una coda, esse servono in particolar -modo nel caso dei thread, in cui si possono usare i segnali real-time come -meccanismi di comunicazione elementare; la prima di queste funzioni è -\funcd{sigwait}, il cui prototipo è: +modo nel caso dei \itindex{thread} \textit{thread}, in cui si possono usare i +segnali real-time come meccanismi di comunicazione elementare; la prima di +queste funzioni è \funcd{sigwait}, il cui prototipo è: \begin{prototype}{signal.h} {int sigwait(const sigset\_t *set, int *sig)} @@ -2509,8 +2514,8 @@ consegnato che essere ricevuto da \func{sigwait}, il tutto in maniera non prevedibile. Lo standard POSIX.1b definisce altre due funzioni, anch'esse usate -prevalentemente con i thread; \funcd{sigwaitinfo} e \funcd{sigtimedwait}, i -relativi prototipi sono: +prevalentemente con i \itindex{thread} \textit{thread}; \funcd{sigwaitinfo} e +\funcd{sigtimedwait}, i relativi prototipi sono: \begin{functions} \headdecl{signal.h} @@ -2550,15 +2555,20 @@ di timeout nullo, e non ci sono segnali pendenti la funzione ritorner immediatamente; in questo modo si può eliminare un segnale dalla coda senza dover essere bloccati qualora esso non sia presente. +\itindbeg{thread} + L'uso di queste funzioni è principalmente associato alla gestione dei segnali -con i thread. In genere esse vengono chiamate dal thread incaricato della -gestione, che al ritorno della funzione esegue il codice che usualmente -sarebbe messo nel gestore, per poi ripetere la chiamata per mettersi in attesa -del segnale successivo. Questo ovviamente comporta che non devono essere -installati gestori, che solo il thread di gestione deve usare \func{sigwait} e -che, per evitare che venga eseguita l'azione predefinita, i segnali gestiti in -questa maniera devono essere mascherati per tutti i thread, compreso quello -dedicato alla gestione, che potrebbe riceverlo fra due chiamate successive. +con i \textit{thread}. In genere esse vengono chiamate dal \textit{thread} +incaricato della gestione, che al ritorno della funzione esegue il codice che +usualmente sarebbe messo nel gestore, per poi ripetere la chiamata per +mettersi in attesa del segnale successivo. Questo ovviamente comporta che non +devono essere installati gestori, che solo il \textit{thread} di gestione deve +usare \func{sigwait} e che, per evitare che venga eseguita l'azione +predefinita, i segnali gestiti in questa maniera devono essere mascherati per +tutti i \textit{thread}, compreso quello dedicato alla gestione, che potrebbe +riceverlo fra due chiamate successive. + +\itindend{thread} \subsection{La gestione avanzata delle temporizzazioni} diff --git a/sockctrl.tex b/sockctrl.tex index 7098873..98d1b10 100644 --- a/sockctrl.tex +++ b/sockctrl.tex @@ -781,25 +781,25 @@ ci sono precauzioni particolari da prendere.\footnote{volendo essere pignoli Le funzioni illustrate finora hanno un difetto: utilizzando una area di memoria interna per allocare i contenuti della struttura \struct{hostent} non -possono essere rientranti. Questo comporta anche che in due successive -chiamate i dati potranno essere sovrascritti. Si tenga presente poi che -copiare il contenuto della sola struttura non è sufficiente per salvare tutti -i dati, in quanto questa contiene puntatori ad altri dati, che pure possono -essere sovrascritti; per questo motivo, se si vuole salvare il risultato di -una chiamata, occorrerà eseguire quella che si chiama una \itindex{deep~copy} -\textit{deep copy}.\footnote{si chiama così quella tecnica per cui, quando si - deve copiare il contenuto di una struttura complessa (con puntatori che - puntano ad altri dati, che a loro volta possono essere puntatori ad altri - dati) si deve copiare non solo il contenuto della struttura, ma eseguire una - scansione per risolvere anche tutti i puntatori contenuti in essa (e così - via se vi sono altre sotto-strutture con altri puntatori) e copiare anche i - dati da questi referenziati.} +possono essere\index{funzioni!rientranti} rientranti. Questo comporta anche +che in due successive chiamate i dati potranno essere sovrascritti. Si tenga +presente poi che copiare il contenuto della sola struttura non è sufficiente +per salvare tutti i dati, in quanto questa contiene puntatori ad altri dati, +che pure possono essere sovrascritti; per questo motivo, se si vuole salvare +il risultato di una chiamata, occorrerà eseguire quella che si chiama una +\itindex{deep~copy} \textit{deep copy}.\footnote{si chiama così quella tecnica + per cui, quando si deve copiare il contenuto di una struttura complessa (con + puntatori che puntano ad altri dati, che a loro volta possono essere + puntatori ad altri dati) si deve copiare non solo il contenuto della + struttura, ma eseguire una scansione per risolvere anche tutti i puntatori + contenuti in essa (e così via se vi sono altre sotto-strutture con altri + puntatori) e copiare anche i dati da questi referenziati.} Per ovviare a questi problemi nelle \acr{glibc} sono definite anche delle -versioni rientranti delle precedenti funzioni, al solito queste sono -caratterizzate dall'avere un suffisso \texttt{\_r}, pertanto avremo le due -funzioni \funcd{gethostbyname\_r} e \funcd{gethostbyname2\_r} i cui prototipi -sono: +versioni \index{funzioni!rientranti} rientranti delle precedenti funzioni, al +solito queste sono caratterizzate dall'avere un suffisso \texttt{\_r}, +pertanto avremo le due funzioni \funcd{gethostbyname\_r} e +\funcd{gethostbyname2\_r} i cui prototipi sono: \begin{functions} \headdecl{netdb.h} \headdecl{sys/socket.h} @@ -837,8 +837,8 @@ In caso di successo entrambe le funzioni restituiscono un valore nullo, altrimenti restituiscono un codice di errore negativo e all'indirizzo puntato da \param{result} sarà salvato un puntatore nullo, mentre a quello puntato da \param{h\_errnop} sarà salvato il valore del codice di errore, dato che per -essere rientrante la funzione non può la variabile globale \var{h\_errno}. In -questo caso il codice di errore, oltre ai valori di +essere \index{funzioni!rientranti} rientrante la funzione non può la variabile +globale \var{h\_errno}. In questo caso il codice di errore, oltre ai valori di tab.~\ref{tab:h_errno_values}, può avere anche quello di \errcode{ERANGE} qualora il buffer allocato su \param{buf} non sia sufficiente a contenere i dati, in tal caso si dovrà semplicemente ripetere l'esecuzione della funzione @@ -1103,7 +1103,7 @@ specificati; se la risoluzione ha successo viene restituito un puntatore ad una apposita struttura \struct{servent} contenente tutti i risultati, altrimenti viene restituito un puntatore nullo. Si tenga presente che anche in questo caso i dati vengono mantenuti in una area di memoria statica e che -quindi la funzione non è rientrante. +quindi la funzione non è \index{funzioni!rientranti} rientrante. \begin{figure}[!htb] \footnotesize \centering @@ -1265,11 +1265,11 @@ Come ultimo argomento in \param{res} deve essere passato un puntatore ad una variabile (di tipo puntatore ad una struttura \struct{addrinfo}) che verrà utilizzata dalla funzione per riportare (come \itindex{value~result~argument} \textit{value result argument}) i propri risultati. La funzione infatti è -rientrante, ed alloca autonomamente tutta la memoria necessaria in cui -verranno riportati i risultati della risoluzione. La funzione scriverà -all'indirizzo puntato da \param{res} il puntatore iniziale ad una -\itindex{linked~list} \textit{linked list} di strutture di tipo -\struct{addrinfo} contenenti tutte le informazioni ottenute. +\index{funzioni!rientranti} rientrante, ed alloca autonomamente tutta la +memoria necessaria in cui verranno riportati i risultati della risoluzione. +La funzione scriverà all'indirizzo puntato da \param{res} il puntatore +iniziale ad una \itindex{linked~list} \textit{linked list} di strutture di +tipo \struct{addrinfo} contenenti tutte le informazioni ottenute. \begin{figure}[!htb] \footnotesize \centering diff --git a/socket.tex b/socket.tex index c5150d9..75ae09d 100644 --- a/socket.tex +++ b/socket.tex @@ -956,7 +956,7 @@ L'ultima funzione, \func{inet\_ntoa}, converte il valore a 32 bit dell'indirizzo (espresso in \textit{network order}) restituendo il puntatore alla stringa che contiene l'espressione in formato dotted decimal. Si deve tenere presente che la stringa risiede in memoria statica, per cui questa -funzione non è rientrante. +funzione non è \index{funzioni!rientranti} rientrante. \subsection{Le funzioni \func{inet\_pton} e \func{inet\_ntop}} diff --git a/system.tex b/system.tex index 41f43d9..797f953 100644 --- a/system.tex +++ b/system.tex @@ -1020,9 +1020,9 @@ La struttura usata da entrambe le funzioni motivo viene sovrascritta ad ogni nuova invocazione, lo stesso dicasi per la memoria dove sono scritte le stringhe a cui i puntatori in essa contenuti fanno riferimento. Ovviamente questo implica che dette funzioni non possono -essere rientranti; per questo motivo ne esistono anche due versioni -alternative (denotate dalla solita estensione \code{\_r}), i cui prototipi -sono: +essere \index{funzioni!rientranti} rientranti; per questo motivo ne esistono +anche due versioni alternative (denotate dalla solita estensione \code{\_r}), +i cui prototipi sono: \begin{functions} \headdecl{pwd.h} @@ -1053,9 +1053,9 @@ funzione fallir impostato a \val{NULL}). Del tutto analoghe alle precedenti sono le funzioni \funcd{getgrnam} e -\funcd{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: +\funcd{getgrgid} (e le relative analoghe \index{funzioni!rientranti} +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} @@ -1116,19 +1116,23 @@ file di \textsl{registro} di utenti e gruppi, con il formato classico di \hline \func{fgetpwent} & Legge una voce dal file di registro degli utenti specificato.\\ - \func{fgetpwent\_r}& Come la precedente, ma rientrante.\\ + \func{fgetpwent\_r}& Come la precedente, ma \index{funzioni!rientranti} + rientrante.\\ \func{putpwent} & Immette una voce in un file di registro degli utenti.\\ \func{getpwent} & Legge una voce da \conffile{/etc/passwd}.\\ - \func{getpwent\_r} & Come la precedente, ma rientrante.\\ + \func{getpwent\_r} & Come la precedente, ma \index{funzioni!rientranti} + rientrante.\\ \func{setpwent} & Ritorna all'inizio di \conffile{/etc/passwd}.\\ \func{endpwent} & Chiude \conffile{/etc/passwd}.\\ \func{fgetgrent} & Legge una voce dal file di registro dei gruppi specificato.\\ - \func{fgetgrent\_r}& Come la precedente, ma rientrante.\\ + \func{fgetgrent\_r}& Come la precedente, ma \index{funzioni!rientranti} + rientrante.\\ \func{putgrent} & Immette una voce in un file di registro dei gruppi.\\ \func{getgrent} & Legge una voce da \conffile{/etc/group}.\\ - \func{getgrent\_r} & Come la precedente, ma rientrante.\\ + \func{getgrent\_r} & Come la precedente, ma \index{funzioni!rientranti} + rientrante.\\ \func{setgrent} & Ritorna all'inizio di \conffile{/etc/group}.\\ \func{endgrent} & Chiude \conffile{/etc/group}.\\ \hline @@ -1330,14 +1334,16 @@ gestione (\func{getutxent}, \func{getutxid}, \func{getutxline}, sinonimi delle funzioni appena viste. Come visto in sez.~\ref{sec:sys_user_group}, l'uso di strutture allocate -staticamente rende le funzioni di lettura non rientranti; per questo motivo le -\acr{glibc} forniscono anche delle versioni rientranti: \func{getutent\_r}, -\func{getutid\_r}, \func{getutline\_r}, che invece di restituire un puntatore -restituiscono un intero e prendono due argomenti aggiuntivi. Le funzioni si -comportano esattamente come le analoghe non rientranti, solo che restituiscono -il risultato all'indirizzo specificato dal primo argomento aggiuntivo (di tipo -\code{struct utmp *buffer}) mentre il secondo (di tipo \code{struct utmp - **result)} viene usato per restituire il puntatore allo stesso buffer. +staticamente rende le funzioni di lettura non \index{funzioni!rientranti} +rientranti; per questo motivo le \acr{glibc} forniscono anche delle versioni +\index{funzioni!rientranti} rientranti: \func{getutent\_r}, \func{getutid\_r}, +\func{getutline\_r}, che invece di restituire un puntatore restituiscono un +intero e prendono due argomenti aggiuntivi. Le funzioni si comportano +esattamente come le analoghe non \index{funzioni!rientranti} rientranti, solo +che restituiscono il risultato all'indirizzo specificato dal primo argomento +aggiuntivo (di tipo \code{struct utmp *buffer}) mentre il secondo (di tipo +\code{struct utmp **result)} viene usato per restituire il puntatore allo +stesso buffer. Infine le \acr{glibc} forniscono come estensione per la scrittura delle voci in \file{wmtp} altre due funzioni, \funcd{updwtmp} e \funcd{logwtmp}, i cui @@ -1477,7 +1483,7 @@ fatto solo fino al valore del secondo, che per questo viene detto \textit{hard esse falliranno con un errore di \errcode{ENOMEM}, mentre se il superamento viene causato dalla crescita dello \itindex{stack} - stack il processo riceverà un segnale di + \textit{stack} il processo riceverà un segnale di \const{SIGSEGV}.\\ \const{RLIMIT\_CORE} & La massima dimensione per di un file di \itindex{core~dump} \textit{core dump} (vedi @@ -1539,9 +1545,9 @@ fatto solo fino al valore del secondo, che per questo viene detto \textit{hard si potrà sempre inviare un segnale che non sia già presente su una coda.\footnotemark\\ \const{RLIMIT\_STACK} & La massima dimensione dello \itindex{stack} - stack del - processo. Se il processo esegue operazioni che - estendano lo stack oltre questa dimensione + \textit{stack} del processo. Se il processo + esegue operazioni che estendano lo + \textit{stack} oltre questa dimensione riceverà un segnale di \const{SIGSEGV}.\\ \const{RLIMIT\_RSS} & L'ammontare massimo di pagine di memoria dato al \index{segmento!testo} testo del processo. Il @@ -2283,11 +2289,11 @@ stringa, allocata staticamente, nella forma: e impostano anche la variabile \var{tzname} con l'informazione della \textit{time zone} corrente; \func{ctime} è banalmente definita in termini di \func{asctime} come \code{asctime(localtime(t)}. Dato che l'uso di una stringa -statica rende le funzioni non rientranti POSIX.1c e SUSv2 prevedono due -sostitute rientranti, il cui nome è al solito ottenuto aggiungendo un -\code{\_r}, che prendono un secondo argomento \code{char *buf}, in cui -l'utente deve specificare il buffer su cui la stringa deve essere copiata -(deve essere di almeno 26 caratteri). +statica rende le funzioni non \index{funzioni!rientranti} rientranti POSIX.1c +e SUSv2 prevedono due sostitute \index{funzioni!rientranti} rientranti, il cui +nome è al solito ottenuto aggiungendo un \code{\_r}, che prendono un secondo +argomento \code{char *buf}, in cui l'utente deve specificare il buffer su cui +la stringa deve essere copiata (deve essere di almeno 26 caratteri). Le altre tre funzioni, \func{gmtime}, \func{localtime} e \func{mktime} servono per convertire il tempo dal formato \type{time\_t} a quello di \struct{tm} e @@ -2297,9 +2303,10 @@ locale; \func{mktime} esegue la conversione inversa. Anche in questo caso le prime due funzioni restituiscono l'indirizzo di una struttura allocata staticamente, per questo sono state definite anche altre -due versioni rientranti (con la solita estensione \code{\_r}), che prevedono -un secondo argomento \code{struct tm *result}, fornito dal chiamante, che deve -preallocare la struttura su cui sarà restituita la conversione. +due versioni \index{funzioni!rientranti} rientranti (con la solita estensione +\code{\_r}), che prevedono un secondo argomento \code{struct tm *result}, +fornito dal chiamante, che deve preallocare la struttura su cui sarà +restituita la conversione. Come mostrato in fig.~\ref{fig:sys_tm_struct} il \textit{broken-down time} permette di tenere conto anche della differenza fra tempo universale e ora @@ -2427,7 +2434,7 @@ un errore nell'esecuzione di una funzione, ma di norma questo viene riportato semplicemente usando un opportuno valore di ritorno della funzione invocata. Inoltre il sistema di classificazione degli errori è basato sull'architettura a processi, e presenta una serie di problemi nel caso lo si debba usare con i -thread. +\itindex{thread} \textit{thread}. \subsection{La variabile \var{errno}} @@ -2445,10 +2452,11 @@ che c' Per riportare il tipo di errore il sistema usa la variabile globale \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 + problemi (ad esempio nel caso dei \itindex{thread} \textit{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 + \itindex{thread} \textit{thread}.} definita nell'header \file{errno.h}; la variabile è in genere definita come \direct{volatile} dato che può essere cambiata in modo asincrono da un segnale (si veda sez.~\ref{sec:sig_sigchld} per un esempio, ricordando quanto trattato in sez.~\ref{sec:proc_race_cond}), @@ -2508,13 +2516,14 @@ La funzione utilizza una stringa statica che non deve essere modificata dal programma; essa è utilizzabile solo fino ad una chiamata successiva a \func{strerror} o \func{perror}, nessun'altra funzione di libreria tocca questa stringa. In ogni caso l'uso di una stringa statica rende la funzione -non rientrante, per cui nel caso si usino i thread le librerie -forniscono\footnote{questa funzione è la versione prevista dalle \acr{glibc}, - ed effettivamente definita in \file{string.h}, ne esiste una analoga nello - standard SUSv3 (quella riportata dalla pagina di manuale), che restituisce - \code{int} al posto di \code{char *}, e che tronca la stringa restituita a - \param{size}.} una apposita versione rientrante \func{strerror\_r}, il cui -prototipo è: +non \index{funzioni!rientranti} rientrante, per cui nel caso si usino i +\itindex{thread} \textit{thread} le librerie forniscono\footnote{questa + funzione è la versione prevista dalle \acr{glibc}, ed effettivamente + definita in \file{string.h}, ne esiste una analoga nello standard SUSv3 + (quella riportata dalla pagina di manuale), che restituisce \code{int} al + posto di \code{char *}, e che tronca la stringa restituita a + \param{size}.} una apposita versione \index{funzioni!rientranti} rientrante +\func{strerror\_r}, il cui prototipo è: \begin{prototype}{string.h} {char * strerror\_r(int errnum, char *buf, size\_t size)} @@ -2534,9 +2543,10 @@ prototipo \noindent La funzione è analoga a \func{strerror} ma restituisce la stringa di errore -nel buffer \param{buf} che il singolo thread deve allocare autonomamente per -evitare i problemi connessi alla condivisione del buffer statico. Il messaggio -è copiato fino alla dimensione massima del buffer, specificata dall'argomento +nel buffer \param{buf} che il singolo \itindex{thread} \textit{thread} deve +allocare autonomamente per evitare i problemi connessi alla condivisione del +buffer statico. Il messaggio è copiato fino alla dimensione massima del +buffer, specificata dall'argomento \param{size}, che deve comprendere pure il carattere di terminazione; altrimenti la stringa viene troncata. diff --git a/thread.tex b/thread.tex index a42e2cc..87ed4d0 100644 --- a/thread.tex +++ b/thread.tex @@ -12,12 +12,15 @@ \chapter{I thread} \label{cha:threads} + +\itindbeg{thread} + Tratteremo in questo capitolo un modello di programmazione multitasking, quello dei \textit{thread}, alternativo al modello classico dei processi, tipico di Unix. Ne esamineremo le caratteristiche, vantaggi e svantaggi, e le diverse realizzazioni che sono disponibili per Linux; nella seconda parte tratteremo in dettaglio quella che è l'implementazione principale, che fa -riferimento all'interfaccia standardizzata da POSIX.1e. +riferimento all'interfaccia standardizzata da POSIX.1e. \section{Introduzione ai \textit{thread}} @@ -73,7 +76,7 @@ dei processi: \section{Posix \textit{thread}} -\label{sec:thread_intro} +\label{sec:thread_posix_intro} Tratteremo in questa sezione l'interfaccia di programmazione con i @@ -100,6 +103,9 @@ delle \acr{glibc}. \label{sec:pthread_cond} +\itindend{thread} + + % LocalWords: thread multitasking POSIX sez Posix Library kernel glibc mutex -- 2.30.2