\documentclass{article}
\usepackage{graphicx,times}
\usepackage{psfig,epsfig}
\usepackage{amsfonts}

\newtheorem{pr}{Proposition}
\newtheorem{re}{Remarque}

\begin{document}

\def\na{nombres al\'eatoires}
\def\a{al\'eatoire}

\hspace{-.6cm}Universit\'e Paris 7

\hspace{-.6cm}IUP 2

\hspace{-.6cm}R\'eseaux

\hspace{-.6cm}Ann\'ee 2003-2004

\begin{center}
\textbf{R\'esum\'e de Cours pour le TP no 3}

\textbf{Multiplexage I/O et la Fonction \emph{select}.}
\end{center}

\begin{itemize}

\item \textbf{Le probl\`eme :}

Quand on a besoin de lire un descripteur et d'\'ecrire dans un autre,
on utilise de l'entr\'ee/sortie (I/O) bloquant dans une boucle comme
ceci :

\begin{verbatim}
while ((n = read(STDIN_FILENO, buf, BUFSIZ)) > 0)
   if (write(STDOUT_FILENO, buf, n) != n)
       err_sys("write error");
\end{verbatim}

Que faire si on veut lire deux descripteurs ? On ne peut pas faire de
\emph{read} bloquant sur l'un des deux car des donn\'ees peuvent
arriver sur l'autre pendant que nous serons bloqu\'es.


\item \textbf{Les Solutions}

\begin{itemize}
\item \emph{fork} : cr\'eer deux processus et leur faire faire un
  \emph{read} bloquant sur chacun des processus. Mais probl\`eme quand
  l'op\'eration termine : on doit utiliser des signaux en cas de mort
  du fils ou du p\`ere et le programme gagne en complexit\'e.
\item I/O asynchrone : utiliser des \emph{read} et \emph{write} non
  bloquants, dans des boucles et alternativement sur les deux
  descripteurs. Mais le probl\`eme est que cela utilise beaucoup le processeur.
\item Multiplexage I/O et la Fonction \emph{select} : on cr\'ee une
  liste de descripteurs qui non int\'eressent et on appelle une
  fonction qui ne retourne pas avant que l'un des descripteurs ne soit
  pr\^et pour lire ou \'ecrire.


\end{itemize}

\item \textbf{Select }

\begin{verbatim}
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
       struct timeval *timeout);
\end{verbatim}

\item \textbf{Valeur de Retour :}

$-1$ pour une erreur

$0$ pour un timeout

$> 0$ Nombre de descripteurs pr\^ets. Dans ce cas, seuls les
  descripteurs pr\^ets sont encore pr\'esents dans les ensembles
  readfds, writefds et exceptfds.

\item \textbf{Que veut dire qu'un descripteur est pr\^et ?}

1 Un descripteur de l'ensemble lire (readfds) est consid\'er\'e comme
pr\^et si un \emph{read} sur ce descripteur ne va pas bloquer.

2 Un descripteur de l'ensemble \'ecrire (writefds) est consid\'er\'e comme
pr\^et si un \emph{write} sur ce descripteur ne va pas bloquer.


\item \textbf{Le premier argument de \emph{select}}, n, est le plus
  grand descripteur de fichier qui nous int\'eresse auquel on a
  ajout\'e 1.


\item \textbf{Manipuler la structure} \verb+fd_set+ :

Il faut utiliser les macros : 

\begin{verbatim}
FD_ZERO(fd_set *set);            Efface tous les descripteurs de fdset.
FD_SET(int fd, fd_set *set);     Rentre le descripteur fd dans fdset.
FD_CLR(int fd, fd_set *set);     Efface le descripteur fd de fdset.
FD_ISSET(int fd, fd_set *set);   Teste si le descripteur fd est dans fdset.
\end{verbatim}


\item \textbf{L'exemple du \emph{man select} }

\begin{verbatim}
       #include <stdio.h>
       #include <sys/time.h>
       #include <sys/types.h>
       #include <unistd.h>

       int main(void) {
           fd_set rfds;
           struct timeval tv;
           int retval;

           /* Watch stdin (fd 0) to see when it has input. */
           FD_ZERO(&rfds);
           FD_SET(0, &rfds);
           /* Wait up to five seconds. */
           tv.tv_sec = 5;
           tv.tv_usec = 0;

           retval = select(1, &rfds, NULL, NULL, &tv);

           if (retval)
               printf("Data is available now.\n");
               /* FD_ISSET(0, &rfds) will be true. */
           else
               printf("No data within five seconds.\n");

           return 0;
       }
\end{verbatim}

\end{itemize}

\end{document}
