Iniziato a rivedere il multiplexing I/O.
[gapil.git] / fileadv.tex
index 2d3ce015b9acb4563d1d9b350f3fbec4937b1dd7..4415602bcce799513de037ee02f7867f09dfc093 100644 (file)
@@ -1,6 +1,6 @@
 %% fileadv.tex
 %%
-%% Copyright (C) 2000-2002 Simone Piccardi.  Permission is granted to
+%% Copyright (C) 2000-2003 Simone Piccardi.  Permission is granted to
 %% copy, distribute and/or modify this document under the terms of the GNU Free
 %% Documentation License, Version 1.1 or any later version published by the
 %% Free Software Foundation; with the Invariant Sections being "Prefazione",
@@ -70,15 +70,15 @@ I/O non bloccante.
 \label{sec:file_multiplexing}
 
 Per superare il problema di dover usare il \textit{polling}\index{polling} per
-controllare la possibilità di effettuare operazioni su un file aperto in
-modalità non bloccante, sia BSD che System V hanno introdotto delle nuove
-funzioni in grado di sospendere l'esecuzione di un processo in attesa che
-l'accesso diventi possibile.  Il primo ad introdurre questa modalità di
-operazione, chiamata usualmente \textit{I/O multiplexing}, è stato
-BSD,\footnote{la funzione è apparsa in BSD4.2 e standardizzata in BSD4.4, ma è
-  stata portata su tutti i sistemi che supportano i
-  \textit{socket}\index{socket}, compreso le varianti di System V.}  con la
-funzione \funcd{select}, il cui prototipo è:
+controllare la possibilità di effettuare operazioni su un gruppo di file
+aperti in modalità non bloccante, sia BSD che System V hanno introdotto delle
+nuove funzioni in grado di sospendere l'esecuzione di un processo fin quando
+l'accesso ad un dato insieme di file diventi possibile.  Il primo ad
+introdurre questa modalità di operazione, chiamata usualmente \textit{I/O
+  multiplexing}, è stato BSD,\footnote{la funzione è apparsa in BSD4.2 e
+  standardizzata in BSD4.4, ma è stata portata su tutti i sistemi che
+  supportano i \textit{socket}\index{socket}, compreso le varianti di System
+  V.}  con la funzione \funcd{select}, il cui prototipo è:
 \begin{functions}
   \headdecl{sys/time.h}
   \headdecl{sys/types.h}
@@ -135,10 +135,14 @@ opportune macro di preprocessore:
 In genere un \textit{file descriptor set} può contenere fino ad un massimo di
 \const{FD\_SETSIZE} file descriptor.  Questo valore in origine corrispondeva
 al limite per il numero massimo di file aperti\footnote{ad esempio in Linux,
-  fino alla serie 2.0.x, c'era un limite di 256 file per processo.}, ma
+  fino alla serie 2.0.x, c'era un limite di 256 file per processo.}, ma da
 quando, come nelle versioni più recenti del kernel, non c'è più un limite
 massimo, esso indica le dimensioni massime dei numeri usati nei \textit{file
-  descriptor set}.
+  descriptor set}.\footnote{il suo valore, secondo lo standard POSIX
+  1003.1-2001, è definito in \file{sys/select.h}, ed è pari a 1024.} Si tenga
+presente che i \textit{file descriptor set} devono sempre essere inizializzati
+con \macro{FD\_ZERO}; passare a \func{select} un valore non inizializzato può
+dar luogo a comportamenti non prevedibili.
 
 La funzione richiede di specificare tre insiemi distinti di file descriptor;
 il primo, \param{readfds}, verrà osservato per rilevare la disponibilità di
@@ -147,17 +151,24 @@ possibilit
 verificare l'esistenza di condizioni eccezionali (come i messaggi urgenti su
 un \textit{socket}\index{socket}, vedi \secref{sec:xxx_urgent}).
 
