Skip to content
Snippets Groups Projects
Select Git revision
  • 783f88b18cdae399c2a7016ffd23938929412572
  • main default protected
2 results

main.py

Blame
  • Forked from LSDS / Teaching / Master / Cloud / chatbot-lab
    Source project has a limited visibility.
    index.html 35.73 KiB
    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <meta name="generator" content="pandoc">
        <meta name="author" content="Guillaume Chanel">
        <title>I/O</title>
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
        <link rel="stylesheet" href="../../../dist/reset.css">
        <link rel="stylesheet" href="../../../dist/reveal.css">
        <link rel="stylesheet" href="../../../dist/theme/white.css" id="theme">
        <link rel="stylesheet" href="../../../plugin/highlight/zenburn.css" id="highlight-theme">
    
        <!-- Add my own theme on top of classical reveal.js theme -->
        <link rel="stylesheet" href="../css/mytheme.css">
    
        <!-- Printing and PDF exports -->
        <script>
            var link = document.createElement('link');
            link.rel = 'stylesheet';
            link.type = 'text/css';
            link.href = window.location.search.match(/print-pdf/gi) ? '../../../css/print/pdf.scss' : '../../../css/print/paper.scss';
            document.getElementsByTagName('head')[0].appendChild(link);
        </script>
        <!--[if lt IE 9]>
        <script src="../../../lib/js/html5shiv.js"></script>
        <![endif]-->
    
        <!-- Include example directly in slide -->
        <script type="text/javascript">
          window.onload=function() {
            fetch('examples/copy.c').then(function(response) {
                response.text().then(function(text) {
                    element = document.getElementById('ex-copy');
                    element.textContent = text;
                    hljs.highlightBlock(element);
                });
            });
            fetch('examples/seekStruct.c').then(function(response) {
                response.text().then(function(text) {
                    element = document.getElementById('ex-seek');
                    element.textContent = text;
                    hljs.highlightBlock(element);
                });
            });
    
            fetch('examples/pipes/consumer.c').then(function(response) {
                response.text().then(function(text) {
                    element = document.getElementById('ex-pipes-consumer');
                    element.textContent = text;
                    hljs.highlightBlock(element);
                });
            });
    
            fetch('examples/pipes/producer.c').then(function(response) {
                response.text().then(function(text) {
                    element = document.getElementById('ex-pipes-producer');
                    element.textContent = text;
                    hljs.highlightBlock(element);
                });
            });
    
          }
        </script>
    </head>
    
    <body>
        <div class="reveal">
            <div class="slides">
    
                <section id="title-slide">
                    <h1 class="title">I/O</h1>
                    <p class="author">Guillaume Chanel</p>
                    <p class="author">Remerciements à Jean-Luc Falcone</p>
                </section>
    
                <!-- ######################### CANAUX ######################### -->
    
                <section>
                    <section id="canaux" class="title-slide slide level1">
                        <h1>Canaux</h1>
                    </section>
                    <section id="canaux-1" class="slide level2">
                        <h2>Canaux</h2>
                        <p><img data-src="schema.png" alt="image" /></p>
                        <p>Merci à Jacques Menu</p>
                        <aside class="notes">
                            <p>Afin d'acceder aux contenus des fichiers on va créer des canaux d'accès</p>
                            <p>Chaque canal spécifie notament le mode d'ouverture (ajout - append, lecture / écriture) et la position courante dans le fichier (curseur)</p>
                        </aside>
                    </section>
                    <section id="descripteur-de-canal" class="slide level2">
                        <h2>Descripteur de Canal</h2>
                        <ul>
                            <li>Un descripteur de canal d'entrée/sortie est représenté par un entier non-négatif qui correspond à un index dans la <em>table des canaux ouverts</em> par le processus.</li>
                            <li>Trois descripteurs sont créés au lancement d'un processus:
                                <table>
                                    <tr><th>0</th><td>Entrée standard</td></tr>
                                    <tr><th>1</th><td>Sortie standard</td></tr>
                                    <tr><th>2</th><td>Erreur standard</td></tr>
                                </table>
                            </li>
                        </ul>
                    </section>
    
                    <section id="ouverture-de-canal" class="slide level2">
                        <h2>Ouverture de canal</h2>
                        <div class="text-block">
                            <p>A l'ouverture d'un canal d'entrée/sortie:</p>
                            <ul>
                                <li>un élément est ajouté à la table des canaux ouverts du noyau.</li>
                                <li>un descripteur y est associé (indice).</li>
                                <li>un pointeur vers l'élément est introduit dans la table des canaux ouverts du processus à l'indice associé.</li>
                            </ul>
                        </div>
                        <fieldset style="margin-top:20px">
                            <legend>Remarques</legend>
                            <p style="margin-bottom:0px">Un processus peut ouvrir plusieurs canaux vers un même inode:</p>
                            <ul>
                                <li>Plusieurs éléments distincts seront créés dans la tables du noyau</li>
                                <li>Plusieurs descripteurs distincts seront créés.</li>
                            </ul>
                        </fieldset>
                    </section>
    
                    <section id="table-des-canaux-ouverts" class="slide level2">
                        <h2>Table des canaux ouverts</h2>
                        <div class="text-block">
                            <p>Un élément de la tables des canaux ouverts contient (entre autre):</p>
                            <ul>
                                <li>Mode d'accès aux données (<code><a href="#/flags">O_RDONLY, O_WRONLY, O_RDWR</a></code>)</li>
                                <li>L'état du canal (<code><a href="#/flags">O_APPEND</a>, O_NONBLOCK, O_ASYNC</code>)</li>
                                <li>Système de fichier et numéro d'inode</li>
                                <li>Compteur de références pointant sur l'élément</li>
                                <li>Pour les fichiers normaux: la <strong>position actuelle</strong></li>
                                <li>Le bit <em>close-on-exec</em></li>
                            </ul>
                        </div>
                    </section>
    
                    <section id="opérations-sur-les-canaux" class="slide level2">
                        <h2>Opérations sur les canaux</h2>
                        <p>Les mêmes fonctions sont utilisés quelque soit le type de fichier (fichier de données, socket, pipe, périphériques, etc.):</p>
                        <table>
                            <tr><th><strong>Opération</strong></th><th><strong>Appel système</strong></th></tr>
                            <tr><td>Ouverture</td><td><code>open</code></td></tr>
                            <tr><td>Lecture de données</td><td><code>read</code></td></tr>
                            <tr><td>Ecriture de données</td><td><code>write</code></td></tr>
                            <!-- <tr><td>Attente</td><td><code>select</code></td></tr> --><!-- removed cause I do not do asynch anymore -->
                            <tr><td>Contrôle du fonctionement</td><td><code>fcntl</code><br><code>dup</code><br><code>dup2</code></td></tr>
                            <tr><td>Fermeture</td><td><code>close</code></td></tr>
                        </table>
                        <aside class="notes">
                            <p style="color:red">ioctl -> fcntl ?</p>
    
                        </aside>
                    </section>
                </section>
    
                <!-- ######################### CANAUX ######################### -->
    
                <section>
                    <section id="ouverture-fermeture-et-contrôle" class="title-slide slide level1">
                        <h1>Ouverture, Fermeture et Contrôle</h1>
                    </section>
    
                    <section id="ouvrir-un-canal-open" class="slide level2">
                        <h2>Ouvrir un canal (<code>open</code>)</h2>
                        <div class="text-block">
                            <p>L'appel système suivant ouvre un canal:</p>
                            <pre><code class="c">int open(const char *pathname, int flags, mode_t mode);</code></pre>
                            <ul>
                                <li><code>pathname</code> est le nom du fichier</li>
                                <li><code>flags</code> est un champ de bit indiquant le mode d'accès au fichier</li>
                                <li><code>mode</code> indique les permissions si le fichier est créé par <code>open</code> (cf. <code>O_CREAT</code>).</li>
                                <li>Retourne soit le descripteur créé, soit -1 en cas d'erreur.</li>
                                <li>Le descripteur retourné est le plus petit descripteur possible.</li>
                            </ul>
                        </div>
                    </section>
    
                    <section id="flags" class="slide level2">
                        <h2>Flags</h2>
                        <p>Les flags suivants peuvent être passés à la fonction <code>open</code>:</p>
                        <font size=5.5><table>
                            <tr><td><code>O_RDONLY</code></td><td>Lecture seule</td></tr>
                            <tr><td><code>O_WRONLY</code></td><td>Ecriture seule</td></tr>
                            <tr><td><code>O_RDWR</code></td><td>Lecture et écriture</td></tr>
                            <tr><td><code>O_APPEND</code></td><td>Ecrit à la fin</td></tr>
                            <tr><td><code>O_CREAT</code></td><td>Crée le fichier s'il n'existe pas</td></tr>
                            <tr><td><code>O_TRUNC</code></td><td>Efface le fichier s'il existe</td></tr>
                            <tr><td><code>O_EXCL</code></td><td>Erreur si <code>O_CREATE</code> est spécifié et que le fichier existe</td></tr>
                        </table></font>
                        <fieldset style="margin-top:20px">
                            <legend>Remarques</legend>
                            <p style="margin-bottom:0">Les trois premiers flags sont particuliers:</p>
                            <ul style="margin-top:0">
                                <li>On ne peut pas les combiner entre eux</li>
                                <li>On doit en passer au moins un.</li>
                            </ul>
                        </fieldset>
                    </section>
    
                    <section id="mode-permissions" class="slide level2">
                        <h2>Mode (permissions)</h2>
                        <p>Lorsque que le flag <code>O_CREAT</code> est passé, il faut spécifier les permissions:</p>
                        <pre><code data-noescape class="c">int fd = open("/tmp/foo.txt", O_RDWR | <mark>O_CREAT</mark> | O_OEXCL, <mark>0640</mark>);</code></pre>
                        <p>Si <code>O_CREAT</code> est absent, le mode est ignoré.</p>
                    </section>
                    <section id="ouverture-multiple" class="slide level2">
                        <h2>Ouverture multiple</h2>
                        <div class="text-block">
                            <p>Si un fichier est ouvert plusieurs fois par un ou plusieurs processus:</p>
                            <ul>
                                <li>Plusieurs canaux seront créés</li>
                                <li>Dans le cas d'un fichier normal, chaque canal aura sa position dans le fichier et éventuellement ses propres buffer</li>
                                <li>Toutes les opérations s'effectuent indépendamment et en parallèle</li>
                            </ul>
                        </div>
                        <fieldset class="warning" style="margin-top:20px">
                            <legend>Attention</legend>
                            <p>Le développeur est responsable de coordonner l'accès aux fichiers. Pour en savoir plus vous renseigner sur les verrous (lock)</p>
                        </fieldset>
                    </section>
    
                    <section id="fermer-un-canal-close" class="slide level2">
                        <h2>Fermer un canal (<code>close</code>)</h2>
                        <div class="text-block">
                            <ul>
                                <li>L'appel système suivant permet de fermer un canal ouvert <code>fd</code>:</li>
                            </ul>
                            <pre><code class="c">int close(int fd);</code></pre>
                            <ul>
                                <li>Le descripteur est liberé et pourra être recyclé (<span class="alert">attention</span>)</li>
                                <li>Retourne 0 en cas de succès et -1 en cas d'erreur</li>
                                <li>Le compteur de référence de l'élément de la table des canaux ouverts est décrémenté
                                    <ul>
                                        <li>s'il atteint 0, l'élément est effacé et les ressources libérées</li>
                                    </ul>
                                </li>
                                <li>Si fd est la dernière indirection vers un nom de fichier effacé par <code>unlink</code>, le fichier est effectivement effacé.</li>
                            </ul>
                        </div>
                    </section>
    
                    <section id="fermeture-automatique-dun-canal" class="slide level2">
                        <h2>Fermeture automatique d'un canal</h2>
                        <ul class="text-block">
                            <li>Lors de la terminaison d'un processus par <code>exit</code> ou <code>abort</code>, le noyau ferme tous les descripteurs (équivalent à <code>close</code>).</li>
                            <li>Egalement lors d'un appel à <code>execv()</code> si le bit <em>close-on-exec</em> est égal à 1.</li>
                        </ul>
                    </section>
    
                    <section id="manipulation-des-descripteurs-fcntl" class="slide level2">
                        <h2>Manipulation des descripteurs (<code>fcntl</code>)</h2>
                        <div class="text-block">
                            <p>On peut manipuler finement un descripteur avec:</p>
                            <pre><code class="c">int fcntl(int fd, int cmd, ... /* arg */ );</code></pre>
                            <ul>
                                <li>où <code>fd</code> est un descripteur et <code>cmd</code> la commande.</li>
                                <li>Utilisé par exemple pour dupliquer les descritpeurs (slide suivant)</li>
                                <li>Beaucoup d'autre manipulations peuvent être effectuées sur les descripteurs avec <code>fcntl</code> (voir <code>
                                    man).</code></li>
                            </ul>
                        </div>
                    </section>
    
                    <section>
                        <h2>Duplication de descripteurs</h2>
                        <div class="text-block">
                            <p style="margin-bottom: 0px;"><code>dup</code> et <code>dup2</code> permettent de dupliquer des descripteurs de fichiers qui pointerons sur la même entrée de la table des canaux.</p>
                            <pre><code class="c" data-trim>
                                #include &lt;unistd.h&gt;
                                int dup(int fildes);
                                int dup2(int fildes, int fildes2);
                            </code></pre>
                            <ul>
                                <li><code>fildes</code>: un descripteur à dupliquer</li>
                                <li>retourne le nouveau descripteur ou -1 en cas d'erreur</li>
                                <li>pour <code>dup2</code> seulement: ferme le descripteur existant <code>fildes2</code> et y stocke un nouveau descripteur qui est un duplicata de <code>fildes</code></li>
                            </ul>
                            <p style="margin-bottom: 0px; margin-top: 30px;"><code>dup</code> est équivalent à:</p>
                            <pre><code class="c" data-trim>
                                fcntl(fildes, F_DUPFD, 0);
                            </code></pre>
                        </div>
                    </section>
    
                </section>
    
                <!-- ######################### LECTURE / ECRITURE ######################### -->
    
                <section>
                    <section id="lectureecriture" class="title-slide slide level1">
                        <h1>Lecture/Ecriture</h1>
                    </section>
    
                    <section id="lecture-bas-niveau-read" class="slide level2">
                        <h2>Lecture: bas niveau (<code>read</code>)</h2>
                        <div class="text-block">
                            <p>Pour lire les données d'un descripteur, on peut utiliser:</p>
                            <pre><code class="c">ssize_t read(int fd, void *buf, size_t count);</code></pre>
                            <ul>
                                <li>Essaie de lire jusqu'à <code>count</code> bytes depuis le descripteur <code>fd</code></li>
                                <li>Copie les bytes lus dans <code>buf</code></li>
                                <li>Retourne le nombre de bytes <strong>effectivement lus</strong> en cas de succès</li>
                                <li>Retourne -1 en cas d'erreur (cf. <code>errno</code>)</li>
                                <li>Le nombre de bytes retournés peut être plus petit que ce qui est demandé</li>
                                <li><strong>La position avance</strong> d'autant de bytes</li>
                            </ul>
                        </div>
                        <aside class="notes">
                            <p>Size_t vs. ssize_t: non-signé vs. signé, ssize_t [-1, SSIZE_MAX] peut être utilisé pour un code de retour négatif</p>
                        </aside>
                    </section>
    
                    <section id="ecriture-bas-niveau-write" class="slide level2">
                        <h2>Ecriture: bas niveau (<code>write</code>)</h2>
                        <div class="text-block">
                            <p>Pour écrire des données sur un descripteur, on peut utiliser:</p>
                            <pre><code class="c">ssize_t write(int fd, void *buf, size_t count);</code></pre>
                            <ul>
                                <li>Essaie d'écrire jusqu'à <code>count</code> bytes sur le descripteur <code>fd</code></li>
                                <li><code>buf</code> contient les bytes à écrire</li>
                                <li>Retourne le nombre de bytes <strong>effectivement écrits</strong> en cas de succès</li>
                                <li>Retourne -1 en cas d'erreur (cf. <code>errno</code>)</li>
                                <li>Le nombre de bytes écrits peut être plus petit que ce qui est demandé</li>
                                <li><strong>La position avance</strong> d'autant de bytes</li>
                            </ul>
                        </div>
                    </section>
    
                    <section id="notes-on-read-write" class="slide level2">
                        <h2>Notes sur <code>read</code> et <code>write</code></h2>
                        <div class="text-block">
                            <p style="margin: 5px;">Sur des fichiers standards read et write retournent moins que demandé quand:</p>
                            <ul>
                                <li><code>read</code> arrive en fin de fichier;</li>
                                <li><code>write</code> n'a plus d'espace sur le système de fichier.</li>
                            </ul>
                            <p style="margin-bottom: 5px;">Mais il faut penser que:</p>
                            <ul>
                                <li>une lecture/ecriture peut toujours être intérrompue par un signal;</li>
                                <li>les utilisateurs peuvent passer à votre programme tout type de fichiers qui se comportent différemments (pipes, sockets, charater devices, etc.)</li>
                            </ul>
                        </div>
                        <fieldset style="margin-top: 5px;">
                            <legend>Attention</legend>
                            <p>Il faut donc bien gérer les cas où <code>read</code>/<code>write</code> font des opérations partielles.</p>
                            <p>Une autre solution est de faire appel aux entrées/sorties bufferisées.</p>
                        </fieldset>
                    </section>
    
                    <section id="exemple" class="slide level2">
                        <h2>Exemple (<a href="examples/copy.c">examples/copy.c</a>)</h2>
                        <pre><code id="ex-copy" class="c" style="font-size:70%;height:50vh;max-height:100vh">Include example there (see script)</code></pre>
                    </section>
    
                    <section id="accès-aléatoire-lseek" class="slide level2">
                        <h2>Accès aléatoire (<code>lseek</code>)</h2>
                        <div class="text-block">
                            <ul>
                                <li>La position d'un fichier ouvert est à 0</li>
                                <li>Elle avance à chaque lecture/écriture</li>
                                <li>Si le type de fichier le permet, on peut changer la position avec:</li>
                            </ul>
                            <pre><code class="c">off_t lseek(int fd, off_t offset, int whence);</code></pre>
                            <ul>
                                <li>Avance la position du descripteur <code>fd</code></li>
                                <li>L'offset est a interprété en fonction de l'argument <code>whence</code> (slide suivant)</li>
                                <li>En cas de succès retourne la position en byte depuis le début du fichier.</li>
                                <li>En cas d'échec, retourne -1 (cf. <code>errno</code>)</li>
                            </ul>
                        </div>
                    </section>
    
                    <section id="accès-aléatoire-2" class="slide level2">
                        <h2>Accès aléatoire (2)</h2>
                        <p>La nouvelle position, dépend de <code>whence</code> et d'<code>offset</code></p>
                        <table>
                            <tr><th><code>whence</code></th><th><strong>Nouvelle position</strong></th></tr>
                            <tr><td><code>SEEK_SET</code></td><td><code>offset</code></td></tr>
                            <tr><td><code>SEEK_CUR</code></td><td>position courant + <code>offset</code></td></tr>
                            <tr><td><code>SEEK_END</code></td><td>fin du fichier + <code>offset</code></td></tr>
                            <!-- I removed the two below because they are not standard (only linux it seems) and nor available for all filesystems -->
                            <!-- <tr><td><code>SEEK_DATA</code></td><td>prochaine zone de donnée <span class="math inline">≥</span> <code>offset</code></td></tr> -->
                            <!-- <tr><td><code>SEEK_HOLE</code></td><td>prochain trou <span class="math inline">≥</span> <code>offset</code></td></tr> -->
                        </table>
                        <fieldset style="margin-top:20px">
                            <legend>Remarque</legend>
                            <p>Ecrire plus loin que la fin du fichier crée des trous, remplis de <code>\0</code>.</p>
                        </fieldset>
                        <aside class="notes">
                            <p>Peut aussi etre utilisé pour obtenir la position du curseur avec un offset de 0 et SEEK_CUR</p>
                        </aside>
                    </section>
    
                    <section id="exemple-1" class="slide level2">
                        <h2>Exemple (<a href="examples/seekStruct.c">examples/seekStruct.c</a>)</h2>
                        <pre><code id="ex-seek" class="c" style="font-size:70%;height:50vh;max-height:100vh">Include example there (see script)</code></pre>
                    </section>
                </section>
    
                <!-- ######################### FICHIERS TEMPORAIRES ######################### -->
    
                <section>
                    <section id="fichiers-temporaires" class="title-slide slide level1">
                        <h1>Fichiers temporaires</h1>
                    </section>
                    <section id="fichiers-temporaires-temporary-files" class="slide level2">
                        <h2>Fichiers temporaires (<em>temporary files</em>)</h2>
                        <ul>
                            <li>Un programme peut utiliser des <em>fichier temporaires</em>, par exemple pour:
                                <ul>
                                    <li>Soulager la mémoire vive</li>
                                    <li>Téléchargement partiel</li>
                                    <li>Communication entre processus</li>
                                </ul>
                            </li>
                        </ul>
                        <fieldset class="warning" style="margin-top:20px">
                            <legend>Problème</legend>
                            <ul>
                                <li>Il faut créer un nom unique pour éviter d'écraser d'autres fichiers existant.</li>
                                <li>Il faut être sûr que le fichier soit effacé lorsque l'on quitte les processus.</li>
                            </ul>
                        </fieldset>
                    </section>
    
                    <section id="créer-et-ouvrir-un-fichier-temporaire-mkstemp" class="slide level2">
                        <h2>Créer et ouvrir un fichier temporaire (<code>mkstemp</code>)</h2>
                        <div class="text-block">
                            <p>La fonction <code>mkstemp</code> permet de créer et d'ouvrir un fichier temporaire:</p>
                            <pre><code class="c">int mkstemp(char *template);</code></pre>
                            <ul>
                                <li>Il faut passer un modèle pour le nom du fichier (<code>*template</code>), terminé par 6 "X".</li>
                                <li>En cas de succès, la chaîne <code>*template</code> est modifiée avec le vrai nom du fichier.</li>
                                <li>Le fichier est créé avec les permissions <code>0600</code></li>
                                <li>Retourne un descripteur de fichier ouvert en cas de succès (-1 sinon).</li>
                            </ul>
                        </div>
                    </section>
    
                    <section id="exemple-mkstemp" class="slide level2">
                        <h2>Exemple <code>mkstemp</code></h2>
                        <pre><code data-trim class="c">
    char name[15] = "";
    int fd = -1;
    strncpy( name, "/tmp/ed.XXXXXX", sizeof name );
    fd = mkstemp( name );
    if( fd < 0 ) {
        //Gerer l'erreur
    }
    else {
        printf( "The temporaray filename is %s\n", name );
    }
                        </code></pre>
                    </section>
    
                    <section id="effacer-automatiquement" class="slide level2">
                        <h2>Effacer automatiquement</h2>
                        <ul class="text-block">
                            <li><strong>Rappel:</strong>
                                <ul>
                                    <li><code>unlink</code> n'efface pas un fichier, seulement son nom</li>
                                    <li>Le fichier est effacé s'il n'y a pas de descripteur ouvert.</li>
                                </ul>
                            </li>
                            <li>On peut alors immédiatement appeler <code>unlink</code> sur un fichier temporaire créé.</li>
                            <li>Le processus peut toujours interragir avec le fichier via le descripteur.</li>
                            <li>A la fermeture du descripteur (ou à la terminaison du processus) le fichier est effacé.</li>
                            <li>Aucun autre processus ne peut y accéder.</li>
                        </ul>
                    </section>
    
                    <section id="exemple-mkstempunlinklink-pseudocode" class="slide level2">
                        <h2>Exemple <code>mkstemp/unlink/link</code> (pseudocode)</h2>
                        <pre><code data-trim class="c">
    int fd = mkstemp( name );
    unlink( fd );           // Enleve le nom
    DOWNLOAD_INTO( fd );
    PLAY_WITH( fd );
    close( downloadFD );    // Efface les donnees
                        </code></pre>
                    </section>
    
                    <section id="répertoires-temporaires-mkdtemp" class="slide level2">
                        <h2>Répertoires temporaires (<code>mkdtemp</code>)</h2>
                        <div class="text-block">
                            <p>On peut aussi créer des répertoires temporaires:</p>
                            <pre><code class="c">char *mkdtemp(char *template);</code></pre>
                            <ul>
                                <li>Le template suit les mêmes règles que pour <code>mkstemp</code>.</li>
                                <li>Le répertoire créé a les permissions <code>0700</code>.</li>
                                <li>En cas de succès retourne le template (modifié).</li>
                                <li>En cas d'écher retourne <code>NULL</code>.</li>
                            </ul>
                        </div>
                    </section>
                </section>
    
                <!-- ######################## FIFO - PIPES ######################## -->
    
                <section>
                    <section id="fifo" class="title-slide slide level1">
                        <h1>PIPES et FIFO</h1>
                    </section>
    
                    <section id="pipes-et-fifo" class="slide level2">
                        <h2>Rappel sur les pipes et FIFO</h2>
                        <div class="text-block">
                            <p>Rappel:</p>
                            <pre><code class="shell">$ ls -lh /dev | more</code></pre>
                            <ul>
                                <li>Le noyau crée un canal de communication anonyme (<strong>pipe</strong> en anglais, <strong>tube</strong> en français) entre les processus <code>ls</code> et <code>more</code></li>
                                <p></p>
                                <li>Il est également possible de créer des tubes nommées (<strong>named pipes</strong> ou <strong>FIFO</strong>).</li>
                            </ul>
                        </div>
                    </section>
    
                    <section>
                        <h2>Tubes anonymes</h2>
                        <p>On peut créer un canal de communication anonyme en utilisant:</p>
                        <pre><code class="c">int pipe(int fildes[2]);</code></pre>
                        <ul>
                            <li><code>filedes[0]</code> est un descripteur de fichier représentant la sortie du tube/pipe (i.e. on peu lire sur ce descripteur);</li>
                            <li><code>filedes[1]</code> est un descripteur de fichier représentant l'entrée du tube/pipe (i.e. on peu écrire sur ce descripteur);</li>
                            <li>retourne -1 en cas d'erreur (voir <code>errno</code>);</li>
                            <li>Pas d'accès aléatoire possible.</li>
                        </ul>
                    </section>
    
                    <section id="concepts" class="slide level2">
                        <h2>Concepts generaux des pipes</h2>
                        <div class="text-block">
                            <p>Les tubes et FIFO:</p>
                            <ul>
                                <li>Permettent une communication à haute vitesse entre deux processus sur la même machine.</li>
                                <li>Ont deux extrémités: une ouverte en lecture et une ouverte en écriture.</li>
                                <li><strong>Sont unidirectionels</strong>: en conséquence du point précédent l'information ne transite que dans un sens.</b></li>
                            </ul>
                            <p></p>
                            <ul>
                                <li>Sont <strong>bloquants</strong>:
                                    <ul>
                                        <li>L'ouverture d'une extrémité bloque jusqu'à l'ouverture de l'autre extrémité.</li>
                                        <li>Permet d'établir des <strong>Rendez-Vous</strong></li>
                                        <li>Possibilité de <strong>deadlocks</strong> !</li>
                                    </ul>
                                </li>
                            </ul>
                        </div>
                        <aside class="notes">
                            <p>Insister sur la communication unidirectionelle: on ne peut pas avoir plusieur processus lisant le même pipe. On ne peux pas echanger de l'information des deux cotés</p>
                            <p>Etablir des rendez-vous: un processus ouvre en lecture et lit l'autre en ecriture et écrit. Lorsque les deux opérations sont effectués les deux processus ont rejoinds le rendez-vous</p>
                            <p>Deadlock: si il y a plusieurs rendez-vous un processus peut en attendre un autre a une endroits alors que l'autre processus l'attends a un autre</p>
                        </aside>
                    </section>
    
                    <section id="commande-shell-mkfifo1" class="slide level2">
                        <h2>Pipe nommé: Commande <code>mkfifo(1)</code></h2>
                        <div class="text-block">
                            <p>On peut créer un FIFO avec la commande:</p>
                            <pre><code class="shell">mkfifo [OPTION]... NOM...</code></pre>
                            <ul>
                                <li>Où <code>NOM</code> est le nom du FIFO à créer</li>
                                <li>Parmi les options on peut passer les permissions du FIFO par l'option <code>-m MODE</code>.</li>
                            </ul>
                        </div>
                        <fieldset style="margin-top:20px">
                            <legend>Exemple shell</legend>
                            <pre><code data-trim class="shell">
    $ mkfifo -m 0640 /tmp/fifo1
    $ ls -lh /dev > /tmp/fifo1
    
    $ more /tmp/fifo1  # Dans un autre shell
                            </code></pre>
                        </fieldset>
    
                        <aside class="notes">
                            <p>Insiter sur le fait que le processus ls est bloqué dans que aucun processus n'est connecté à la sortie du pipe</p>
                        </aside>
                    </section>
    
    
                    <section id="fonction-posix-mkfifo2" class="slide level2">
                        <h2>Fonction POSIX <code>mkfifo(2)</code></h2>
                        <p>On peut créer un FIFO avec l'appel système:</p>
                        <pre><code class="c">int mkfifo(const char *pathname, mode_t mode);</code></pre>
                        <ul>
                            <li><code>pathname</code> est le nom du fichier à créer</li>
                            <li><code>mode</code> représente les permissions (modifiées <code>mode &amp; ~umask</code>)</li>
                            <li>Un FIFO peut être ouvert en lecture/écriture comme n'importe quel fichier (<code>open/read</code>) mais il faut veiller à respecter la directionalité du fifo</li>
                            <li>Pas d'accès aléatoire possible.</li>
                        </ul>
                    </section>
    
                    <section id="exemple-prod" class="slide level2">
                        <h2>Exemple - <a href="examples/pipes/producer.c">producer</a></h2>
                        <pre><code id="ex-pipes-producer" class="c" style="font-size:70%;height:50vh;max-height:100vh">Include example there (see script)</code></pre>
                        <aside class="notes">
                            <p>Ici j'ai éviter de mettre des boucle while autour des read/write</p>
                            <p>A noter que si c'est au consomateur de supprime le fifo</p>
                        </aside>
                    </section>
    
                    <section id="exemple-cons" class="slide level2">
                        <h2>Exemple - <a href="examples/pipes/consumer.c">consumer</a></h2>
                        <pre><code id="ex-pipes-consumer" class="c" style="font-size:70%;height:50vh;max-height:100vh">Include example there (see script)</code></pre>
                    </section>
                </section>
            </div>
        </div>
    
        <!-- Initialize reveal.js with common configuration -->
        <!-- TODO find a way to have chalkboard script included from the config to avoid redundancy in each presentation -->
        <script src="../../../plugin/reveal.js-plugins/chalkboard/plugin.js"></script>
        <script src="../config.js" type="module"></script>
    </body>
    
    </html>