X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=ipc.tex;h=9d8ebe6d88822dd1788a9782dd6fcaaec37e8792;hp=6f69e46880c4c747a2c4843720657e6e36606658;hb=06604d9d9800ff3f095bda01f9c93bc2e82d50eb;hpb=59b107d5207f19e0049bbd1032e10cba660da92e diff --git a/ipc.tex b/ipc.tex index 6f69e46..9d8ebe6 100644 --- a/ipc.tex +++ b/ipc.tex @@ -1692,7 +1692,7 @@ una scansione della struttura mostrata in \figref{fig:ipc_mq_schema}, restituendo il primo messaggio incontrato che corrisponde ai criteri specificati (che quindi, visto come i messaggi vengono sempre inseriti dalla coda, è quello meno recente); in particolare: -\begin{itemize*} +\begin{itemize} \item se \param{msgtyp} è 0 viene estratto il messaggio in cima alla coda, cioè quello fra i presenti che è stato inserito inserito per primo. \item se \param{msgtyp} è positivo viene estratto il primo messaggio il cui @@ -1701,7 +1701,7 @@ coda, \item se \param{msgtyp} è negativo viene estratto il primo fra i messaggi con il valore più basso del tipo, fra tutti quelli il cui tipo ha un valore inferiore al valore assoluto di \param{msgtyp}. -\end{itemize*} +\end{itemize} Il valore di \param{msgflg} permette di controllare il comportamento della funzione, esso può essere nullo o una maschera binaria composta da uno o più @@ -1763,7 +1763,7 @@ int main(int argc, char *argv[]) /* Variables definition */ int i, n = 0; char **fortune; /* array of fortune message string */ - char *fortunefilename; /* fortune file name */ + char *fortunefilename = "/usr/share/games/fortunes/linux"; /* file name */ struct msgbuf_read { /* message struct to read request from clients */ long mtype; /* message type, must be 1 */ long pid; /* message data, must be the pid of the client */ @@ -1788,6 +1788,7 @@ int main(int argc, char *argv[]) exit(1); } /* Main body: loop over requests */ + daemon(0, 0); while (1) { msgrcv(msgid, &msg_read, sizeof(int), 1, MSG_NOERROR); n = random() % i; /* select random value */ @@ -1835,7 +1836,7 @@ in \var{n} il numero di frasi da leggere specificato a linea di comando ed in server, viene prima controllato (\texttt{\small 22}) il numero di frasi richieste abbia senso (cioè sia maggiore di zero), le quali poi (\texttt{\small 23}) vengono lette nel vettore in memoria con la stessa -funzione \code{FortuneParse()} usata anche per il server basato sulle fifo. +funzione \code{FortuneParse} usata anche per il server basato sulle fifo. Una volta inizializzato il vettore di stringhe coi messaggi presi dal file delle \textit{fortune} si procede (\texttt{\small 25}) con la generazione di @@ -1845,33 +1846,35 @@ creazione della stessa (si noti come si sia chiamata \func{msgget} con un valore opportuno per l'argomento \param{flag}), avendo cura di abortire il programma (\texttt{\small 27--29}) in caso di errore. -Finita la fase di inizializzazione il server esegue in permanenza il ciclo -principale (\texttt{\small 32--41}). Questo inizia (\texttt{\small 33}) con il -porsi in attesa di un messaggio di richiesta da parte di un client; si noti -infatti come \func{msgrcv} richieda un messaggio con \var{mtype} uguale a 1: -questo è il valore usato per le richieste dato che corrisponde al \acr{pid} di -\cmd{init}, che non può essere un client. L'uso del flag \const{MSG\_NOERROR} -è solo per sicurezza, dato che i messaggi di richiesta sono di dimensione -fissa (e contengono solo il \acr{pid} del client). +Finita la fase di inizializzazione il server prima (\texttt{\small 32}) chiama +la funzione \func{daemon} per andare in background e poi esegue in permanenza +il ciclo principale (\texttt{\small 33--40}). Questo inizia (\texttt{\small + 34}) con il porsi in attesa di un messaggio di richiesta da parte di un +client; si noti infatti come \func{msgrcv} richieda un messaggio con +\var{mtype} uguale a 1: questo è il valore usato per le richieste dato che +corrisponde al \acr{pid} di \cmd{init}, che non può essere un client. L'uso +del flag \const{MSG\_NOERROR} è solo per sicurezza, dato che i messaggi di +richiesta sono di dimensione fissa (e contengono solo il \acr{pid} del +client). Se non sono presenti messaggi di richiesta \func{msgrcv} si bloccherà, ritornando soltanto in corrispondenza dell'arrivo sulla coda di un messaggio di richiesta da parte di un client, in tal caso il ciclo prosegue -(\texttt{\small 34}) selezionando una frase a caso, copiandola (\texttt{\small - 35}) nella struttura \var{msgbuf\_write} usata per la risposta e -calcolandone (\texttt{\small 36}) la dimensione. +(\texttt{\small 35}) selezionando una frase a caso, copiandola (\texttt{\small + 36}) nella struttura \var{msgbuf\_write} usata per la risposta e +calcolandone (\texttt{\small 37}) la dimensione. Per poter permettere a ciascun client di ricevere solo la risposta indirizzata -a lui il tipo del messaggio in uscita viene inizializzato (\texttt{\small 37}) +a lui il tipo del messaggio in uscita viene inizializzato (\texttt{\small 38}) al valore del \acr{pid} del client ricevuto nel messaggio di richiesta. -L'ultimo passo del ciclo (\texttt{\small 38}) è inviare sulla coda il +L'ultimo passo del ciclo (\texttt{\small 39}) è inviare sulla coda il messaggio di risposta. Si tenga conto che se la coda è piena anche questa funzione potrà bloccarsi fintanto che non venga liberato dello spazio. Si noti che il programma può terminare solo grazie ad una interruzione da -parte di un segnale; in tal caso verrà eseguito il gestore -\code{HandSIGTERM}, che semplicemente si limita a cancellare la coda -(\texttt{\small 44}) ed ad uscire (\texttt{\small 45}). +parte di un segnale; in tal caso verrà eseguito (\texttt{\small 45--48}) il +gestore \code{HandSIGTERM}, che semplicemente si limita a cancellare la coda +(\texttt{\small 46}) ed ad uscire (\texttt{\small 47}). \begin{figure}[!bht] \footnotesize \centering @@ -1929,6 +1932,43 @@ tipo corrispondente al valore del \acr{pid} inviato nella richiesta. L'ultimo passo (\texttt{\small 17}) prima di uscire è quello di stampare a video il messaggio ricevuto. +Proviamo allora il nostro nuovo sistema, al solito occorre definire +\code{LD\_LIBRAY\_PATH} per accedere alla libreria \file{libgapil.so}, dopo di +che, in maniera del tutto analoga a quanto fatto con il programma che usa le +fifo, potremo far partire il server con: +\begin{verbatim} +[piccardi@gont sources]$ ./mqfortuned -n10 +\end{verbatim}%$ +come nel caso precedente, avendo eseguito il server in background, il comando +ritornerà immediatamente; potremo però verificare con \cmd{ps} che il +programma è effettivamente in esecuzione, e che ha creato una coda di +messaggi: +\begin{verbatim} +[piccardi@gont sources]$ ipcs + +------ Shared Memory Segments -------- +key shmid owner perms bytes nattch status + +------ Semaphore Arrays -------- +key semid owner perms nsems + +------ Message Queues -------- +key msqid owner perms used-bytes messages +0x0102dc6a 0 piccardi 666 0 0 +\end{verbatim} +a questo punto potremo usare il client per ottenere le nostre frasi: +\begin{verbatim} +[piccardi@gont sources]$ ./mqfortune +Linux ext2fs has been stable for a long time, now it's time to break it + -- Linuxkongreß '95 in Berlin +[piccardi@gont sources]$ ./mqfortune +Let's call it an accidental feature. + --Larry Wall +\end{verbatim} +con un risultato del tutto equivalente al precedente. Infine potremo chiudere +il server inviando il segnale di terminazione con il comando \code{killall + mqfortuned} verficando che effettivamente la coda di messaggi viene rimossa. + Benché funzionante questa architettura risente dello stesso inconveniente visto anche nel caso del precedente server basato sulle fifo; se il client viene interrotto dopo l'invio del messaggio di richiesta e prima della lettura @@ -2756,7 +2796,9 @@ Come per le code di messaggi e gli insiemi di semafori, anche per i segmenti di memoria condivisa esistono una serie di limiti imposti dal sistema. Alcuni di questi limiti sono al solito accessibili e modificabili attraverso \func{sysctl} o scrivendo direttamente nei rispettivi file di -\file{/proc/sys/kernel/}. In \tabref{tab:ipc_shm_limits} si sono riportate le +\file{/proc/sys/kernel/}. + +In \tabref{tab:ipc_shm_limits} si sono riportate le costanti simboliche associate a ciascuno di essi, il loro significato, i valori preimpostati, e, quando presente, il file in \file{/proc/sys/kernel/} che permettono di cambiarne il valore. @@ -2813,49 +2855,64 @@ un segmento di memoria condivisa \begin{errlist} \item[\errcode{EACCES}] Si è richiesto \const{IPC\_STAT} ma i permessi non consentono l'accesso in lettura al segmento. - \item[\errcode{EINVAL}] O \param{shmid} o \param{cmd} hanno valori non - validi. + \item[\errcode{EINVAL}] O \param{shmid} non è un identificatore valido o + \param{cmd} non è un comando valido. \item[\errcode{EIDRM}] L'argomento \param{shmid} fa riferimento ad un segmento che è stato cancellato. \item[\errcode{EPERM}] Si è specificato un comando con \const{IPC\_SET} o \const{IPC\_RMID} senza i permessi necessari. - \item[\errcode{EOVERFLOW}] L'argomento \param{shmid} fa riferimento ad un - segmento che è stato cancellato. + \item[\errcode{EOVERFLOW}] Si è tentato il comando \const{IPC\_STAT} ma il + valore del group-ID o dell'user-ID è troppo grande per essere + memorizzato nella struttura puntata dal \param{buf}. + \item[\errcode{EFAULT}] L'indirizzo specificato con \param{buf} non è + valido. \end{errlist} - ed inoltre \errval{EFAULT}.} +} \end{functions} -Il comportamento della funzione dipende dal valore del comando passato -attraverso l'argomento \param{cmd}, i valori possibili sono i seguenti: +Il comando specificato attraverso l'argomento \param{cmd} determina i diversi +effetti della funzione; i possibili valori che esso può assumere, ed il +corripondente comportamento della funzione, sono i seguenti: + \begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}} \item[\const{IPC\_STAT}] Legge le informazioni riguardo il segmento di memoria condivisa nella struttura \struct{shmid\_ds} puntata da \param{buf}. Occorre - avere il permesso di lettura sulla coda. + che il processo chiamante abbia il permesso di lettura sulla segmento. \item[\const{IPC\_RMID}] Marca il segmento di memoria condivisa per la rimozione, questo verrà cancellato effettivamente solo quando l'ultimo processo ad esso agganciato si sarà staccato. Questo comando può essere eseguito solo da un processo con user-ID effettivo corrispondente o al - creatore della coda, o al proprietario della coda, o all'amministratore. + creatore del segmento, o al proprietario del segmento, o all'amministratore. \item[\const{IPC\_SET}] Permette di modificare i permessi ed il proprietario del segmento. Per modificare i valori di \var{shm\_perm.mode}, \var{shm\_perm.uid} e \var{shm\_perm.gid} occorre essere il proprietario o - il creatore della coda, oppure l'amministratore. Compiuta l'operazione + il creatore del segmento, oppure l'amministratore. Compiuta l'operazione aggiorna anche il valore del campo \var{shm\_ctime}. -\item[\const{SHM\_LOCK}] Abilita il \textit{memory locking}\index{memory - locking}\footnote{impedisce cioè che la memoria usata per il segmento - venga salvata su disco dal meccanismo della memoria virtuale; si ricordi - quanto trattato in \secref{sec:proc_mem_lock}.} sul segmento di memoria - condivisa. Solo l'amministratore può utilizzare questo comando. +\item[\const{SHM\_LOCK}] Abilita il + \textit{memory locking}\index{memory locking}\footnote{impedisce cioè che la + memoria usata per il segmento venga salvata su disco dal meccanismo della + memoria virtuale\index{memoria virtuale}; si ricordi quanto trattato in + \secref{sec:proc_mem_lock}.} sul segmento di memoria condivisa. Solo + l'amministratore può utilizzare questo comando. \item[\const{SHM\_UNLOCK}] Disabilita il \textit{memory locking} sul segmento di memoria condivisa. Solo l'amministratore può utilizzare questo comando. \end{basedescript} -i primi tre comandi sono gli stessi già visti anche per le code ed i semafori, -gli ultimi due sono delle estensioni previste da Linux. - -Per utilizzare i segmenti di memoria condivisa l'interfaccia prevede due -funzioni, la prima è \funcd{shmat}, che serve ad agganciare un segmento al -processo chiamante, in modo che quest'ultimo possa vederlo nel suo spazio di -indirizzi; il suo prototipo è: +i primi tre comandi sono gli stessi già visti anche per le code di messaggi e +gli insiemi di semafori, gli ultimi due sono delle estensioni specifiche +previste da Linux, che permettono di abilitare e disabilitare il meccanismo +della memoria virtuale\index{memoria virtuale} per il segmento. + +L'argomento \param{buf} viene utilizzato solo con i comandi \const{IPC\_STAT} +e \const{IPC\_SET} nel qual caso esso dovrà puntare ad una struttura +\struct{shmid\_ds} precedentemente allocata, in cui nel primo caso saranno +scritti i dati del segmento di memoria restituiti dalla funzione e da cui, nel +secondo caso, verranno letti i dati da impostare sul segmento. + +Una volta che lo si è creato, per utilizzare un segmento di memoria condivisa +l'interfaccia prevede due funzioni, \funcd{shmat} e \func{shmdt}. La prima di +queste serve ad agganciare un segmento al processo chiamante, in modo che +quest'ultimo possa inserirlo nel suo spazio di indirizzi per potervi accedere; +il suo prototipo è: \begin{functions} \headdecl{sys/types.h} \headdecl{sys/shm.h}