-La funzione inoltre richiede anche di specificare, tramite l'argomento
-\param{n}, un valore massimo del numero dei file descriptor usati
-nell'insieme; si può usare il già citato \const{FD\_SETSIZE}, oppure il numero
-più alto dei file descriptor usati nei tre insiemi, aumentato di uno.
+Dato che in genere non si tengono mai sotto controllo fino a
+\const{FD\_SETSIZE} file contemporaneamente la funzione richiede di
+specificare qual'è il numero massimo dei file descriptor indicati nei tre
+insiemi precedenti. Questo viene fatto per efficienza, per evitare di passare
+e far controllare al kernel una quantità di memoria superiore a quella
+necessaria. Questo limite viene indicato tramite l'argomento \param{n}, che
+deve corrispondere al valore massimo aumentato di uno.\footnote{i file
+  descriptor infatti sono contati a partire da zero, ed il valore indica il
+  numero di quelli da tenere sotto controllo; dimenticarsi di aumentare di uno
+  il valore di \param{n} è un errore comune.}
 
 Infine l'argomento \param{timeout}, specifica un tempo massimo di
-attesa\footnote{il tempo è valutato come \textit{elapsed time}.} prima che la
-funzione ritorni; se impostato a \val{NULL} la funzione attende
-indefinitamente. Si può specificare anche un tempo nullo (cioè una struttura
-\struct{timeval} con i campi impostati a zero), qualora si voglia
-semplicemente controllare lo stato corrente dei file descriptor.
+attesa\footnote{il tempo è valutato come \textit{clock time} (vedi
+  \secref{sec:sys_unix_time}).} prima che la funzione ritorni; se impostato a
+\val{NULL} la funzione attende indefinitamente. Si può specificare anche un
+tempo nullo (cioè una struttura \struct{timeval} con i campi impostati a
+zero), qualora si voglia semplicemente controllare lo stato corrente dei file
+descriptor.
 
 La funzione restituisce il totale dei file descriptor pronti nei tre insiemi,
 il valore zero indica sempre che si è raggiunto un timeout. Ciascuno dei tre
@@ -167,35 +178,35 @@ operazioni ad esso relative, in modo da poterlo controllare con la macro
 non vengono toccati.
 
 In Linux \func{select} modifica anche il valore di \param{timeout},
-impostandolo al tempo restante; questo è utile quando la funzione viene
-interrotta da un segnale, in tal caso infatti si ha un errore di
-\errcode{EINTR}, ed occorre rilanciare la funzione; in questo modo non è
-necessario ricalcolare tutte le volte il tempo rimanente.\footnote{questo può
-  causare problemi di portabilità sia quando si trasporta codice scritto su
-  Linux che legge questo valore, sia quando si usano programmi scritti per
-  altri sistemi che non dispongono di questa caratteristica e ricalcolano
-  \param{timeout} tutte le volte. In genere la caratteristica è disponibile
-  nei sistemi che derivano da System V e non disponibile per quelli che
-  derivano da BSD.}
-
-Come accennato l'interfaccia di \func{select} è una estensione di BSD; anche
-System V ha introdotto una sua interfaccia per gestire l'\textit{I/O
-  multiplexing}, basata sulla funzione \funcd{poll},\footnote{la funzione è
-  prevista dallo standard XPG4, ed è stata introdotta in Linux come system
-  call a partire dal kernel 2.1.23 e dalle \acr{libc} 5.4.28.} il cui
+impostandolo al tempo restante in caso di interruzione prematura; questo è
+utile quando la funzione viene interrotta da un segnale, in tal caso infatti
+si ha un errore di \errcode{EINTR}, ed occorre rilanciare la funzione; in
+questo modo non è necessario ricalcolare tutte le volte il tempo
+rimanente.\footnote{questo può causare problemi di portabilità sia quando si
+  trasporta codice scritto su Linux che legge questo valore, sia quando si
+  usano programmi scritti per altri sistemi che non dispongono di questa
+  caratteristica e ricalcolano \param{timeout} tutte le volte. In genere la
+  caratteristica è disponibile nei sistemi che derivano da System V e non
+  disponibile per quelli che derivano da BSD.}
+
+Come accennato l'interfaccia di \func{select} è una estensione creata nello
+sviluppo di BSD; anche System V ha introdotto una sua interfaccia per gestire
+l'\textit{I/O multiplexing}, basata sulla funzione \funcd{poll},\footnote{la
+  funzione è prevista dallo standard XPG4, ed è stata introdotta in Linux come
+  system call a partire dal kernel 2.1.23 e dalle \acr{libc} 5.4.28.} il cui
 prototipo è:
 \begin{prototype}{sys/poll.h}
   {int poll(struct pollfd *ufds, unsigned int nfds, int timeout)}
