Select Git revision
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 <unistd.h>
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 & ~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>