diff --git a/0.objectifs/index.html b/0.objectifs/index.html index e177946a28e106fe8d9b9a0835ede7f77ffd063b..f12718ffe7c20baa946b25e6b6565ac475849cc6 100644 --- a/0.objectifs/index.html +++ b/0.objectifs/index.html @@ -35,10 +35,11 @@ <ol> <li><a href="../1.processes/">Processus et virtualisation</a></li> <li class="slide-menu-item"><a href="../6.files">Les fichiers et les répertoires sous UNIX</a></li> - <li class="slide-menu-item"><a href="../7.io">Les entrées / sorties (I/O)</a></li> + <!-- <li class="slide-menu-item"><a href="../7.io">Les entrées / sorties (I/O)</a></li> --> <li>Communications inter-processus</li> <ul> <li><a href="../2.signals/">Les signaux</a></li> + <li><a href="../8.pipes/">Les pipes et FIFO</a></li> <li><a href="../3.sharedmem/">Les mémoires partagées</a></li> <li><a href="../4.sockets/">Les sockets / le réseau</a></li> </ul> diff --git a/8.pipes/examples/pipes/consumer.c b/8.pipes/examples/pipes/consumer.c new file mode 100644 index 0000000000000000000000000000000000000000..fbc384e5b65709b8125f16366d2719ddc910d074 --- /dev/null +++ b/8.pipes/examples/pipes/consumer.c @@ -0,0 +1,64 @@ +/* Inspiré d'un exemple de J. Menu */ + +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <sys/fcntl.h> +#include <unistd.h> // pour STDOUT_FILENO + +#define BUF_SIZE 64 + +int openFIFO( char *name ) { + int fifo = open( name, O_RDONLY ); + if( fifo < 0 ) { + perror( "Cannot open the fifo" ); + exit(EXIT_FAILURE); + } + printf( "The fifo %s is open\n", name ); + return fifo; +} + +void fifo2stdout( int fifo ) { + char buffer[BUF_SIZE]; + ssize_t nread, nwrit; + while(1) { + nread = read( fifo, buffer, BUF_SIZE ); + if( nread < 0 ) { + perror( "Reading fifo failed "); + exit(EXIT_FAILURE); + } + if( nread == 0 ) { + printf( "Received End-Of-File\n" ); + return; + } + nwrit = write( STDOUT_FILENO, buffer, nread ); + if( nwrit != nread ) { + perror( "Writing to STDOUT failed" ); + exit(EXIT_FAILURE); + } + } +} + +void disposeFIFO( int fifo, char *name ) { + int ret = close( fifo ); + if( ret < 0 ) { + perror( "Cannot close fifo." ); + } + ret = unlink( name ); + if( ret < 0 ) { + perror( "Cannot remove fifo." ); + } +} + +int main (int argc, char **argv ) { + if (argc != 2) { + printf( "Usage: %s <fifo_name> \n", argv[0] ); + exit(EXIT_FAILURE); + } + char *name = argv[1]; + int fifo = openFIFO( name ); + fifo2stdout( fifo ); + disposeFIFO( fifo, name ); + exit(EXIT_SUCCESS); +} + diff --git a/8.pipes/examples/pipes/producer.c b/8.pipes/examples/pipes/producer.c new file mode 100644 index 0000000000000000000000000000000000000000..a79be0144b8f3aa9d27882fba620f267113a1654 --- /dev/null +++ b/8.pipes/examples/pipes/producer.c @@ -0,0 +1,59 @@ +/* Inspiré d'un exemple de J. Menu */ + +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <sys/fcntl.h> +#include <sys/stat.h> +#include <unistd.h> // pour STDOUT_FILENO + +#define BUF_SIZE 64 + +int createFIFO( char *name ) { + int fifo = -1; + int result = mkfifo( name, 0600 ); + if( result < 0 ) { + perror( "Cannot create the fifo" ); + exit(EXIT_FAILURE); + } + printf( "Created fifo %s\n", name ); + fifo = open( name, O_WRONLY ); + if( fifo < 0 ) { + perror( "Cannot open the fifo" ); + exit(EXIT_FAILURE); + } + printf( "The fifo %s is open\n", name ); + return fifo; +} + +void stdin2fifo( int fifo ) { + char buffer[BUF_SIZE]; + ssize_t nread, nwrit; + while (1) { + nread = read(STDIN_FILENO, buffer, BUF_SIZE); + if( nread < 0 ) { + perror( "Reading STDIN failed "); + exit(EXIT_FAILURE); + } + if( nread == 0 ) { + printf( "Received End-Of-File \n" ); + return; + } + nwrit = write( fifo, buffer, nread ); + if( nwrit != nread ) { + perror( "Writing to fifo failed" ); + exit(EXIT_FAILURE); + } + } +} + +int main (int argc, char **argv) { + if (argc != 2) { + printf( "Usage: %s <fifo_name> \n", argv[0] ); + exit(EXIT_FAILURE); + } + int fifo = createFIFO( argv[1] ); + stdin2fifo( fifo ); + close(fifo); + exit(EXIT_SUCCESS); +} diff --git a/8.pipes/index.html b/8.pipes/index.html new file mode 100644 index 0000000000000000000000000000000000000000..4122fa1421c3d5be9ad0dbcd5f60974eeb7987c3 --- /dev/null +++ b/8.pipes/index.html @@ -0,0 +1,194 @@ +<!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.css' : '../../../css/print/paper.css'; + 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">Pipes et FIFO</h1> + <p class="author">Guillaume Chanel</p> + <p class="author">Remerciements à Jean-Luc Falcone</p> + </section> + + <!-- ######################## FIFO - PIPES ######################## --> + + <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> + </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> diff --git a/8.pipes/schema.png b/8.pipes/schema.png new file mode 100644 index 0000000000000000000000000000000000000000..8d9cd2bbef6f76200c15df682fb1ec503d0260c2 Binary files /dev/null and b/8.pipes/schema.png differ diff --git a/menu.html b/menu.html index 1fe48cbe0f94adf35a29eba1f631f00bb37c5353..5b403aad09d527c837751896d3df75dcde15e578 100644 --- a/menu.html +++ b/menu.html @@ -2,10 +2,11 @@ <li class="slide-menu-item"><a href="../0.objectifs">Objectifs</a></li> <li class="slide-menu-item"><a href="../1.processes/">Processus et virtualisation</a></li> <li class="slide-menu-item"><a href="../6.files">Les fichiers et les répertoires sous UNIX</a></li> - <li class="slide-menu-item"><a href="../7.io">Les entrées / sorties (I/O)</a></li> + <!-- <li class="slide-menu-item"><a href="../7.io">Les entrées / sorties (I/O)</a></li> --> <li class="slide-menu-item">Communications inter-processus</li> <ul style="margin-left: 10%"> <li class="slide-menu-item"><a href="../2.signals/">Les signaux</a></li> + <li class="slide-menu-item"><a href="../8.pipes/">Les pipes et FIFO</a></li> <li class="slide-menu-item"><a href="../3.sharedmem/">Les mémoires partagées</a></li> <li class="slide-menu-item"><a href="../4.sockets/">Les sockets / le réseau</a></li> </ul>