|
@@ -12,10 +12,91 @@ complexité.
|
|
|
|
|
|
\subsection{poll, select}
|
|
|
|
|
|
-\subsection{epoll}
|
|
|
+\begin{code}{c}{Prototype de poll dans man 2 poll}
|
|
|
+int poll(struct pollfd *fds, nfds_t nfds, int délai);<Paste>
|
|
|
+\end{code}
|
|
|
+
|
|
|
+\begin{code}{c}{Prototype de select et macros dans man 2 select}
|
|
|
+int select(int nfds, fd_set *readfds, fd_set *writefds,
|
|
|
+ fd_set *exceptfds, struct timeval *timeout);
|
|
|
+
|
|
|
+void FD_CLR(int fd, fd_set *set);
|
|
|
+int FD_ISSET(int fd, fd_set *set);
|
|
|
+void FD_SET(int fd, fd_set *set);
|
|
|
+void FD_ZERO(fd_set *set);
|
|
|
+\end{code}
|
|
|
|
|
|
\subsection{Asynchronous IO}
|
|
|
|
|
|
+Les asynchronous IO, ou AIO, sont un mécanisme de notification de complétion des
|
|
|
+requêtes de lecture et écriture. L'objectif final de l'implémentation des AIO
|
|
|
+est d'arriver à faire du zéro-copie sur l'API réseau de Linux. En effet, dans un
|
|
|
+modèle par complétion, on peut indiquer directement au noyau où stocker les
|
|
|
+données reçues. Il faut néanmoins accepter la déception et voir que c'est
|
|
|
+parfois aussi coûteux que de faire la copie, particulièrement sur les
|
|
|
+transmissions de petite taille.
|
|
|
+
|
|
|
+L'API est implémenté en userland dans glibc, est relativement coûteuse et ne
|
|
|
+permet d'attendre la première opération qui aurait terminée comme le permettait
|
|
|
+les primitives précédentes. Ell est également difficile à utiliser car les
|
|
|
+notifications sont reçues sous forme de signal, de nouveau thread ou ne sont
|
|
|
+pas envoyées. Elle est donc inutilisable pour notre application mais vaut le
|
|
|
+coup d'être mentionnée pour la réalisation d'un \inltype{vlc_msg_poller_t}
|
|
|
+zéro-copie dans le futur.
|
|
|
+
|
|
|
+\begin{code}{c}{Extrait de l'API de AIO depuis man 2}
|
|
|
+struct aiocb {
|
|
|
+ /* The order of these fields is implementation-dependent */
|
|
|
+
|
|
|
+ int aio_fildes; /* File descriptor */
|
|
|
+ off_t aio_offset; /* File offset */
|
|
|
+ volatile void *aio_buf; /* Location of buffer */
|
|
|
+ size_t aio_nbytes; /* Length of transfer */
|
|
|
+ int aio_reqprio; /* Request priority */
|
|
|
+ struct sigevent aio_sigevent; /* Notification method */
|
|
|
+ int aio_lio_opcode; /* Operation to be performed;
|
|
|
+ lio_listio() only */
|
|
|
+
|
|
|
+ /* Various implementation-internal fields not shown */
|
|
|
+};
|
|
|
+
|
|
|
+int aio_read(struct aiocb *aiocbp);
|
|
|
+int aio_write(struct aiocb *aiocbp);
|
|
|
+\end{code}
|
|
|
+
|
|
|
+\subsection{epoll}
|
|
|
+
|
|
|
+% TODO: https://lkml.org/lkml/2015/2/24/667
|
|
|
+% TODO: https://lore.kernel.org/patchwork/patch/543311/
|
|
|
+Linux fournit depuis assez récemment un mécanisme bien plus performant et avec
|
|
|
+une interface bien plus proche des autres API standards. Ce mécanisme, epoll, a
|
|
|
+longtemps été critiqué car bien qu'étant le dernier des mécanismes permettant ce
|
|
|
+genre de programmation sur événement, il reproduisait des problèmes d'interface
|
|
|
+qui avaient été résolu par les solutions précédentes sur les autres systèmes
|
|
|
+depuis longtemps. C'est notamment des développeurs chez Nginx qui ont remonté
|
|
|
+des problèmes dans leur utilisation qui a abouti à l'ajout de
|
|
|
+\inltype{EPOLLEXCLUSIVE} dans le noyau Linux 4.5.
|
|
|
+
|
|
|
+Dans notre cas, il nous fournit une interface fonctionnant sur la disponibilité
|
|
|
+des descripteurs de fichiers, utilisable facilement pour construire notre
|
|
|
+implémentation du modèle par complétion.
|
|
|
+
|
|
|
+La complexité est en $O(1)$ et elle n'a pas de limitation sur le nombre de
|
|
|
+descripteur autre que la consommation mémoire. C'est aussi la méthode de
|
|
|
+remplacement privilégié pour \inltype{poll} et en concurrence directe avec les
|
|
|
+AIO de la sous-section précédente.
|
|
|
+
|
|
|
+\begin{code}{c}{API de epoll décrite dans man 2 epoll}
|
|
|
+/* retourne un descripteur de fichier vers un objet epoll */
|
|
|
+int epoll_create1(int flags);
|
|
|
+/* attend l'arrivée d'un événement sur l'instance d'epoll donnée */
|
|
|
+int epoll_wait(int epfd, struct epoll_event *events,
|
|
|
+ int maxevents, int timeout);
|
|
|
+/* permet d'ajouter, modifier ou enlever des associations d'événement à des
|
|
|
+ * descripteurs de fichiers dans l'instance d'epoll */
|
|
|
+int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
|
|
|
+\end{code}
|
|
|
+
|
|
|
\section{Initialisation des eventloops}
|
|
|
|
|
|
% TODO: implémentation sandbox_start
|