-
-La funzione attente un cambiamento di stato per uno dei file descriptor
-specificati da \param{ufds}.
+  
+  La funzione attende un cambiamento di stato per uno dei file descriptor
+  specificati da \param{ufds}.
   
 \bodydesc{La funzione restituisce il numero di file descriptor con attività in
   caso di successo, o 0 se c'è stato un timeout; in caso di errore viene
   restituito  -1 ed \var{errno} assumerà uno dei valori:
   \begin{errlist}
   \item[\errcode{EBADF}] Si è specificato un file descriptor sbagliato in uno
-  degli insiemi.
+    degli insiemi.
   \item[\errcode{EINTR}] La funzione è stata interrotta da un segnale.
   \end{errlist}
   ed inoltre \errval{EFAULT} e \errval{ENOMEM}.}
@@ -211,17 +222,11 @@ negativo indica un'attesa indefinita).
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
-struct pollfd {
-        int fd;           /* file descriptor */
-        short events;     /* requested events */
-        short revents;    /* returned events */
-};
-    \end{lstlisting}
+    \includestruct{listati/pollfd.h}
   \end{minipage} 
   \normalsize 
-  \caption{La struttura \struct{pollfd}, utilizzata per specificare le modalità
-    di controllo di un file descriptor alla funzione \func{poll}.}
+  \caption{La struttura \structd{pollfd}, utilizzata per specificare le
+    modalità di controllo di un file descriptor alla funzione \func{poll}.}
   \label{fig:file_pollfd}
 \end{figure}
 
@@ -254,7 +259,8 @@ vengono utilizzati solo per \var{revents} come valori in uscita).
     \const{POLLWRNORM}& 0x100 & È possibile la scrittura di dati normali.  \\ 
     \const{POLLWRBAND}& 0x200 & È possibile la scrittura di dati ad 
                                 alta priorità. \\
-    \const{POLLMSG}   & 0x400 & Estensione propria di Linux.\\
+    \const{POLLMSG}   & 0x400 & Un segnale \const{SIGPOLL} è arrivato alla
+                                cima dello stream.\\
     \hline    
   \end{tabular}
   \caption{Costanti per l'identificazione dei vari bit dei campi
@@ -313,12 +319,22 @@ della funzione.
 L'uso di \param{sigmask} è stato introdotto allo scopo di prevenire possibili
 race condition\footnote{in Linux però, non esistendo una system call apposita,
   la funzione è implementata nelle \acr{glibc} usando \func{select}, e la
-  possibilità di una race condition resta.} quando si deve eseguire un test su
-una variabile assegnata da un manipolatore sulla base dell'occorrenza di un
-segnale per decidere se lanciare \func{select}. Fra il test e l'esecuzione è
-presente una finestra in cui potrebbe arrivare il segnale che non sarebbe
-rilevato; la race condition diventa superabile disabilitando il segnale prima
-del test e riabilitandolo poi grazie all'uso di \param{sigmask}.
+  possibilità di una race condition\index{race condition} resta.} quando si
+deve eseguire un test su una variabile assegnata da un gestore sulla base
+dell'occorrenza di un segnale per decidere se lanciare \func{select}. Fra il
+test e l'esecuzione è presente una finestra in cui potrebbe arrivare il
+segnale che non sarebbe rilevato; la race condition\index{race condition}
+diventa superabile disabilitando il segnale prima del test e riabilitandolo
+poi grazie all'uso di \param{sigmask}.
+
+Dato che l'I/O multiplexing serve a risolvere il problema di dover attendere
+la disponibilità di accesso ad un insieme di file, esso viene utilizzato
+prevalentemente per programmi in cui l'accesso ad un file descriptor può
+essere bloccante. Abbiamo già accennato come questo non avvenga mai per i
+normali file su disco; l'uso più comune di queste funzioni infatti è nei
+server di rete, in cui esse vengono utilizzate per tenere sotto controllo vari
+socket; pertanto ritorneremo su di esse con maggiori dettagli e con qualche
+esempio in \secref{sec:TCP_sock_multiplexing}.
 
 
 
