tralasciamo la gestione del caso in cui questo non è vero. Infine si stampa
(\texttt{\small 32}) a video la risposta, si chiude (\texttt{\small 33}) la
fifo e si cancella (\texttt{\small 34}) il relativo file.
-
Si noti come la fifo per la risposta sia stata aperta solo dopo aver inviato
la richiesta, se non si fosse fatto così si avrebbe avuto uno stallo, in
quanto senza la richiesta, il server non avrebbe potuto aprirne il capo in
+\subsection{La funzione \func{socketpair}}
+\label{sec:ipc_socketpair}
+
+Un meccanismo di comunicazione molto simile alle pipe, ma che non presenta il
+problema della unidirezionalità del flusso dei dati, è quello dei cosiddetti
+\textit{socket} locali (o \textit{Unix domain socket}). Tratteremo l'argomento
+dei socket in \capref{cha:socket_intro}, nell'ambito dell'interfaccia generale
+che essi forniscono per la programmazione di rete; e vedremo
+(in~\secref{sec:sock_sa_local}) come in tal caso si possono definire dei file
+speciali (di tipo \textit{socket}, analoghi alle fifo) cui si accede però
+attraverso quella interfaccia; vale però la pena esaminare qui una
+modalità\footnote{la funzione \func{socketpair} è stata introdotta in BSD4.4,
+ ma è supportata in genere da qualunque sistema che fornisca l'interfaccia
+ dei socket.} di uso di questi socket che li rende sostanzialmente identici
+ad una pipe bidirezionale.
+
+Attraverso la funzione \func{socketpair} infatti è possibile creare una coppia
+di socket (che sono trattati com file descriptor) connessi fra di loro, senza
+fare nessun riferimento ad un file speciale sul filesystem, in maniera analoga
+a quello che si fa con \func{pipe}; la differenza è che in questo caso il
+flusso dei dati è bidirezionale. Il prototipo della funzione è:
+\begin{functions}
+ \headdecl{sys/types.h}
+ \headdecl{sys/socket.h}
+
+ \funcdecl{int socketpair(int domain, int type, int protocol, int sv[2])}
+
+ Crea una coppia di socket connessi fra loro.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \begin{errlist}
+ \item[\macro{EAFNOSUPPORT}] I socket locali non sono supportati.
+ \item[\macro{EPROTONOSUPPORT}] Il protocollo specificato non è supportato.
+ \item[\macro{EOPNOTSUPP}] Il protocollo specificato non supporta la
+ creazione di coppie di socket.
+ \end{errlist}
+ ed inoltre \macro{EMFILE}, \macro{EFAULT}.
+}
+\end{functions}
+
+La funzione restituisce in \param{sv} una coppia di descrittori di socket
+(come vedremo in \capref{cha:socket_intro} i file descriptor vengono usati
+anche per i socket) connessi fra di loro, così che quello che si scrive da una
+parte può essere riletto dall'altra e viceversa. I parametri \param{domain},
+\param{type} e \param{protocol} derivano dall'interfaccia dei socket, ma in
+questo caso i soli valori validi sono rispettivamente \macro{AF\_UNIX},
+\macro{SOCK\_STREAM} e \macro{0}.
+
+
+
\section{La comunicazione fra processi di System V}
\label{sec:ipc_sysv}
\funcdecl{int msgget(key\_t key, int flag)}
- Restituisce l'identificatore di una cosa di messaggi.
+ Restituisce l'identificatore di una coda di messaggi.
\bodydesc{La funzione restituisce l'identificatore (un intero positivo) o -1
in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{enumerate}
\item Eseguire una \func{fork} e terminare immediatamente il processo padre
proseguendo l'esecuzione nel figlio. In questo modo si ha la certezza che
- il processo non è un \textit{process group leader}, e si può chiamare
- \func{setsid} con successo.
+ il figlio non è un \textit{process group leader}, (avrà il \acr{pgid} del
+ padre, ma un \acr{pid} diverso) e si può chiamare \func{setsid} con
+ successo. Inoltre la shell considererà terminato il comando all'uscita del
+ padre.
\item Eseguire \func{setsid} per creare una nuova sessione ed un nuovo
- raggruppamento di cui il processo è leader, che non ha associato nessun
- terminale di controllo.
+ raggruppamento di cui il processo diventa automaticamente il leader, che
+ però non ha associato nessun terminale di controllo.
\item Assicurarsi che al processo non venga associato in seguito nessun nuovo
terminale di controllo; questo può essere fatto sia avendo cura di usare
sempre l'opzione \macro{O\_NOCTTY} nell'aprire i file di terminale, che
- eseguendo una ulteriore \func{fork} proseguendo nel figlio, che a questo
- punto non essendo più leader di sessione non può più ottenere un terminale
- di controllo.
-\item Eseguire una \func{chdir} per impostare la directory di lavoro (su
- \file{/} o su una directory che contenga dei file necessari per il
- programma), per evitare che la directory da cui si è lanciato il processo
+ eseguendo una ulteriore \func{fork} uscendo nel padre e proseguendo nel
+ figlio. In questo caso, non essendo più quest'ultimo un leader di sessione
+ non potrà ottenere automaticamente un terminale di controllo.
+\item Eseguire una \func{chdir} per impostare la directory di lavoro del
+ processo (su \file{/} o su una directory che contenga dei file necessari per
+ il programma), per evitare che la directory da cui si è lanciato il processo
resti in uso e non sia possibile rimuoverla o smontare il filesystem che la
contiene.
\item Impostare la maschera dei permessi (di solito con \code{umask(0)}) in
modo da non essere dipendenti dal valore ereditato da chi ha lanciato
originariamente il processo.
-\item Chiudere i file standard (o redirigerli verso \file{/dev/null}).
+\item Chiudere tutti i file aperti che non servono più (in generale tutti); in
+ particolare vanno chiusi i file standard che di norma sono ancora associati
+ al terminale (un'altra opzione è quella di redirigerli verso
+ \file{/dev/null}).
\end{enumerate}
valori impostati dalle sottostanti \func{fork} e \func{setsid}.}
\end{prototype}
-La funzione esegue una \func{fork}, per uscire subito, con \func{\_exit} nel
-padre, mentre l'esecuzione prosegue nel figlio che esegue \func{setsid}. Se
-\param{nochdir} è nullo la funzione imposta anche la directory di lavoro su
-\file{/}, se \param{noclose} è nullo i file standard vengono rediretti su
-\file{dev/null}; in caso di valori non nulli non viene eseguita nessuna altra
-azione.
-
+La funzione esegue una \func{fork}, per uscire subito, con \func{\_exit}, nel
+padre, mentre l'esecuzione prosegue nel figlio che esegue subito una
+\func{setsid}. In questo modo si compiono automaticamente i passi 1 e 2 della
+precedente lista. Se \param{nochdir} è nullo la funzione imposta anche la
+directory di lavoro su \file{/}, se \param{noclose} è nullo i file standard
+vengono rediretti su \file{/dev/null} (corrispondenti ai passi 4 e 6); in caso
+di valori non nulli non viene eseguita nessuna altra azione.
+
+Dato che un programma demone non può più accedere al terminale, si pone il
+problema di come fare per la notifica di eventuali errori, non potendosi più
+utilizzare lo standard error; per il normale I/O infatti ciascun demone avrà
+le sue modalità di interazione col sistema e gli utenti a seconda dei compiti
+e delle funzionalità che sono sono previste; ma gli errori devono normalmente
+essere notificati all'amministratore del sistema.
+
+Una soluzione può essere quella di scrivere gli eventuali messaggi su uno
+specifico file (cosa che a volte viene fatta comunque) ma questo comporta il
+grande svantaggio che l'amministratore dovrà tenere sotto controllo un file
+diverso per ciascun demone, e che possono anche generarsi conflitti di nomi.
+Per questo in BSD4.2 venne introdotto un servizio di sistema, il
+\textit{syslog}, che oggi si trova su tutti i sistemi Unix, e che permettesse
+ai demoni di inviare messaggi all'amministratore in una maniera
+standardizzata.
+
+Il servizio prevede vari meccanismi di notifica, e, come ogni altro servizio
+in un sistema unix-like, viene gestito attraverso un apposito programma,
+\cmd{syslogd}, che è anch'esso un \textsl{demone}. In generale i messaggi di
+errore vengono raccolti dal file speciale \file{/dev/log}, un \textit{socket}
+locale (vedi \secref{sec:sock_sa_local}) dedicato a questo scopo, o via rete,
+con un \textit{socket} UDP, o da un apposito demone, \cmd{klogd}, che estrae i
+messaggi del kernel.\footnote{i messaggi del kernel sono tenuti in un buffer
+ circolare e scritti tramite la funzione \func{printk}, analoga alla
+ \func{printf} usata in user space; una trattazione eccellente dell'argomento
+ si trova in \cite{LinDevDri}, nel quarto capitolo.}
+
+Il servizio permette poi di trattare i vari messaggi classificandoli secondo
+due indici, una \textit{facility}, che indica quale categoria di demone ha
+emesso il messaggio, e permette di classificarli per sottosistemi (kernel,
+posta elettronica, demoni di stampa, ecc.), ed una \textit{priority}, che
+identifica l'importanza del messaggio. Il sistema di \textit{syslog} provvede
+poi a riportare i messaggi all'amministratore in varie modalità come:
+\begin{itemize*}
+\item scriverli sulla console.
+\item inviarli via mail ad uno specifico utente.
+\item scriverli su un file (comunemente detto \textit{log file}).
+\item inviarli ad un altro demone (anche via rete).
+\item scartarli.
+\end{itemize*}
+secondo le modalità che questo preferisce e che possono essere impostate
+attraverso il file di configurazione \file{/etc/syslog.conf} (maggiori
+dettagli si possono trovare sulle relative pagine di manuale per questo file e
+per \cmd{syslogd}).
+
+Le \acr{glibc} definiscono una serie di funzioni standard con cui un processo
+può accedere in maniera generica al servizio di syslog, che però funzionano
+solo localmente; se si vogliono inviare i messaggi ad un'altro sistema occorre
+farlo esplicitamente con un socket UDP, o utilizzare le capacità di reinvio
+del servizio.
+
+La prima funzione definita dall'interfaccia è \func{openlog}; essa in generale
+non è necessaria per l'uso del servizio, ma permette di impostare alcuni
+valori che controllano gli effetti delle chiamate successive; il suo prototipo
+è:
+\begin{prototype}{syslog.h}{void openlog(const char *ident, int option,
+int facility)}
+
+Apre una connessione al sistema di \textit{syslog}.
+
+\bodydesc{La funzione non restituisce nulla.}
+\end{prototype}
+La funzione permette di specificare, tramite \param{ident}, l'identità di chi
+ha inviato il messaggio (di norma si passa il nome del programma, come
+specificato da \code{argv[0]}); la stringa verrà preposta all'inizio di ogni
+messaggio. Il parametro \param{facility} permette invece di specificare una
+categoria per classificare i vari messaggi; i valori possibili sono riportati
+in \tabref{tab:sess_syslog_facility}.
+
+
+\begin{table}[htb]
+\centering
+\begin{tabular}[c]{|l|p{8cm}|}
+\hline
+\textbf{Valore}& \textbf{Significato}\\
+\hline
+\hline
+\macro{LOG\_AUTH} & \\
+\macro{LOG\_AUTHPRIV} & \\
+\macro{LOG\_CRON} & \\
+\macro{LOG\_DAEMON} & \\
+\macro{LOG\_FTP} & \\
+\macro{LOG\_KERN} & \\
+\macro{LOG\_LOCAL0} & \\
+...& \\
+\macro{LOG\_LOCAL7} & \\
+\macro{LOG\_LPR} & \\
+\macro{LOG\_MAIL} & \\
+\macro{LOG\_NEWS} & \\
+\macro{LOG\_SYSLOG} & \\
+\macro{LOG\_USER} & \\
+\macro{LOG\_UUCP} & \\
+\hline
+\end{tabular}
+\caption{Valori possibili per l'argomento \param{facility} di \func{openlog}.}
+\label{tab:sess_syslog_facility}
+\end{table}
\section{L'I/O su terminale}