@@ -362,14 +378,14 @@ pi
 Linux però supporta le estensioni POSIX.1b dei segnali che permettono di
 superare il problema facendo ricorso alle informazioni aggiuntive restituite
 attraverso la struttura \struct{siginfo\_t}, utilizzando la forma estesa
-\var{sa\_sigaction} del manipolatore (si riveda quanto illustrato in
+\var{sa\_sigaction} del gestore (si riveda quanto illustrato in
 \secref{sec:sig_sigaction}).
 
 Per far questo però occorre utilizzare le funzionalità dei segnali real-time
 (vedi \secref{sec:sig_real_time}) impostando esplicitamente con il comando
 \const{F\_SETSIG} di \func{fcntl} un segnale real-time da inviare in caso di
 I/O asincrono (il segnale predefinito è \const{SIGIO}). In questo caso il
-manipolatore tutte le volte che riceverà \const{SI\_SIGIO} come valore del
+gestore tutte le volte che riceverà \const{SI\_SIGIO} come valore del
 campo \var{si\_code}\footnote{il valore resta \const{SI\_SIGIO} qualunque sia
   il segnale che si è associato all'I/O asincrono, ed indica appunto che il
   segnale è stato generato a causa di attività nell'I/O asincrono.} di
@@ -404,9 +420,10 @@ di thread. Al momento\footnote{fino ai kernel della serie 2.4.x, nella serie
   di I/O, che prevede anche l'introduzione di un nuovo layer per l'I/O
   asincrono (effettuato a partire dal 2.5.32).} esiste una sola versione
 stabile di questa interfaccia, quella delle \acr{glibc}, che è realizzata
-completamente in user space.  Esistono comunque vari progetti sperimentali
-(come il KAIO della SGI, o i patch di Benjamin La Haise) che prevedono un
-supporto diretto da parte del kernel.
+completamente in user space, ed accessibile linkando i programmi con la
+libreria \file{librt}.  Esistono comunque vari progetti sperimentali (come il
+KAIO della SGI, o i patch di Benjamin La Haise) che prevedono un supporto
+diretto da parte del kernel.
 
 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
@@ -419,21 +436,10 @@ disponibilit
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
-struct aiocb
-{
-    int aio_fildes;               /* File descriptor.  */
-    off_t aio_offset;             /* File offset */
-    int aio_lio_opcode;           /* Operation to be performed.  */
-    int aio_reqprio;              /* Request priority offset.  */
-    volatile void *aio_buf;       /* Location of buffer.  */
-    size_t aio_nbytes;            /* Length of transfer.  */
-    struct sigevent aio_sigevent; /* Signal number and value.  */
-};
-    \end{lstlisting}
+    \includestruct{listati/aiocb.h}
   \end{minipage} 
   \normalsize 
-  \caption{La struttura \struct{aiocb}, usata per il controllo dell'I/O
+  \caption{La struttura \structd{aiocb}, usata per il controllo dell'I/O
     asincrono.}
   \label{fig:file_aiocb}
 \end{figure}
@@ -469,20 +475,11 @@ esse.
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
-struct sigevent
-{
-    sigval_t sigev_value;
-    int sigev_signo;
-    int sigev_notify;
-    sigev_notify_function;
-    sigev_notify_attributes;
-};
-    \end{lstlisting}
+    \includestruct{listati/sigevent.h}
   \end{minipage} 
   \normalsize 
-  \caption{La struttura \struct{sigevent}, usata per specificare le modalità di
-    notifica degli eventi relativi alle operazioni di I/O asincrono.}
+  \caption{La struttura \structd{sigevent}, usata per specificare le modalità
+    di notifica degli eventi relativi alle operazioni di I/O asincrono.}
   \label{fig:file_sigevent}
 \end{figure}
 
@@ -492,15 +489,17 @@ notifica del completamento delle operazioni richieste. La struttura 
 riportata in \secref{fig:file_sigevent}; il campo \var{sigev\_notify} è quello
 che indica le modalità della notifica, esso può assumere i tre valori:
 \begin{basedescript}{\desclabelwidth{3.0cm}}
-\item[\const{SIGEV\_NONE}]   Non viene inviata nessuna notifica.
+\item[\const{SIGEV\_NONE}]  Non viene inviata nessuna notifica.
 \item[\const{SIGEV\_SIGNAL}] La notifica viene effettuata inviando al processo
-  chiamante il segnale specificato nel campo \var{sigev\_signo}, se il
-  manipolatore è installato con \const{SA\_SIGINFO}, il gli verrà restituito
-  il valore di \var{sigev\_value} in come valore del campo \var{si\_value} per
+  chiamante il segnale specificato da \var{sigev\_signo}; se il gestore di
+  questo è stato installato con \const{SA\_SIGINFO} gli verrà restituito il
+  valore di \var{sigev\_value} (la cui definizione è in
+  \figref{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 gli attributi specificati da \var{sigev\_notify\_attribute}.
+  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
@@ -814,15 +813,10 @@ il secondo, \var{iov\_len}, la dimensione dello stesso.
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
-struct iovec {
-    __ptr_t iov_base;    /* Starting address */
-    size_t iov_len;      /* Length in bytes  */
-};
-    \end{lstlisting}
+    \includestruct{listati/iovec.h}
   \end{minipage} 
   \normalsize 
-  \caption{La struttura \struct{iovec}, usata dalle operazioni di I/O
+  \caption{La struttura \structd{iovec}, usata dalle operazioni di I/O
     vettorizzato.} 
   \label{fig:file_iovec}
 \end{figure}
@@ -1129,14 +1123,14 @@ Pertanto se si modifica un file con l'interfaccia standard queste modifiche
 potranno essere visibili o meno a seconda del momento in cui la memoria
 virtuale trasporterà dal disco in memoria quella sezione del file, perciò è
 del tutto imprevedibile il risultato della modifica di un file nei confronti
-del contenuto della memoria mappata su cui è mappato.
-
-Per quanto appena visto, è sempre sconsigliabile eseguire scritture su file
-attraverso l'interfaccia standard, quando lo si è mappato in memoria, è invece
-possibile usare l'interfaccia standard per leggere un file mappato in memoria,
-purché si abbia una certa cura; infatti l'interfaccia dell'I/O mappato in
-memoria mette a disposizione la funzione \funcd{msync} per sincronizzare il
-contenuto della memoria mappata con il file su disco; il suo prototipo è:
+del contenuto della memoria su cui è mappato.
+
+Per questo, è sempre sconsigliabile eseguire scritture su file attraverso
+l'interfaccia standard, quando lo si è mappato in memoria, è invece possibile
+usare l'interfaccia standard per leggere un file mappato in memoria, purché si
+abbia una certa cura; infatti l'interfaccia dell'I/O mappato in memoria mette
+a disposizione la funzione \funcd{msync} per sincronizzare il contenuto della
+memoria mappata con il file su disco; il suo prototipo è:
 \begin{functions}  
   \headdecl{unistd.h}
   \headdecl{sys/mman.h} 
@@ -1240,9 +1234,10 @@ processi scrivono, mescolando in maniera imprevedibile il loro output sul
 file.
 
 In tutti questi casi il \textit{file locking} è la tecnica che permette di
-evitare le race condition, attraverso una serie di funzioni che permettono di
-bloccare l'accesso al file da parte di altri processi, così da evitare le
-sovrapposizioni, e garantire la atomicità delle operazioni di scrittura.
+evitare le race condition\index{race condition}, attraverso una serie di
+funzioni che permettono di bloccare l'accesso al file da parte di altri
+processi, così da evitare le sovrapposizioni, e garantire la atomicità delle
+operazioni di scrittura.
 
 
 
@@ -1507,18 +1502,10 @@ regione bloccata.
 \begin{figure}[!bht]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
-struct flock {
-    short int l_type;   /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK.  */
-    short int l_whence; /* Where `l_start' is relative to (like `lseek').  */
-    off_t l_start;      /* Offset where the lock begins.  */
-    off_t l_len;        /* Size of the locked area; zero means until EOF.  */
-    pid_t l_pid;        /* Process holding the lock.  */
-};
-    \end{lstlisting}
+    \includestruct{listati/flock.h}
   \end{minipage} 
   \normalsize 
-  \caption{La struttura \struct{flock}, usata da \func{fcntl} per il file
+  \caption{La struttura \structd{flock}, usata da \func{fcntl} per il file
     locking.} 
   \label{fig:struct_flock}
 \end{figure}
@@ -1712,60 +1699,7 @@ necessario a soddisfare l'operazione richiesta.
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}{}
-int main(int argc, char *argv[])
-{
-    int type = F_UNLCK;            /* lock type: default to unlock (invalid) */
-    off_t start = 0;             /* start of the locked region: default to 0 */
-    off_t len = 0;              /* length of the locked region: default to 0 */
-    int fd, res, i;                                    /* internal variables */
-    int bsd = 0;                          /* semantic type: default to POSIX */
-    int cmd = F_SETLK;              /* lock command: default to non-blocking */
-    struct flock lock;                                /* file lock structure */
-    ...
-    if ((argc - optind) != 1) {          /* There must be remaing parameters */
-        printf("Wrong number of arguments %d\n", argc - optind);
-        usage();
-    }
-    if (type == F_UNLCK) {            /* There must be a -w or -r option set */
-        printf("You should set a read or a write lock\n");
-        usage();
-    }
-    fd = open(argv[optind], O_RDWR);           /* open the file to be locked */
-    if (fd < 0) {                                           /* on error exit */
-        perror("Wrong filename");
-        exit(1);
-    }
-    /* do lock */
-    if (bsd) {                                             /* if BSD locking */
-        /* rewrite cmd for suitables flock operation values */ 
-        if (cmd == F_SETLKW) {                             /* if no-blocking */
-            cmd = LOCK_NB;              /* set the value for flock operation */
-        } else {                                                     /* else */
-            cmd = 0;                                      /* default is null */
-        }
-        if (type == F_RDLCK) cmd |= LOCK_SH;          /* set for shared lock */
-        if (type == F_WRLCK) cmd |= LOCK_EX;       /* set for exclusive lock */
-        res = flock(fd, cmd);                                /* esecute lock */
-    } else {                                             /* if POSIX locking */
-        /* setting flock structure */
-        lock.l_type = type;                       /* set type: read or write */
-        lock.l_whence = SEEK_SET;    /* start from the beginning of the file */
-        lock.l_start = start;          /* set the start of the locked region */
-        lock.l_len = len;             /* set the length of the locked region */
-        res = fcntl(fd, cmd, &lock);                              /* do lock */
-    }
-    /* check lock results */
-    if (res) {                                              /* on error exit */
-        perror("Failed lock");
-        exit(1);
-    } else {                                           /* else write message */
-        printf("Lock acquired\n");
-    }
-    pause();                       /* stop the process, use a signal to exit */
-    return 0;
-}
-    \end{lstlisting}
+    \includecodesample{listati/Flock.c}
   \end{minipage} 
   \normalsize 
   \caption{Sezione principale del codice del programma \file{Flock.c}.}
@@ -2033,7 +1967,7 @@ opportune verifiche nei processi, questo verrebbe comunque rispettato.
 Per poter utilizzare il \textit{mandatory locking} è stato introdotto un
 utilizzo particolare del bit \acr{sgid}. Se si ricorda quanto esposto in
 \secref{sec:file_suid_sgid}), esso viene di norma utilizzato per cambiare il
-groupid effettivo con cui viene eseguito un programma, ed è pertanto sempre
+group-ID effettivo con cui viene eseguito un programma, ed è pertanto sempre
 associato alla presenza del permesso di esecuzione per il gruppo. Impostando
 questo bit su un file senza permesso di esecuzione in un sistema che supporta
 il \textit{mandatory locking}, fa sì che quest'ultimo venga attivato per il