diff --git a/Exercices/.gitkeep b/.gitkeep similarity index 100% rename from Exercices/.gitkeep rename to .gitkeep diff --git a/Blog/.gitignore b/Blog/.gitignore deleted file mode 100644 index 56cebfeca20534d74e237b6d9c002fa2ff440ece..0000000000000000000000000000000000000000 --- a/Blog/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# Ignore all _build directories -_build -# Ignore all files ending with ~ -*~ -*.o -\#* -blog/* \ No newline at end of file diff --git a/Blog/2014/01/22/bienvenue.rst b/Blog/2014/01/22/bienvenue.rst deleted file mode 100644 index 6cd30690fe67a91a6263fbb4fee166627758ec67..0000000000000000000000000000000000000000 --- a/Blog/2014/01/22/bienvenue.rst +++ /dev/null @@ -1,21 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012-2014 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Bienvenue -========= - -.. author:: default -.. categories:: none -.. tags:: none -.. comments:: - - -Ce site comprend l'ensemble des informations relatives au cours `SINF1252 <http://www.uclouvain.be/cours-2015-LSINF1252.html>`_ donné aux `étudiants en informatique <http://www.uclouvain.be/info.html>`_ à l'`Université catholique de Louvain <http://www.uclouvain.be>`_ (UCL). - - - `Théorie </pages/Theorie.html>`_ - - `Outils informatiques </pages/Outils.html>`_ - - `Exercices et Projets </pages/Exercices.html>`_ - -Ce site web et l'ensemble des documents écrits pour le cours sont distribués sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - diff --git a/Blog/conf.py b/Blog/conf.py deleted file mode 100644 index c0f6c1e2eee3977edf7db3c82a8a9638d142428e..0000000000000000000000000000000000000000 --- a/Blog/conf.py +++ /dev/null @@ -1,93 +0,0 @@ -# -*- coding: utf-8 -*- - -import tinkerer -import tinkerer.paths - -# ************************************************************** -# TODO: Edit the lines below -# ************************************************************** - -# Change this to the name of your blog -project = 'My blog' - -# Change this to the tagline of your blog -tagline = 'Add intelligent tagline here' - -# Change this to the description of your blog -description = 'This is an awesome blog' - -# Change this to your name -author = 'Winston Smith' - -# Change this to your copyright string -copyright = '1984, ' + author - -# Change this to your blog root URL (required for RSS feed) -website = 'http://127.0.0.1/blog/html/' - -# ************************************************************** -# More tweaks you can do -# ************************************************************** - -# Add your Disqus shortname to enable comments powered by Disqus -disqus_shortname = None - -# Change your favicon (new favicon goes in _static directory) -html_favicon = 'tinkerer.ico' - -# Pick another Tinkerer theme or use your own -html_theme = "flat" - -# Theme-specific options, see docs -html_theme_options = { } - -# Link to RSS service like FeedBurner if any, otherwise feed is -# linked directly -rss_service = None - -# Generate full posts for RSS feed even when using "read more" -rss_generate_full_posts = False - -# Number of blog posts per page -posts_per_page = 10 - -# Character use to replace non-alphanumeric characters in slug -slug_word_separator = '_' - -# ************************************************************** -# Edit lines below to further customize Sphinx build -# ************************************************************** - -# Add other Sphinx extensions here -extensions = ['tinkerer.ext.blog', 'tinkerer.ext.disqus'] - -# Add other template paths here -templates_path = ['_templates'] - -# Add other static paths here -html_static_path = ['_static', tinkerer.paths.static] - -# Add other theme paths here -html_theme_path = ['_themes', tinkerer.paths.themes] - -# Add file patterns to exclude from build -exclude_patterns = ["drafts/*", "_templates/*"] - -# Add templates to be rendered in sidebar here -html_sidebars = { - "**": ["recent.html", "searchbox.html"] -} - -# ************************************************************** -# Do not modify below lines as the values are required by -# Tinkerer to play nice with Sphinx -# ************************************************************** - -source_suffix = tinkerer.source_suffix -master_doc = tinkerer.master_doc -version = tinkerer.__version__ -release = tinkerer.__version__ -html_title = project -html_use_index = False -html_show_sourcelink = False -html_add_permalinks = None \ No newline at end of file diff --git a/Blog/index.html b/Blog/index.html deleted file mode 100644 index 1b575396f6a72005402dcc2b6216ee52288fc320..0000000000000000000000000000000000000000 --- a/Blog/index.html +++ /dev/null @@ -1,8 +0,0 @@ -<!doctype html> -<html> - <head> - <meta http-equiv="REFRESH" content="0; url=./blog/html/index.html" /> - <title></title> - </head> - <body></body> -</html> \ No newline at end of file diff --git a/Blog/master.rst b/Blog/master.rst deleted file mode 100644 index 86a1d97584b434c8b681bb6b4e1a36f60a3355dc..0000000000000000000000000000000000000000 --- a/Blog/master.rst +++ /dev/null @@ -1,7 +0,0 @@ -Sitemap -======= - -.. toctree:: - :maxdepth: 1 - - diff --git a/Blog/pages/auteurs.rst b/Blog/pages/auteurs.rst deleted file mode 100644 index 5dd191618bce4edf2f87a0dabd0b4698d2493b35..0000000000000000000000000000000000000000 --- a/Blog/pages/auteurs.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012-2014 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Auteurs -======= - -Les documents relatifs au cours ont été écrits par différents auteurs. - -La partie théorique a été principalement écrite par Olivier Bonaventure avec l'aide de Grégory Detal, Christoph Paasch et de nombreuses suggestions d'étudiants et d'assistants. - -La partie relative aux outils informatiques a été initié par Olivier Bonaventure, Grégory Detal et Christoph Paasch, mais la majorité du texte a été écrit par des étudiants après avoir suivi le cours avec fruit. Benoît Legat a écrit toute la section sur git. Nicolas Houtain et Maxime Demol ont écrit notamment les sections relatives au shell. Antoine Cailliau a écrit la section sur Cunit. - -Les exercices ont été écrits par Olivier Bonaventure, Grégory Detal et Christoph Paasch. Floriant Chalet et Kilian Verhetsel ont fortement contribué aux exercices avec correction automatique sur la plateforme pythia/inginious. - - - - diff --git a/Blog/pages/exercices.rst b/Blog/pages/exercices.rst deleted file mode 100644 index 5326dc6749b8cc1d01184c44e9164a8a1a630326..0000000000000000000000000000000000000000 --- a/Blog/pages/exercices.rst +++ /dev/null @@ -1,16 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012-2014 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Exercices -========= - - - -Les exercices du cours `SINF1252 <http://www.uclouvain.be/cours-2015-LSINF1252.html>`_ donné aux `étudiants en informatique <http://www.uclouvain.be/info.html>`_ à l'`Université catholique de Louvain <http://www.uclouvain.be>`_ (UCL) sont disponibles sous trois formats : - - - `HTML <http://sites.uclouvain.be/SystInfo/notes/Exercices/html/index.html>`_ accessible directement depuis un navigateur web - - `pdf <http://sites.uclouvain.be/SystInfo/distrib/SINF1252-Exercices.pdf>`_ utilisable avec Adobe Acrobat ou pour impression - - `epub <http://sites.uclouvain.be/SystInfo/distrib/SINF1252-Exercices.epub>`_ utilisable avec une tablette - -Les exercices sont mis à jour régulièrement au fur et à mesure de l'avancement du cours. Il est inutile de les imprimer. diff --git a/Blog/pages/outils.rst b/Blog/pages/outils.rst deleted file mode 100644 index 38d959a4d387b3ee624dcde6785074532daf4e25..0000000000000000000000000000000000000000 --- a/Blog/pages/outils.rst +++ /dev/null @@ -1,19 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012-2014 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Outils informatiques -==================== - -Cette annexe reprend les outils informatiques utiles pour le cours `SINF1252 <http://www.uclouvain.be/cours-2015-LSINF1252.html>`_ suivi par les `étudiants en informatique <http://www.uclouvain.be/info.html>`_ à l'`Université catholique de Louvain <http://www.uclouvain.be>`_ (UCL). Elle est disponible sous trois formats : - - - `HTML <http://sites.uclouvain.be/SystInfo/notes/Outils/html/index.html>`_ accessible directement depuis un navigateur web - - `pdf <http://sites.uclouvain.be/SystInfo/distrib/SINF1252-Outils.pdf>`_ utilisable avec Adobe Acrobat ou pour impression - - `epub <http://sites.uclouvain.be/SystInfo/distrib/SINF1252-Outils.epub>`_ utilisable avec une tablette - - -La version HTML est préférable car elle contient de nombreux liens vers les pages de manuels des différents logiciels utilisés. - - - -Les étudiants sont invités à améliorer cette section en soumettant des patches via https://github.com/obonaventure/SystemesInformatiques diff --git a/Blog/pages/source.rst b/Blog/pages/source.rst deleted file mode 100644 index 1a57e8b00b7fa9cfbf7dcfed3f8774f8015bca78..0000000000000000000000000000000000000000 --- a/Blog/pages/source.rst +++ /dev/null @@ -1,15 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012-2014 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Source -====== - - -L'ensemble des sources de ce site web et des notes du cours de systèmes informatiques sont disponibles depuis https://github.com/obonaventure/SystemesInformatiques - -Le site web a été écrit en restructured text en utilisant l'outil tinkerer. - -Les notes sont écrites en restructured text et converties en HTML, pdf et epub en utilisant `sphinx <http://sphinx.pocoo.org>`_ - -Toutes les suggestions pour l'amélioration des notes, exercices ou de la section relative aux outils sont les bienvenues. diff --git a/Blog/pages/theorie.rst b/Blog/pages/theorie.rst deleted file mode 100644 index d32b5581822f123c53276302dca092115db5e7da..0000000000000000000000000000000000000000 --- a/Blog/pages/theorie.rst +++ /dev/null @@ -1,15 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012-2014 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Theorie -======= - -Les notes du cours `SINF1252 <http://www.uclouvain.be/cours-2015-LSINF1252.html>`_ donné aux `étudiants en informatique <http://www.uclouvain.be/info.html>`_ à l'`Université catholique de Louvain <http://www.uclouvain.be>`_ (UCL) sont disponibles sous trois formats : - - - `HTML <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/index.html>`_ accessible directement depuis un navigateur web - - `pdf <http://sites.uclouvain.be/SystInfo/distrib/SINF1252-Theorie.pdf>`_ utilisable avec Adobe Acrobat ou pour impression - - `epub <http://sites.uclouvain.be/SystInfo/distrib/SINF1252-Theorie.epub>`_ utilisable avec une tablette - - -Ce site web et l'ensemble des documents écrits pour le cours sont distribués sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ diff --git a/Exercices/Programmes/prog-1.rst b/Exercices/Programmes/prog-1.rst deleted file mode 100644 index cf20bb9bc90f232f77961aa0e340e4894f90ef89..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/prog-1.rst +++ /dev/null @@ -1,298 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Exercices -========= - - - -1. Exercices de manipulation du shell -------------------------------------- - -Pour rappel, quelques commandes de base dans le shell pour gérer les dossiers et fichiers: - - - `ls(1)`_ : affiche la liste des fichiers et dossiers du répertoire spécifié - - `mv(1)`_ : utilitaire pour renommer ou déplacer un fichier ou dossier - - `cp(1)`_ : copie un fichier ou dossier (``-r`` pour les dossiers) - - `rm(1)`_ : efface un fichier ou dossier - - `mkdir(1)`_ : crée un répertoire - - `rmdir(1)`_ : efface un répertoire vide - - `cd(1posix)`_ : change le répertoire courant - - `pwd(1)`_ : affiche le répertoire courant - - `grep(1)`_ : permet de faire des recherches sur le contenu des fichiers - -Pour vous familiariser avec le shell, faites les petits exercices suivants dans le shell: - -#. Créez, dans un nouveau répertoire ``my_dir`` le fichier nommé ``first`` contenant le texte "`Inserer`". Vérifiez chaque étape en utilisant une des commandes `ls(1)`_, `pwd(1)`_ et `cat(1)`_. -#. Copiez le fichier ``first`` vers ``second`` et ajoutez la ligne "`Retirer`" à ``second``. -#. Comment pourriez-vous afficher la taille des fichiers avec `ls(1)`_? -#. Concaténez ``first`` et ``second`` dans un nouveau fichier ``third`` (sans utiliser la command `echo(1)`_) -#. Utilisez `grep(1)`_ pour afficher le numéro de la ligne sur laquelle se trouve le mot "`Retirer`" dans ``second``. -#. Retournez dans le répertoire parent de ``my_dir`` et copiez le dossier complet ``my_dir`` dans ``my_dir_2``. -#. Effacez le dossier entier ``my_dir`` en une seule commande (utilisez `rm(1)`_). - -Vous trouverez également sur `le cours LSINF1252 sur inginious <https://inginious.info.ucl.ac.be/course/LSINF1252>`_ les exercices suivants : - -#. Utilisation de la commande `grep(1)`_ : https://inginious.info.ucl.ac.be/course/LSINF1252/s1_grep -#. Utilisation des pipes : https://inginious.info.ucl.ac.be/course/LSINF1252/s1_pipes -#. Utilisation de la commande `tar(1)`_ : https://inginious.info.ucl.ac.be/course/LSINF1252/s1_tar -#. Capture the flag (1): https://inginious.info.ucl.ac.be/course/LSINF1252/s1_ctf1 -#. Capture the flag (2): https://inginious.info.ucl.ac.be/course/LSINF1252/s1_ctf2 - -.. only:: staff - - - Il faudrait quand même qu'ils l'aient fait une fois avant le TP - - Faire l'exercice sur les pipes avant de faire le CTF - - Si un élève est bloqué, relire les dernières consignes, si rien d'explicite taper "./.suite" - - Quand les consignes disent de - dire quelque chose de spécifique = "echo parole | ./interlocuteur" - parler à quelqu'un = "./interlocuteur" - - Faire TRÈS attention à taper correctement l'identifiant inginious au début, sinon ce n'est qu'en ayant fini le CTF qu'ils verront l'erreur - - Attention, quand on tape la réponse finale dans inginious, elle est écrite sous la forme "[hash] -", il faut copier-coller la sortie en entier, le tiret compris, pas juste le hash - - L'exercice est individuel, la réponse dépend de l'identifiant de l'étudiant - - En cas de problème avec le code de vérification (il n'y en a théoriquement pas, mais qui sait) le tuteur peut générer la clé à entrer dans inginious comme suit (depuis la racine) : - cd .ressources/script - ./init lIdentifiantInginious - ./next - ./next - ./next - ./next - ./next - - -2. Découverte du C ------------------- - -Certains côtés du C sont très proches du langage Java que vous connaissez déjà . Ce n'est pas surprenant -puisque Java a été conçu avec le langage C comme base. Les inventeurs de Java ont ajouté tout ce qui -était nécessaire pour supporter les objets et ont retiré la gestion explicite de la mémoire. Les premiers -exercices `inginious en C <https://inginious.info.ucl.ac.be/course/LSINF1252>`_ sont très proches de ceux -que vous aviez réalisé en Java. - -#. Calcul de la valeur absolue d'une entier: https://inginious.info.ucl.ac.be/course/LSINF1252/absolute_value -#. Calcul de la factorielle d'un nombre entier: https://inginious.info.ucl.ac.be/course/LSINF1252/factorial -#. Recherche d'un élément dans un tableau d'entiers: https://inginious.info.ucl.ac.be/course/LSINF1252/tab_find - -#. Compilez et exécutez le code suivant. Expliquez ce que fait l'appel à `printf(3)`_. - - .. code-block:: c - - int f() - { - int a = 1252; - printf("%d\n", a); - } - - int main(int argc, const char *argv[]) - { - f(); - } - - -#. Expliquez à quoi sert l'option ``-Werror`` de ``gcc``. Regardez la manpage (`gcc(1)`_). - - .. only:: staff - - .. note:: - ``-Werror`` - Make all warnings into errors. - -#. Recompilez le code du point `4` avec l'option ``-Werror``, que se passe-t-il ? Que faut-t-il rajouter dans le code pour qu'il compile sans erreurs ? - - .. only:: staff - - .. note:: - - Le programme ne compile plus. Il faut inclure ``stdio.h`` parce que C nécessite d'avoir une déclaration des fonctions. - -#. (bonus) comment se fait-il que ``gcc`` compilait sans problème au point `4`? - - .. only:: staff - - .. note:: - - ``gcc`` crée une déclaration implicite des fonctions de la librairie C. Il n'affiche qu'un warning. - -#. Lorsque j'exécute le programme corrigé du point `6` dans une console, j'ai accès à plusieurs variables. L'une d'elles est ``$?`` qui permet de récupérer la valeur de retour du dernier programme exécuté. Expliquez à quoi sert cette valeur. - - .. code-block:: console - - $ gcc -Werror -std=c99 test.c -o test - $ ./test - 1252 - $ echo $? - 0 - - .. only:: staff - - .. note:: - - voir notes de cours. - -#. Expliquez à quoi sert l'option ``-Wall`` de ``gcc``. - - .. only:: staff - - .. note:: - - ``-Wall`` - This enables all the warnings about constructions that some users consider questionable, and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros. - -#. Recompilez le code corrigé du point `6` avec les options ``-Wall`` et ``-Werror``, que se passe-t-il ? Que faut-il rajouter dans le code pour qu'il compile sans erreurs ? - - .. only:: staff - - .. note:: - - ``-Wall``: warning si une fonction ne renvoie pas de valeur. Il faut donc ajouter ``return 0;`` à la fin de la ``main``. - - - .. only:: staff - - #. Compilez le code suivant (sans les options ``-Wall`` et ``-Werror``). Expliquez ce que sont les arguments de la fonction ``main``. Expliquez ce que fait `atoi(3)`_ (voir `strtol(3)`_ pour une fonction similaire). Exécutez ensuite le code avec ou sans arguments. Qu'observez-vous ? Comment se protéger du fait qu'un utilisateur ne va pas forcément rentrer le bon nombre d'arguments ? - - .. code-block:: c - - #include <stdlib.h> - int main(int argc, const char *argv[]) - { - int a = atoi(argv[1]); - printf("%d\n", a); - } - - .. note:: - - ``argc`` = nombre d'arguments. - ``argv`` = tableau de chaine de caractère contenant le nom de l'exécutable suivi des arguments. - ``atoi`` = transforme une chaine de caractère en un entier. - Le programme renvoi une segmentation fault lorsque l'on ne passe pas d'argument. Il faut donc utiliser ``argc`` pour tester que l'on a le bon nombre d'argument. - - - .. only:: staff - - #. Ecrivez un programme qui va itérer (avec une boucle ``for`` et une boucle ``while``) et afficher tous les arguments qui lui sont passés à la sortie standard. - - .. note:: - - .. code-block:: c - - #include <stdio.h> - int main(int argc, const char *argv[]) - { - int i; - for (i = 1; i < argc; i++) - printf("%s\n", argv[i]); - return 0; - } - -#. Ecrivez deux programmes qui réagissent de façon similaire à `true(1)`_ et `false(1)`_ en utilisant `exit(3)`_. Vous pouvez tester le bon fonctionnement de votre programme en exécutant le code suivant dans une console: - - .. code-block:: console - - $ if ./true; then echo "true fonctionne"; fi - true fonctionne - $ if ! ./false; then echo "false fonctionne"; fi - false fonctionne - - Bash permet aussi de faire des ``else``. Trouvez comment faire en regardant ce `lien <http://tldp.org/LDP/abs/html/tests.html>`_. - .. only:: staff - - .. note:: - - ``true`` retourne toujours 0: - .. code-block:: c - - #include <stdlib.h> - int main(int argc, const char *argv[]) - { - exit(0); - } - - ``false`` retourne toujours quelque chose != 0: - .. code-block:: c - - #include <stdlib.h> - int main(int argc, const char *argv[]) - { - exit(1); - } - - - -.. only:: staff - - #. Faites l'exercice sur `commandetest <https://inginious.info.ucl.ac.be/course/LSINF1252/commandetest>`_ sur la commande `test(1)`_. - - INGInious est un environnement qui permet de soumettre du code, et des tests sont automatiquement exécutés sur ce code. Cela vous permettra de vérifier que votre programme fonctionne. - - Pour vous connecter sur INGInious, utilisez votre login INGI que vous recevrez durant la première séance de TP. - - - #. Faites de même pour la commande `expr(1)`_. On vous demande d'implémenter les expressions suivantes : ``+``, ``-``, ``*``, ``/`` et ``%``, mais cette fois-ci sans utiliser INGInious. Vous devriez tester votre programme vous-même et assurer le bon fonctionnement de celui-ci. - - N'oubliez pas de respecter les valeurs de retour qui sont décrites dans les man-pages. - - -.. only:: staff - - #. En utilisant le shell et un programme C, essayez de déterminer expérimentalement le nombre maximum d'arguments que vous pouvez passer à un programme C. Y a-t-il une limite à ce nombre d'arguments ? Si oui, d'où vient-elle et de quoi dépend-elle ? - -3. Question de bilan final --------------------------- - -Le fizz buzz est un programme qui affiche sur la sortie standard pour chaque entier ``n``: - -- ``fizz buzz`` si le nombre est divisible par 3 et par 5; -- ``fizz`` si le nombre est divisible par 3; -- ``buzz`` si le nombre est divisible par 5; -- La valeur de ``n`` sinon. - -Un étudiant implémente cet algorithme en Bash. Malheureusement, son script comporte plusieurs erreurs. -Pouvez-vous identifier et corriger les erreurs en question? Son code est disponible ci-dessous. - -.. code-block:: bash - - #!/bin/bash - - x=1 - limit=100 - if [ ! -z "$1" ] - then - limit=$1 - fi - - while [[ $x < "$limit" ]] - do - if [[0 -eq "($x%3)" && 0 -eq "($x%5)"]] - then - # Check if divide by 3 & 5 - echo "fizz buzz" - elif [[0 == "($x%5)"]] - then - # Check if divide by 5 - echo "buzz" - elif [[0 == "($x%3)"]] - then - # Check if divide by 3 - echo "fizz" - else - echo "$x" - fi - x=$(( x + 1 )) - done - - -Il y a 4 différents groupes d'erreurs. Trois d'entre-eux peuvent être facilement repérés via -`ShellCheck <https://www.shellcheck.net>`_, un outil de vérification statique de code Bash. L'utilisation -systématique de ce genre d'outils vous évitera bon nombre d'erreurs fréquentes lors de la rédaction de code. - -.. only:: staff - - #. Double crochets qui manque un espace - - #. == au lieu de -eq - - #. ! -z au lieu de -n - - #. < au lieu de -lt . Cette erreur n'est pas détectée par ShellCheck. diff --git a/Exercices/Programmes/prog-10.rst b/Exercices/Programmes/prog-10.rst deleted file mode 100644 index f51803116b1f71d9e811e6b53ac50abaf002c52a..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/prog-10.rst +++ /dev/null @@ -1,80 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Exercices ---------- - -#. En utilisant `signal(2)`_, écrivez une fonction C ``sig_ignored`` qui prend comme argument un numéro de signal et retourne ``true`` si le signal passé en argument est ignoré par le processus et ``false`` sinon. - - .. only:: staff - - Il suffit de tester la valeur de retour de signal. sigaction est une autre possibilité - -#. A votre avis, pourquoi le système d'exploitation refuse-t-il l'exécution de la ligne ``signal(SIGKILL,SIG_IGN)`` ? - - .. only:: staff - - Bien évidemment pour garantir qu'il sera toujours possible de tuer un processus. - -#. Sachant qu'en tapant `Ctrl-C` durant l'exécution d'un processus le shell envoie un signal ``SIGINT`` à ce processus, comment feriez-vous pour qu'un de vos programmes puisse survivre à `Ctrl-C` ? - - .. only:: staff - - Il faut évidemment définir un handler pour SIGINT et traiter ce signal, ce n'est pas très difficile à faire - -#. Le programme :download:`/Programmes/src/alarm.c` que nous avons utilisé pour illustrer l'appel système `alarm(2)`_ contient une condition de course qui peut dans certains cas empêcher l'interruption de l'appel système `read(2)`_. Un étudiant propose de résoudre ce problème en utilisant une variable modifiée par la fonction de traitement de ``SIGALRM``. Que pensez-vous du programme :download:`/Programmes/src/alarm3.c` ? - - .. only:: staff - - Cette solution n'est pas fiable car il est possible que le processus aie été bloqué juste après l'exécution du if mais juste avant l'appel à read - -#. La page de manuel `signal(7)`_ définit les signaux suivants : - - - ``SIGSYS`` - - ``SIGPIPE`` - - Expliquez dans quels cas ces deux signaux peuvent être générés et délivrés à un processus. - - .. #. Les constantes ``SIG_DFL`` et ``SIG_IGN`` utilisées par `signal(2)`_ sont-elles des entiers ou un autre type? - -#. Unix définit un signal ``SIGCHLD`` qui est envoyé lorsqu'un fils se termine. Quel est l'intérêt d'un tel signal pour le processus père? - - .. only:: staff - - Cela permet au père de savoir quand il doit effectuer un wait. - -#. Un processus a exécuté une fonction de traitement du signal ``SIGUSR1`` et une autre fonction pour traiter le signal ``SIGUSR2``. La fonction qui traite ``SIGUSR1`` est une fonction assez complexe qui prend des centaines d'instructions. Que se passe-t-il si pendant que le processus est en train de traiter le signal ``SIGUSR1``, un autre processus lui envoie : - - - ``SIGUSR1`` - - ``SIGUSR2`` - -#. Considérons la fonction de gestion des signaux suivante : - - .. code-block:: c - - static void sig_handler(int signum) { - char *msg="Reçu signal \n"; - write(STDERR_FILENO,msg,strlen(msg)); - } - - Cette fonction utilise l'appel système `write(2)`_ qui peut modifier la variable ``errno`` en cas d'erreur. Modifiez-la de façon à ce que toute modification à ``errno`` n'affecte pas l'utilisation de ``errno`` dans le programme en cours d'exécution. - -#. Dans les programmes :download:`/Programmes/src/process-sem-before.c` et :download:`/Programmes/src/process-sem-after.c`, on a choisi de créer le sémaphore dans un processus avec `sem_open(3)`_ et de le supprimer avec `sem_unlink(3)`_ dans un autre processus. Est-ce possible de créer et supprimer le sémaphore dans le même processus ? - -#. Un processus ``P`` ouvre le fichier ``fichier`` avec l'appel système `open(2)`_. Celui-ci est associé au descripteur ``fd``. Ensuite, le processus utilise `fork(2)`_ pour créer un processus fils. - - - représenter les open-file objects utilisés - - le père et le fils peuvent-ils lire sur ``fd`` ? - - le processus fils utilise l'appel système `chmod(2)`_ pour rendre le fichier inaccessible en écriture et lecture. Après cette opération, le père et le fils peuvent-ils lire sur ``fd`` ? - - le père ferme le descripteur ``fd``. Après cette opération, le père et le fils peuvent-ils lire sur ``fd`` ? - - le fils exécute `unlink(2)`_ sur le fichier. Après cette opération, le père et le fils peuvent-ils lire sur ``fd`` ? - -#. Même question que ci-dessus, mais en remplaçant le fichier par un sémaphore nommé et `open(2)`_ par `sem_open(3)`_ ? - -#. Le programme :download:`/Programmes/src/miniprojet.c` utilise des sémaphores nommés pour synchroniser la production/consommation entre deux processus. Le processus père crée le fichier ``my_file.txt`` y écrit une valeur. Le processus fils est chargé de lire la donnée présente dans le fichier et l'affiche à la console. Ce programme tourne à l'infini et donc il faut l'arrèter avec la commande ``Ctrl-C``. Malheureusement dans ce cas les sémaphores nommés ne sont pas supprimés correctement. Après avoir terminé le programme avec `Ctrl-C` vous verrez qu'il reste des sémaphores dans ``/dev/shm/``. - - Comment modifier ce programme pour gèrer la terminaison correcte des processus lors de la pression sur ``Ctrl-C``. Pour ce faire, vous devez modifier le programme de façon à ce qu'il libère toutes les ressources allouées avant de se terminer. Ceci peut se faire en traitant le signal envoyé au processus par le shell lorsque l'utilisateur presse ``Ctrl-C``. - -#. Faites les deux exercices INGInious sur `les signaux <https://inginious.info.ucl.ac.be/course/LSINF1252/signaux>`_ et `le sleep <https://inginious.info.ucl.ac.be/course/LSINF1252/sleep>`_. - diff --git a/Exercices/Programmes/prog-11.rst b/Exercices/Programmes/prog-11.rst deleted file mode 100644 index 945a5c23a00db024b6ec077ffaba8b4b166e98d2..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/prog-11.rst +++ /dev/null @@ -1,83 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Exercices ---------- - - -#. Considérons le disque dur ST31500341AS dont les caractéristiques techniques sont présentées dans les notes (1.5TB, 7200 RPM, 32MB Cache, la datasheet est disponible `ici <http://www.seagate.com/staticfiles/support/disc/manuals/desktop/Barracuda%207200.11/100507013e.pdf>`_). Le constructeur annonce un débit de transfert de 300 MBytes par seconde au maximum. Sachant que chaque secteur fait 512 bytes, et que ce disque utilise 63 secteurs par piste, calculez le débit obtenu lors du transfert d'une piste complète et comparez ce débit à celui annoncé par le constructeur. - -#. Considérons un ordinateur utilisant des pages de 1024 bytes et des adresses virtuelles encodées sur 13 bits et des adresses réelles également sur 13 bits. La table des pages actuellement utilisée est la suivante : - - ======== ======== ======= - Indice Validité Adresse - ======== ======== ======= - [111] true 001 - [110] true 000 - [101] true 111 - [100] false - - [011] true 011 - [010] false - - [001] true 010 - [000] true 100 - ======== ======== ======= - - Sur base de cette table des pages, déterminez si les adresses suivantes correspondent à des données se trouvant en mémoire et le cas échéant l'adresse physique correspondante : - - - ``1100110111010`` - - ``0110000110010`` - - ``0000010010001`` - - ``1000010001001`` - - ``0000000000000`` - -#. Un processus est chargé en mémoire. L'output de ``/proc/pid/maps`` est le suivant : - - .. code-block:: console - - 08047000-080f5000 r-xp 00000000 08:01 553302 /bin/bash - 080f5000-080fa000 rw-p 000ae000 08:01 553302 /bin/bash - 09047000-09107000 rw-p 09047000 00:00 0 [heap] - bffaa000-bffbf000 rw-p bffe9000 00:00 0 [stack] - - En supposant que la mémoire RAM était initialement vide et que le processus a été chargé à partir de l'adresse ``0x00000000`` en mémoire physique, construisez la table des pages de ce processus si il utilise des pages de 4 KBytes. - -#. Un ordinateur utilise de la mémoire virtuelle avec des adresses virtuelles sur 32 bits et des adresses physique sur 26 bits. Sa mémoire virtuelle est découpée en pages de 4 KBytes. Si chaque entrée de la table des pages occupe 32 bits, quelle est la zone mémoire occupée par la table des pages ? Le nombre de lignes dans la table des pages varie-t-il si les adresses physiques passent à 32 bits ou 36 bits ? - -#. Un ordinateur dispose de 32 GBytes de mémoire RAM. Il utilise des adresses virtuelles de 64 bits et des pages de 4 KBytes. Combien de lignes doit contenir sa table des pages ? - -#. Comparez les performances du programme :download:`/../Theorie/MemoireVirtuelle/src/cp2.c` avec l'utilitaire `cp(1)`_ standard de Linux. - -#. Un programme construit en mémoire un gros tableau contenant 10 millions d'entiers. Initialisez ce tableau avec des entiers ayant des valeurs croissante. Pour sauvegarder le fichier sur disque, trois solutions s'offrent à vous : - - - écrire directement les entiers sur disque sous forme binaire en utilisant l'appel système `write(2)`_ en passant un pointeur vers chaque entier à cet appel système - - écrire les entiers sur disque sous forme d'un fichier texte avec un entier par ligne - - écrire les entiers directement sur disque, mais en utilisant `mmap(2)`_ plutôt que `write(2)`_ - - Dans les salles informatiques, vous pouvez stocker les données dans trois répertoires qui risquent d'avoir des performances différentes : - - - votre répertoire de login qui est accessible depuis un serveur de fichiers - - le répertoire ``/tmp`` qui sous Linux est en général stocké directement en mémoire RAM - - un clé USB - - Ecrivez un programme qui permet de comparer les performances de ces trois méthodes permettant d'écrire sur disque sur les trois dispositifs de stockage. Quelle est la solution la plus rapide et pourquoi (pensez à utiliser `fsync(2)`_ ou `msync(2)`_ pour forcer le système à écrire vos données sur disque à la fin de l'exécution de votre programme). - -#. Ecrivez un programme similaire au précédent mais qui permet de comparer les performances en lecture. Utilisez `fscanf(3)`_ par exemple pour lire les données du fichier texte. - -#. git est un outil permettant de générer intelligemment les projets informatiques dans lesquels plusieurs développeurs participent à l'écriture du code source. Il existe de nombreux livres et sites web concernant subversion. Cet exercice a pour objectif de vous présenter un workflow classique utilisant ``git``. Pour réaliser cet exercice, vous avez besoin d'un répertoire partagé géré par ``git``. - - - `git(1)`_ supporte de nombreuses sous-commandes. Pour accéder au manuel relatif à une de ces sous-commandes, il faut utiliser ``git help commande`` - - Créez un répertoire de test que vous pourrez supprimer par après, ``mkdir test`` - - Ajoutez ce répertoire à votre repository subversion ``git add test`` - - Enregistrez cette modification sur le serveur en utilisant ``git commit -m "Ajout du répertoire de test"``. L'argument ``-m`` permet de spécifier un commentaire à votre ``commit``. Prenez l'habitude d'expliquer en une ou quelques lignes la modification que vous avez fait, cela vous permettra de revenir plus facilement en arrière si nécessaire. Envoyez ensuite votre modification sur le serveur via ``git push``. - - Créez un fichier texte nommé ``test.txt`` dans votre répertoire. Ce fichier contiendra une ligne de ``aaaaa`` et une deuxième ligne de ``bbbbbb``. Ajoutez ce fichier avec ``git add`` puis faites le ``git commit`` suivi du ``git push`` - - Depuis un autre compte étudiant, faites ``git pull`` pour charger ce nouveau répertoire et le fichier le contenant. - - Un étudiant utilisant le répertoire modifie la première ligne du fichier et la remplace par ``aaXaa``. En même temps, l'autre étudiant modifie la deuxième ligne du fichier et la remplace par ``bbbYbbb``. Une fois ces modifications faites, utilisez ``git commit`` puis ``git push`` pour pousser la modification sur le serveur. - - Faites ``git log test.txt`` pour voir la liste des modifications faites sur ce fichier - - Utilisez ``git diff test.txt`` pour voir la différence entre votre version du fichier et celle du serveur - - Essayez maintenant de faire des modifications à la même ligne du fichier, par exemple en ajoutant chacun une ligne supplémentaire. Ce faisant, vous allez créer un conflit. Utilisez ``git merge`` pour résoudre ce conflit. - - -.. rubric:: Footnotes - - diff --git a/Exercices/Programmes/prog-12.rst b/Exercices/Programmes/prog-12.rst deleted file mode 100644 index 43b4d2fd5c58aaf17ae74351a9ea10946459b879..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/prog-12.rst +++ /dev/null @@ -1,24 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Exercices ---------- - -#. L'appel système `shmget(2)`_ supporte également le drapeau ``IPC_EXCL`` en plus du drapeau ``IPC_CREAT``. Expliquez à quoi ce drapeau peut servir et dans quel cas il peut être utile. - -#. Un processus père ouvre un segment de mémoire partagée avec l'appel système ``shmget(key, 4096, IPC_CREAT | S_IRUSR | S_IWUSR )``. Un de ses processus fils peut-il exécuter ``shmget(key, 4096, S_IRUSR )`` ? Si oui, ce processus peut-il ensuite attacher cette page en utilisant : - - - ``shmat(shm_id, NULL, SHM_RDONLY)`` - - ``shmat(shm_id, NULL, SHM_EXEC)`` - -#. Lorsque l'on utilise l'appel système `shmat(2)`_ avec ``NULL`` comme deuxième argument, le système d'exploitation choisit l'adresse à laquelle le segment de mémoire va être attaché. Cela pose des difficultés si l'on veut stocker des pointeurs en mémoire partagée. Un étudiant propose de d'abord allouer la zone mémoire avec `malloc(3)`_ et d'ensuite attacher le segment de mémoire à cet endroit. Il a réalisé un test avec un processus père et son fils et les deux segments de mémoire partagée se retrouvent à la même adresse. Il en conclut que cela permet de résoudre le problème. Qu'en pensez-vous ? - -#. Deux processus utilisent un segment de mémoire partagée et doivent se partager une liste chaînée. Comment implémenteriez-vous cette liste simplement chaînée de façon à ce qu'elle puisse être utilisée dans cette mémoire partagée. On supposera que le segment de mémoire partagée est toujours plus grand que la zone mémoire nécessaire au stockage de la liste. - -#. Le livre [Kerrisk2010]_ contient de nombreux exemples de programmes permettant de manipuler les segments de mémoire partagée [#fex]_. Compilez les programmes ``svshm_create``, ``svshm_attach`` et ``svshm_rm`` pour créer, attacher et supprimer un segment de mémoire partagée. Les commandes `ipcs(1)`_ et `ipcrm(1)`_ permettent de visualiser et supprimer les segments de mémoire partagée. Pensez à utiliser ces commandes pour vérifier que vous n'avez pas laissé de segment de mémoire partagée qui traine. - - -.. rubric:: Footnotes - -.. [#fex] Voir notamment http://www.man7.org/tlpi/code/online/all_files_by_chapter.html (chapitre 48) ou http://www.man7.org/tlpi/code/index.html diff --git a/Exercices/Programmes/prog-2.rst b/Exercices/Programmes/prog-2.rst deleted file mode 100644 index 02b3dcf42efaf8f529896a6aea030da9e3572f33..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/prog-2.rst +++ /dev/null @@ -1,105 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - - -Questions INGINIOUS -------------------- - -#. Faites l'exercice relatif à `printf(3)`_ sur INGINIOUS : https://inginious.info.ucl.ac.be/course/LSINF1252/printf - -#. Un utilisateur peut adapter le comportement d'un programme via les arguments passés en ligne de commande. Ecrivez un programme permettant d'afficher un argument sur deux tel qu'indiqué sur INGINIOUS: https://inginious.info.ucl.ac.be/course/LSINF1252/main_argc - -#. L'an dernier, vous avez écrit un programme permettant de détecter si une chaîne de caractères était un palindrome. Faites de même en C avec l'exercice INGINIOUS https://inginious.info.ucl.ac.be/course/LSINF1252/palindrome - -#. Ecrivez le corps de la fonction `swap2 <https://inginious.info.ucl.ac.be/course/LSINF1252/swap2int>`_ permettant d'échanger les valeurs stockées dans deux variables de type entier. Faites de même lorsque les arguments de cette fonction sont des structures contenant des fractions : https://inginious.info.ucl.ac.be/course/LSINF1252/swap2int - -#. La libraire `string(3)`_ implémente un grand nombre de fonctions de manipulation des strings qui vous serons utile lors de différents projets de programmation. - - * `strlen(3)`_ - * `strcat(3)`_ - * `strcasecmp(3)`_ - - - Ecrivez le code implémentant ces trois fonctions. Pour cela, créez un fichier ``string.c`` contenant la définition des fonctions et un fichier ``string.h`` avec les `déclarations <http://en.wikipedia.org/wiki/Declaration_(computer_programming)>`_ des fonctions. Vous devez aussi fournir un Makefile (cfr :ref:`outils:make`) qui permet de recompiler facilement votre programme en tapant ``make``. Pensez à implémenter quelques tests pour vos fonctions dans la fonction ``main`` et n'incluez pas l'exécutable dans l'archive. Pour la réalisation de ces tests, utilisez une librairie de tests unitaires telle que `CUnit <http://cunit.sourceforge.net>`_ - - Lorsque vous considérez que votre programme est correct, testez son bon fonctionnement via l'exercice correspondant sur inginious : https://inginious.info.ucl.ac.be/course/LSINF1252/mini-projet-string - -#. Faites l'exercice `swap <https://inginious.info.ucl.ac.be/course/LSINF1252/swap>`_ sur INGInious - -#. Faites les exercices de manipulation de bits sur `INGInious <https://inginious.info.ucl.ac.be/course/LSINF1252>`_. Pour réaliser ces exercices, réfléchissez d'abord sur papier, par exemple sur des blocs de 4 ou 8 bits. Pour la plupart des questions, il faut combiner des décalages à gauche ou à droite avec des opérations ``AND`` (``&``), ``OR`` (``|``) et ``NOT`` (``~``) bit à bit. - - - https://inginious.info.ucl.ac.be/course/LSINF1252/bits_leftmost - - https://inginious.info.ucl.ac.be/course/LSINF1252/bits_rightmost - - https://inginious.info.ucl.ac.be/course/LSINF1252/set_bit - - https://inginious.info.ucl.ac.be/course/LSINF1252/bits_spin - - https://inginious.info.ucl.ac.be/course/LSINF1252/bits_sum - - https://inginious.info.ucl.ac.be/course/LSINF1252/bits_strong - - -Questions de discussion ------------------------ - -.. only:: staff - - #. La zone mémoire utilisée diffère d'un type primitif à un autre. Ecrivez un code qui permet d'afficher le nombre de bytes utilisés sur un système 64 bits (une machine des salles) et une machine 32 bits (sirius, voir section :ref:`outils:ssh`) pour représenter un ``int``, ``long``, ``void *``, ``char *``, ``size_t`` et ``uint64_t``. Expliquez les différences. - - .. important:: - - Il est nécessaire de recompiler le code source si vous voulez exécuter le binaire sur une autre architecture. Le type ``uint64_t`` est défini dans `stdint.h`_. - Sur sirius ``gcc`` n'est pas forcément disponible, il faut dans ce cas utiliser ``cc`` à la place - -.. only:: staff - - #. En utilisant des opérations binaires (décalage, and, or, ...), définissez un algorithme efficace pour trouver la valeur du bit le moins significatif d'un entier ``i`` (ex, 8 pour 56, 16 pour 208). - - .. note:: - - La plupart des étudiants vont probablement écrire un code similaire à : - - .. code-block:: c - - int c; - for ( c = 0 ; !((i >> c) & 1) ; c++ ) ; - printf("%d\n", 1 << c); - - Mais il existe plus efficace: - - .. code-block:: c - - printf("%d\n", i & (~i + 1)); - -#. Soit ``char *ptr = "Test"``. Itérez sur ce pointeur et affichez avec `printf(3)`_ la valeur et l'adresse mémoire où se trouve stocké chaque caractère de deux façons différentes. Regardez la manpage de `printf(3)`_ pour savoir comment afficher la valeur d'un pointeur. - -#. Lorsque l'on veut améliorer les performances d'un programme, il est utile de pouvoir mesurer précisément son temps d'exécution. La commande `time(1posix)`_ permet d'effectuer cette mesure depuis la ligne de commande. Parfois, on souhaite mesurer le temps de calcul une partie critique d'un code. Une façon simple pour obtenir cette mesure est d'utiliser `gettimeofday(2)`_ comme dans l'exemple ci-dessous (:download:`/Programmes/s2_perf.c`). - - .. literalinclude:: /Programmes/s2_perf.c - :encoding: utf-8 - :language: c - - Pour certaines opérations, les performances dépendent du type de données utilisé. Modifiez le programme ci-dessous de façon à utiliser un calcul plus compliqué que la simple addition et comparez sur de longues itérations (:math:`10^7` ou plus) les performances de cette opération lorsqu'elle utilise des ``int``, ``long long``, ``double`` ou ``float``. Les performances sont-elles identiques ? - - -Questions de bilan final ------------------------- - -#. La structure suivante ``foo_t`` est définie de façon à ce qu'elle contienne un ``char`` suivi d'un entier. D'après vous combien de bytes occupe cette structure en mémoire ? Vérifiez ce que vous pensiez en utilisant ``sizeof``. (bonus: expliquez vos résultats.) - - .. code-block:: c - - struct foo_t { - char a; - int b; - }; - - -#. Considérez le programme suivant. - - .. literalinclude:: /Programmes/s2_qbf.c - :encoding: utf-8 - :language: c - - * Sans executer le programme, essayez de comprendre son fonctionnement. En particulier, quelles seront les adresses affichées à chaque tour de boucle? - * Compilez le programme et exécutez le. Expliquez sa sortie et comparez avec vos attentes. - * (Bonus) Expliquez les valeurs affichées lors de l'exécution de la dernière boucle. diff --git a/Exercices/Programmes/prog-3.rst b/Exercices/Programmes/prog-3.rst deleted file mode 100644 index dabde89b4debfa43808acb360244aa1003418e01..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/prog-3.rst +++ /dev/null @@ -1,241 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Questions INGINIOUS -------------------- - -#. Le premier exercice INGINIOUS porte sur le heap et le stack : https://inginious.info.ucl.ac.be/course/LSINF1252/stack_vs_heap - -#. `malloc(3)`_ est une fonction clé en C puisqu'elle permet d'allouer une zone de mémoire. Elle a l'inconvénient de ne *pas* initialiser cette mémoire, contrairement à `calloc(3)`_. Lisez les pages de manuel de ces deux fonctions et implémentez vous-même la fonction `calloc(3)`_ en utilisant `malloc(3)`_ : https://inginious.info.ucl.ac.be/course/LSINF1252/calloc2 - -#. Lorsque l'on utilise les fonctions de la librairie ou les appels systèmes, il est *nécessaire* de vérifier chaque fois leur valeur de retour pour éviter tout problème. Dans cet exercice, vous écrivez une variante de `malloc(3)`_ qui essaye plusieurs fois d'allouer de la mémoire pour pallier à un problème temporaire de manque de mémoire : https://inginious.info.ucl.ac.be/course/LSINF1252/sleep_malloc - -#. La question suivante porte sur les déclarations de types de données (faites seulement les 7 premières sous-questions) : https://inginious.info.ucl.ac.be/course/LSINF1252/types - -#. `strcpy(3)`_ est une fonction de la librairie standard qui permet de copier une chaîne de caractères. Cet exercice vous propose d'écrire une variante de cette fonction : https://inginious.info.ucl.ac.be/course/LSINF1252/strcpy - -#. Lorsque l'on travaille avec les pointeurs, il est possible d'accéder à n'importe quel endroit de la mémoire. Cet exercice vous permet de tester vos compétences de manipulation des pointeurs: https://inginious.info.ucl.ac.be/course/LSINF1252/pointer_types - -#. Un exercice classique pour montrer que l'on comprend bien les pointeurs est de manipuler des listes chainées: https://inginious.info.ucl.ac.be/course/LSINF1252/basic_linked_list - -#. Un exercice sur le parcours simple d'un arbre binaire de recherche https://inginious.info.ucl.ac.be/course/LSINF1252/BST - -#. Un exercice où vous devez analyser l'information reçue d'un modem : https://inginious.info.ucl.ac.be/course/LSINF1252/modem_read - -#. Maintenant que vous avez écrit de nombreuses fonctions sur INGINIOUS, il est temps pour vous d'écrire votre premier programme directement en C. Utilisez un éditeur de texte pour écrire le fichier ``test.c`` qui implémente un sous-ensemble du programme standard `test(1)`_. Pensez à structurer votre code en utilisant des sous-fonctions. Compilez votre programme sur votre ordinateur avant de le soumettre sur INGINIOUS. https://inginious.info.ucl.ac.be/course/LSINF1252/commandetest - - - -Questions complémentaires -------------------------- - -#. En C, on peut définir des tableaux à deux dimensions avec une déclaration comme ``int a[3][3];``. Ecrivez un petit programme qui utilise des pointeurs pour déterminer si un tel tableau à deux dimensions est stocké ligne par ligne ou colonne par colonne. - - .. only:: staff - - .. note:: - - .. code-block:: c - - void main(void) { - int a[3][3]; - - if (&a[0][0] + 1 == &a[1][0]) - printf("Par ligne\n"); - else if (&a[0][0] + 1 == &a[0][1]) - printf("Par colonne\n"); - else - printf("WTF!!!\n"); - } - -#. Exécutez plusieurs fois le code suivant. Expliquez les différents résultats obtenus. - .. code-block:: c - - int global; - void main(void) - { - int local; - int *ptr1 = (int *)malloc(sizeof(*ptr1)); - int *ptr2 = (int *)malloc(sizeof(*ptr2)); - - printf("global %p loc %p p1 %p p2 %p\n", &global, &local, ptr1, ptr2); - } - - .. only:: staff - - .. note:: - - L'adresse de ``global`` ne change pas, car elle fait partie du segment texte du programme. Les autres sont soit sur la pile (stack), ou sur le tas (heap). - -#. Un étudiant a fait l'implémentation d'un sous-ensemble des fonctions définies dans string.h, mais il rencontre quelques problèmes avec son code :download:`/Programmes/src/string.c`. Utilisez `gdb <http://sites.uclouvain.be/SystInfo/notes/Outils/html/gdb.html>`_ pour corriger son code. Utilisez le flag ``-g`` de ``gcc`` pour ajouter les informations de debug dans votre executable. Pour rappel, voici quelques commandes importantes de `gdb <http://sites.uclouvain.be/SystInfo/notes/Outils/html/gdb.html>`_: - - - ``run [ARGS]`` permet de lancer l'execution du programme avec les arguments ARGS si spécifiés. - - ``break string.c:9`` met un point d'arrêt à la ligne 9 du fichier string.c - - ``next`` permet d'executer la ligne courante et de s'arrêter à la ligne suivante - - ``print var`` affiche la valeur de la variable ``var`` - - ``backtrace`` affiche la pile d'appel des fonctions courantes - - ``quit`` quitte `gdb <http://sites.uclouvain.be/SystInfo/notes/Outils/html/gdb.html>`_ - - .. only:: staff - - .. note:: - - 4 erreurs: strlen ne check pas NULL, strlen appelé à chaque itération de strcat, argc pas vérifié, concat_2 pas initialisé - -#. Vous travaillez sur un programme qui doit manipuler des vecteurs. Afin de pouvoir supporter des vecteurs de taille quelconque, vous décidez de réimplémenter ces vecteurs vous même en utilisant des pointeurs. Votre programme définit la structure ``struct vector_t`` et les fonctions ci-dessous. - Implémentez ces fonctions sans jamais utiliser la notation des tableaux en C (``[`` et ``]``). - - - .. literalinclude:: /Programmes/src/vector.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - - - .. only:: staff - - #. Faites l'exercice relatif aux `linked lists <https://inginious.info.ucl.ac.be/course/LSINF1252/linked_lists_1>`_ sur INGInious. - - - .. only:: staff - - #. Expliquez la différence entre `malloc(3)`_ et `calloc(3)`_. D'après vous, quel appel sera le plus lent ? - - .. only:: staff - - #. Dans la fonction ``push`` du programme de manipulation d'un pile :download:`/../Theorie/C/S3-src/stack.c`, faut-il remplacer l'appel à `malloc(3)`_ par un appel à `calloc(3)`_ - - .. note:: - - Non. La zone mémoire est initialisée directement après. - - .. only:: staff - - #. Le prototype de la fonction ``push`` du programme de manipulation d'une pile :download:`/../Theorie/C/S3-src/stack.c`, est ``void push(struct fraction_t *)``. Serait-il possible d'écrire une function push ayant comme prototype ``void push(struct fraction_t)`` ? Qu'est-ce qui changerait dans ce cas ? - - .. note:: - - Pas possible. - - .. only:: staff - - #. Les fonctions ``push`` et ``pop`` définies dans l'exemple de manipulation d'une pile :download:`/../Theorie/C/S3-src/stack.c` utilisent une pile qui est définie par un pointeur qui est une variable globale. Est-il possible de réécrire ces fonctions de façon à ce qu'elles prennent comme argument un pointeur vers la pile ? Leurs prototypes deviendraient : - - - ``void push(struct node_t *, struct fraction_t *);`` - - ``struct fraction_t * pop(struct node_t *);`` - - .. note:: - - Oui, idéalement dans ce cas, il faudrait définir une fonction init qui renverrait un ``struct node_t *``. - - .. only:: staff - - - #. Considérons la structure suivante: - - .. code-block:: c - - typedef struct { - char c; - long l; - short s; - } test_t; - - - Combien de bytes seront utilisés en mémoire pour représenter cette structure? Représentez graphiquement la position en mémoire de chaque élément (utilisez `printf(3)`_ et ``%p``), observez-vous des trous ? Expliquez. - Serait-il possible d'utiliser moins de bytes pour représenter cette structure ? Si oui, comment ? - - .. note:: - - La structure prend 16 bytes d'espace (sur une machine 64-bits - 12 bytes sur une machine 32 bits). C'est dû au fait que les champs sont alignés à des multiples de 64 bits (resp. 32 bits) pour éviter d'avoir des parties de variables copié sur plusieurs registres. Pour optimiser, il suffit de reordonner les champs. Par exemple: - - .. code-block:: c - - typedef struct { - char c; - short s; - long l; - } test_t; - - .. only:: staff - - .. note:: - - Elle bypasse l'alignement décrit dans la question précédente. L'avantage est que la structure prend l'espace minimale n'importe soit l'ordonnancement des champs. Le désavatage est que la CPU doît faire plus de travail pour lire la variable, car des parties de la variable sont sur plusieurs registres, et donc la CPU doît faire des bit-shifts. - -#. Expliquez à quoi sert l'attribut ``packed`` des structures dans `gcc(1)`_ (regardez la manpage). Appliquez cet attribut à la structure de l'exercice précédent. Qu'observez-vous comme différence ? Quel sont les avantages et désavantages d'utiliser cet attribut ? Dans quel cas est-il intéressant de l'utiliser ? - - .. only:: staff - - .. note:: - - Il bypasse l'alignement décrit dans la question précédente. L'avantage est que la structure prend l'espace minimal n'importe soit l'ordonnancement des champs. Le désavantage est que la CPU doît faire plus de travail pour lire la variable, car des parties de la variable sont sur plusieurs registres, et donc la CPU doît faire des bit-shifts. - - - .. only:: staff - - #. Exécutez plusieurs fois le code suivant. Expliquez les différents résultats obtenus. - .. code-block:: c - - int global; - int main (int argc, char** argv) - { - int local; - int *ptr1 = (int *)malloc(sizeof(*ptr1)); - int *ptr2 = (int *)malloc(sizeof(*ptr2)); - - printf("global %p loc %p p1 %p p2 %p\n", &global, &local, ptr1, ptr2); - return EXIT_SUCCESS; - } - - -Questions de bilan final ------------------------- - -#. Lisez attentivement le code suivant et essayez de deviner ce qui sera affiché - sur la sortie standard. Ensuite, compilez le code en activant l'option - ``-fno-stack-protector`` de `gcc(1)`_ et exécutez le code. Avez-vous bien - deviné ? Comment expliquez-vous les lignes affichées par le programme ? - - .. code-block:: c - - #include <stdlib.h> - #include <stdio.h> - #include <string.h> - #include <stdint.h> - - int f() { - uint32_t zero = 0; - char a = 'a'; - char b = 'b'; - char str[8] = "Hello !"; - printf("1) str = \"%s\",\t\tzero = %d,\ta = %c,\tb = %c\n", str, zero, a, b); - strcpy(str, "I love sour!"); - printf("2) str = \"%s\",\tzero = %d,\ta = %c,\tb = %c\n", str, zero, a, b); - a = 'a'; - b = 'b'; - printf("3) str = \"%s\",\tzero = %d,\ta = %c,\tb = %c\n", str, zero, a, b); - return 0; - } - - int main(int argc, char *argv[]) { - return f(); - } - -#. *Question ouverte*. Soit la structure ``pair_t`` suivante : - - .. code-block:: c - - typedef struct pair { - int a; - int b; - } pair_t; - - - Comment feriez-vous pour stocker dans les - variables ``pair_t *p1, *p2`` les pointeurs vers deux instances de ``pair_t`` - allouées sur le heap de manière contiguë (i.e. les deux structures se suivent - directement dans la mémoire) ? diff --git a/Exercices/Programmes/prog-4-asm.rst b/Exercices/Programmes/prog-4-asm.rst deleted file mode 100644 index b41356b38b87be80473cad456696b6a1285423dd..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/prog-4-asm.rst +++ /dev/null @@ -1,93 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Exercices -========= - -#. Dans le cours théorique, nous avons parlé des instructions ``set`` qui permettent de fixer la valeur d'un byte d'un registre en fonction de la valeur des drapeaux du registre ``eflags``. Comment feriez-vous pour compiler en assembleur la ligne ``b=(a>0)`` sans utilisez cette instruction et en sachant que les valeurs de ``a`` et ``b`` sont initialement dans les registres ``%eax`` et ``%ecx``. Pour répondre à cette question, écrivez d'abord un code en C semblable au code ci-dessous : - - .. code-block:: c - - if ( condition) - { b=1; } - else - { b=0; } - - -#. Avec le compilateur gcc, il est aussi possible de compiler du code assembleur directement dans une programme C. Cette fonctionnalité est intéressante si vous voulez tester de petites fonctions écrites en langage assembleur. Ainsi, une fonction baptisée ``rien`` et qui ne fait absolument rien peut s'écrire comme suit: - - - .. code-block:: c - - extern void rien(); // indique au compilateur que la fonction est externe - - __asm__( - "rien:\n" - " ret\n" - ); - - - En utilisant l'assembleur [IA32]_, écrivez les instructions assembleur qui permettent d'implémenter une fonction qui ne prend aucun argument et retourne toujours l'entier ``1``. - - .. only:: staff - - .. note:: - - .. code-block:: c - - movl $1,%eax - ret - - - De la même façon, écrivez la fonction ``add`` qui prend deux arguments de type ``int`` et retourne la somme de ces deux arguments. - - .. only:: staff - - .. note:: - - .. code-block:: c - - /* add(int a, int b) */ - __asm__( - "add:\n" - " subl $8, %esp\n" - " movl 16(%esp), %eax\n" - " movl 12(%esp), %ebx\n" - " movl %ebx, %eax\n" - " addl $8, %esp\n" - " ret\n" - ); - -#. Considérons une fraction de la mémoire représentée dans le tableau ci-dessous. - - ========== ======== - Adresse Valeur - ========== ======== - 0x0C 0x00 - 0x08 0xFF - 0x04 0x02 - 0x00 0x01 - ========== ======== - - Si ``%esp`` contient initialement la valeur ``0x0C`` et que ``%eax`` et ``%ebx`` contiennent respectivement ``0x02`` et ``0x03``, que deviennent cette mémoire et les registres durant l'exécution de : - - .. code-block:: nasm - - pushl %eax - pushl %ebx - popl %ecx - -#. En C, il n'est pas rare de voir dans certains programmes que la valeur de retour de certaines fonctions est ignorée. C'est une mauvaise pratique qui peut donner lieu à pas mal de problèmes. Connaissant la façon dont la valeur de retour d'une fonction ``int f()`` est gérée en assembleur, expliquez ce qu'il se passe en pratique lorsque la valeur de retour de ``f`` n'est pas sauvegardée. - - .. only:: staff - - .. note:: - - La valeur de retour étant dans %eax, il n'y a aucun problème à l'ignorer, elle sera juste écrasée à la première utilisation de %eax - - - - -#. Vous trouverez sur INGInious plusieurs exemples de questions typiques sur l'assembleur à l'examen. Ces questions portent sur la traduction d'un code assembleur dans son équivalent en C. `Première question <https://inginious.info.ucl.ac.be/course/LSINF1252/asm1>`_, `deuxième question <https://inginious.info.ucl.ac.be/course/LSINF1252/asm2>`_, `troisième question <https://inginious.info.ucl.ac.be/course/LSINF1252/asm3>`_ et `quatrième question <https://inginious.info.ucl.ac.be/course/LSINF1252/asm4>`_ . - diff --git a/Exercices/Programmes/prog-4.rst b/Exercices/Programmes/prog-4.rst deleted file mode 100644 index 62b829b89e4920ca12f08dc4d8b99abfecd779b9..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/prog-4.rst +++ /dev/null @@ -1,173 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Exercices INGINIOUS -=================== - -Deux sortes d'exercices INGINIOUS vous sont proposés durant cette semaine. Les premiers portent sur les structures chaînées car ces structures de données permettent de bien vérifier la compréhension des pointeurs en C. - - - https://inginious.info.ucl.ac.be/course/LSINF1252/simple_stack - - https://inginious.info.ucl.ac.be/course/LSINF1252/cmp_func - - https://inginious.info.ucl.ac.be/course/LSINF1252/linked_structs - - https://inginious.info.ucl.ac.be/course/LSINF1252/advanced_queue - - https://inginious.info.ucl.ac.be/course/LSINF1252/order_relation_linked_list - -Après avoir écrit de nombreuses fonctions C, il est maintenant temps pour vous de commencer à écrire des -programmes composés de plusieurs fonctions. Pour cela, l'utilitaire `make(1)`_ vous sera très utile. Prenez un peu de temps pour lire le chapitre qui lui est consacré dans le syllabus et essayez de répondre aux questions ci-dessous : - - - https://inginious.info.ucl.ac.be/course/LSINF1252/s2_make - - https://inginious.info.ucl.ac.be/course/LSINF1252/s2_make_calc - - https://inginious.info.ucl.ac.be/course/LSINF1252/s2_make_mcq - -.. only:: staff - - - https://inginious.info.ucl.ac.be/course/LSINF1252/s3_make - - https://inginious.info.ucl.ac.be/course/LSINF1252/s3_make_mcq - - https://inginious.info.ucl.ac.be/course/LSINF1252/s3_cunit_basics - - https://inginious.info.ucl.ac.be/course/LSINF1252/s3_make_tests - -Lorsque l'on écrit des programmes en C ou dans un autre langage, il est important de tester -le bon fonctionnement de toutes les fonctions du programme pour éviter des erreurs et autres -bugs difficiles à corriger. L'idéal est de commencer par écrire les tests qui valident le bon -fonctionnement de chaque fonction *avant* d'écrire cette fonction. Plusieurs librairies peuvent vous -aider à écrire de tels tests. CUnit (:ref:`outils:ref_cunit`) est l'un d'entre elles. -Prenez le temps de lire le chapitre -qui lui est consacré dans le syllabus. - -Pour démontrer votre bon utilisation de `make(1)`_ et CUnit, reprenez le programme que vous -avez écrit pour l'exercice `test <https://inginious.info.ucl.ac.be/course/LSINF1252/commandetest>`_ -, -divisez-le en plusieurs fichiers, ajoutez-y des tests unitaires pour chaque fonction et -utilisez `make(1)`_ pour automatiser le tout. Si vous voulez allez plus loin, essayez d'utiliser -la librarie `getopt(3)`_ pour traiter les arguments reçus en ligne de commande. - - -Exercices -========= - -#. Le principe de localité est un principe très important pour comprendre les performances de programmes qui accèdent beaucoup à la mémoire. Considérons tout d'abord un programme qui doit initialiser une grande zone mémoire obtenue via `malloc(3)`_. - - * Ecrivez en C une fonction d'initialisation de cette zone mémoire à la valeur ``1252`` qui profite de la localité spatiale - * Ecrivez en C une fonction d'initialisation de cette zone mémoire qui ne profite pas du tout de la localité spatiale - * Comparez les performances des deux programmes que vous avez écrit. Si nécessaire, désactivez l'optimisation du compilateur. - -#. Un programmeur doit manipuler des tableaux contenant 100.000.000 éléments. Chaque élément du tableau contient un nombre réel et une chaîne contenant 40 caractères. Une opération très courante à effectuer est de calculer la somme de tous les éléments du tableau. A votre avis, quelles seront les performances des deux implémentations suivantes de ce programme : - - * Le tableau est implémenté comme un tableau contenant 100.000.000 structures avec dans chaque structure un ``float`` et un ``char c[40]``. - * Le tableau est implémenté comme deux tableaux distincts. Le premier contient tous les ``float`` et le second toutes les chaînes de caractères. - -#. Un programmeur propose deux fonctions différentes pour calculer la somme des éléments d'un tableau à deux dimensions. Intégrez ces fonctions dans un programme afin d'en mesurer les performances avec `gettimeofday(2)`_. Quelle est la variante la plus rapide et pourquoi ? - - .. literalinclude:: src/sumarray.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -.. only:: staff - - #. Dans le cours théorique, nous avons parlé des instructions ``set`` qui permettent de fixer la valeur d'un byte d'un registre en fonction de la valeur des drapeaux du registre ``eflags``. Comment feriez-vous pour compiler en assembleur la ligne ``b=(a>0)`` sans utilisez cette instruction et en sachant que les valeurs de ``a`` et ``b`` sont initialement dans les registres ``%eax`` et ``%ecx``. Pour répondre à cette question, écrivez d'abord un code en C semblable au code ci-dessous : - - .. code-block:: c - - if ( condition) - { b=1; } - else - { b=0; } - - - #. Avec le compilateur gcc, il est aussi possible de compiler du code assembleur directement dans une programme C. Cette fonctionnalité est intéressante si vous voulez tester de petites fonctions écrites en langage assembleur. Ainsi, une fonction baptisée ``rien`` et qui ne fait absolument rien peut s'écrire comme suit: - - - .. code-block:: c - - extern void rien(); // indique au compilateur que la fonction est externe - - __asm__( - "rien:\n" - " ret\n" - ); - - - En utilisant l'assembleur [IA32]_, écrivez les instructions assembleur qui permettent d'implémenter une fonction qui ne prend aucun argument et retourne toujours l'entier ``1``. - - .. note:: - - .. code-block:: c - - movl $1,%eax - ret - - - De la même façon, écrivez la fonction ``add`` qui prend deux arguments de type ``int`` et retourne la somme de ces deux arguments. - - .. note:: - - .. code-block:: c - - /* add(int a, int b) */ - __asm__( - "add:\n" - " subl $8, %esp\n" - " movl 16(%esp), %eax\n" - " movl 12(%esp), %ebx\n" - " movl %ebx, %eax\n" - " addl $8, %esp\n" - " ret\n" - ); - - - #. Considérons une fraction de la mémoire représentée dans le tableau ci-dessous. - - ========== ======== - Adresse Valeur - ========== ======== - 0x0C 0x00 - 0x08 0xFF - 0x04 0x02 - 0x00 0x01 - ========== ======== - - Si ``%esp`` contient initialement la valeur ``0x0C`` et que ``%eax`` et ``%ebx`` contiennent respectivement ``0x02`` et ``0x03``, que deviennent cette mémoire et les registres durant l'exécution de : - - .. code-block:: nasm - - pushl %eax - pushl %ebx - popl %ecx - - #. En C, il n'est pas rare de voir dans certains programmes que la valeur de retour de certaines fonctions est ignorée. C'est une mauvaise pratique qui peut donner lieu à pas mal de problèmes. Connaissant la façon dont la valeur de retour d'une fonction ``int f()`` est gérée en assembleur, expliquez ce qu'il se passe en pratique lorsque la valeur de retour de ``f`` n'est pas sauvegardée. - - .. note:: - - La valeur de retour étant dans %eax, il n'y a aucun problème à l'ignorer, elle sera juste écrasée à la première utilisation de %eax - - - - #. Trois exercices se trouvent sur INGInious. Un exercice sur la `Comparaison de Fractions <https://inginious.info.ucl.ac.be/course/LSINF1252/fractions>`_, un nouvel exercice sur les `les listes chaînées <https://inginious.info.ucl.ac.be/course/LSINF1252/linked_lists_2>`_ et finalement l'implémentation de `strsep <https://inginious.info.ucl.ac.be/course/LSINF1252/strsep>`_. - - #. Vous trouverez également sur INGInious plusieurs exemples de questions typiques sur l'assembleur à l'examen. Ces questions portent sur la traduction d'un code assembleur dans son équivalent en C. `Première question <https://inginious.info.ucl.ac.be/course/LSINF1252/asm1>`_, `deuxième question <https://inginious.info.ucl.ac.be/course/LSINF1252/asm2>`_, `troisième question <https://inginious.info.ucl.ac.be/course/LSINF1252/asm3>`_ et `quatrième question <https://inginious.info.ucl.ac.be/course/LSINF1252/asm4>`_ . - - -Question de bilan final -======================= - -Considérez le programme suivant. - - .. literalinclude:: src/s4_qbf.c - :encoding: utf-8 - :language: c - -* Dessinez le schéma de l'organisation mémoire du programme. Identifiez dessus où se trouvent toutes les variables présentes dans le programme. -* Pour chaque ligne du programme, indiquez quelles zones mémoires sont accédées et leur contenu après exécution. - -.. only:: staff - - Cette question est importante à réaliser, n'hésitez pas à y passer une bonne demi-heure. Insistez pour commencer à dessiner le schema au tableau et que les étudiants interagissent directement dessus. - - Dans la section code: f, main. - Dans la section initialisée: cours et 97850 (insistez sur ce dernier!). - Dans la section heap: la zone mémoire pointée par tab. - Dans la stack (à des niveaux différents): d, tab, res, c, x. Notez que les arguments des fonctions sont aussi mis sur la stack (y compris a, b, argc et argv), mais insistez là -dessus lors de l'exécution du programme. - Dans la zone param/env: le contenu de argv. \ No newline at end of file diff --git a/Exercices/Programmes/prog-5.rst b/Exercices/Programmes/prog-5.rst deleted file mode 100644 index b6c8219cf66573115fd06e2eb179825ec51c28f5..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/prog-5.rst +++ /dev/null @@ -1,167 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Exercices INGINIOUS -------------------- - -Les exercices INGINIOUS de cette semaine ont comme objectif de vous familiariser avec -les appels systèmes `open(2)`_, `close(2)`_, `read(2)`_, `write(2)`_ et `stat(2)`_ qui -permettent de manipuler les fichiers contenant des données binaires. - -1. Le `premier exercice <https://inginious.info.ucl.ac.be/course/LSINF1252/s5_file_exists>`_ est -une mise en jambe. En utilisant `open(2)`_ (et `close(2)`_), pouvez-vous vérifier si un -fichier dont le nom est passé en argument existe ? - -2. L'avantage des fichiers binaires est qu'il est possible de sauvegarder directement un tableau stocké en mémoire dans le fichier en utilisant `write(2)`_ pour écrire chaque élément du tableau dans un fichier. En lisant les pages de manuel de `write(2)`_, vous verrez même qu'un seul appel à `write(2)`_ peut suffire à sauver tout un tableau dans un fichier. Ecrivez cette `fonction save <https://inginious.info.ucl.ac.be/course/LSINF1252/s4_file_save_struct>`_. - -3. Un fichier binaire peut être utilisé pour stocker tous les éléments d'un tableau d'entiers. Ecrivez la `fonction sum_file <https://inginious.info.ucl.ac.be/course/LSINF1252/s4_read_file_array_integer>`_ qui prend comme argument un nom de fichier contenant un tel tableau et calcule la somme de tous les entiers stockés dans le fichier. Pensez aux cas d'erreurs possibles si le fichier n'a pas la bonne taille. - -4. Vous continuez à explorer les fichiers binaires qui permettent de stocker tous les éléments d'un tableau d'entiers. Cette fois-ci vous devez écrire une `première fonction <https://inginious.info.ucl.ac.be/course/LSINF1252/s5_big_array_get_set>`_ pour récupérer la valeur d'un -élément du tableau stocké dans le fichier et une `seconde fonction <https://inginious.info.ucl.ac.be/course/LSINF1252/s5_big_array_get_set>`_ pour modifier la valeur d'un élément de ce tableau. - -5. En ligne de commande, `cp(1)`_ vous permet de copier complètement un fichier quel que soit son contenu. Pouvez-vous implémenter l'équivalent de cette commande dans la `fonction copy <https://inginious.info.ucl.ac.be/course/LSINF1252/s5_file_copy>`_ que vous allez écrire en C. - - - -Exercices ---------- - - -1. Consultez la page de manuel de `chmod(1)`_ ou d'autres sources pour déterminer la signification des bits de permissions lorsqu'ils sont associés à un répertoire. Expliquez notamment à quoi sert le bit d'exécution sur un répertoire. - - .. only:: staff - - le bit x permet d'autoriser le parcours du répertoire - -2. Quelles sont les permissions associées à votre répertoire de login ? Ces permissions permettent-elles à d'autres étudiants d'accéder à vos fichiers ? Si oui, utilisez `chmod(1)`_ pour supprimer cette autorisation de lecture par défaut dans votre répertoire. - -3. Comment feriez-vous en utilisant `chmod(1)`_ pour créer un répertoire dans lequel vous pouvez lire et écrire, tout étudiant peut lire mais aucun membre du staff (à part l'administrateur système bien entendu) ne peut lire ? - - .. only:: staff - - il faut que l'étudiant soit dans le même groupe et que le répertoire soit accessible au groupe, au minimum 00750 - -4. Le répertoire ``/tmp`` est particulier car il est destiné à pouvoir contenir des fichiers de n'importe quel utilisateur. Pouvez-vous expliquer les permissions utilisées pour ce répertoire ? - - .. only:: staff - - pas besoin de parler du sticky bit sauf si les étudiants l'abordent - -.. only:: staff - - 5. La commande `lsof(8)`_ permet de lister les fichiers ouverts par un processus. A votre avis, comment cette commande fonctionne-t-elle ? - - L'OS maintient une table de tous les fichiers ouverts avec leur inode. Cette table est accessible via /proc - - 6. Lorsqu'un exécutable est lancé avec `execve(2)`_, il hérite des descripteurs de fichiers qui étaient ouverts dans le processus qui a exécuté `execve(2)`_. Comment feriez-vous en utilisant uniquement l'appel système `open(2)`_ pour déterminer combien de descripteurs de fichiers étaient ouverts au démarrage de votre programme ? - - Il suffit de regarder quelle est la valeur de retour de open. Si open retourne 3, cela indique que seuls stdin, stdout et stderr étaient ouverts - -5. Est-il possible dans un processus d'exécuter ``int fd1=open("f",O_RDWR);`` et juste après ``int fd2=open("f",O_RDONLY);`` ? Si oui, quelles seront les valeurs des descripteurs de fichiers retournés lors des appels système. Si non, quelles seront les valeurs de ``errno``? - - .. only:: staff - - Oui, c'est possible. Dans ce cas, les offset pointers sont différents pour les deux copies du même fichier. Il est utile de faire un dessin pour que les étudiants visualisent bien la situation - -.. only:: staff - - 8. Dans un shell, on exécute la commande ``/bin/echo "1234" > /test.txt``. Quels sont les appels systèmes effectués par le shell avant l'exécution de ``/bin/echo`` ? - - - - fork, fermer stdout, ouvrir test.txt - par défaut il aura le premier fd libre, c-a-d celui de stdout qui vient d'être fermé et ensuite exécution avec execve - - 9. Dans un shell, on exécute la commande ``./a.out < in.txt > out.txt``. Quelles sont les appels systèmes qui doivent être exécutés par le shell pour lancer cet exécutable comme demandé par l'utilisateur ? - - - fork puis dans le fils - close(stdin) - open(in.txt,O_RDONLY) - close(stdout) - open(out.txt,O_WRONLY) - execve (qui préserver les descripteurs ouverts) - - 10. Dans un shell, on exécute la commande ``cat < in.txt | grep sinf1252``. Quelles sont les appels systèmes qui doivent être exécutés par le shell pour lancer cette commande comme demandé par l'utilisateur ? - - deux forks - premier fils - close(stdin) - close(stdout) - - 11. Dans un shel `bash(1)`_, lorsque l'on suffixe une commande avec ``2>&1``, le shell redirige la sortie d'erreur standard vers la sortie standard. Quels sont les appels systèmes utilisés par le shell pour réussir cette redirection ? - - le shell va faire fork pour exécuter le programme, mais avant il doit fermer stdout et le dupliquer avec dup ou dup2 - - -6. Comment se comporte l'appel système `write(2)`_ lorsque le disque sur lequel on souhaite écrire des données est plein ? Peut-on distinguer cette erreur d'un problème d'écriture sur le disque ? - - .. only:: staff - - il retourne une erreur et met errno à ENOSPC - -7. A quoi sert l'appel système `sync(2)`_ ? - - .. only:: staff - - A forcer l'écriture des données sur le disque - -8. Le programme :download:`/Programmes/src/writeperf.c` permet de tester les performances des écritures dans write sur un système de fichiers. Compilez-le et exécutez le avec différents tailles de buffers passés à `write(2)`_. Mesurez le temps d'exécution avec la commande `time(1posix)`_ et comparez le temps qu'il faut pour écrire 100MB en blocs de 1 MB ou en blocs de 1 KB. Faites de même en activant la synchronisation avec le paramètre ``-s``. - - .. only:: staff - - Les performances décroissent car il y a plus d'appels systèmes qui sont effectués. sync force l'écriture et bypasse le buffer. Il est utile de mentionner l'existence de ce buffer - -.. only:: staff - - 15. Effectuez l'exercice sur la manipulation de fichiers sur `INGInious <https://inginious.info.ucl.ac.be/course/LSINF1252/fichiers>`_. - -.. 17. `tee(1)`_ est un utilitaire qui permet de recopier son entrée standard vers un ou plusieurs fichiers et également vers sa sortie standard. Il peut être utile pour par exemple inspecter des données échangées entre deux processus à travers un :term:`pipe`. Quels sont les appels systèmes exécutés par `tee(1)`_ lors de l'exécution de la commande ``cat /tmp/t | tee /tmp/tee.out | grep "sinf1252" `` - - -Questions de bilan final ------------------------- - -Un système informatique est utilisé par 3 utilisateurs: ``quentin``, ``brigitte`` and ``françois``. Ils appartiennent à des groupes différents comme décrit ci-dessous. - -.. code-block:: bash - - $ groups quentin - quentin : quentin boys - - $ groups brigitte - brigitte: brigitte girls sudo wheel - - $ groups françois - françois: françois boys - -#. ``quentin`` ouvre le fichier ``/shared_folder/petit_projet.c`` en utilisant les drapeaux ``O_CREAT | O_RDWR | O_TRUNC``, donne les permissions ``664``, l'associe au groupe ``boys`` et écrit le code de son projet dedans. - - #. Quelles sont les permissions que doit avoir ``/shared_folder`` pour que ``françois`` et ``brigitte`` puissent accéder au fichier ``petit_projet.c``? - - - #. ``brigitte``, de son côté, lance ensuite les commandes suivantes. - - .. code-block:: bash - - $ sudo chown brigitte:girls /shared_folder/petit_projet.c - $ chmod 660 /shared_folder/petit_projet.c - - ``quentin`` veut maintenant sauvegarder son travail avec l'appel système ``write(2)`` sur le file descriptor obtenu avec le ``open(2)`` précédent, et puis le ferme avec ``close(2)``. Que se passe-t-il? - - #. ``françois`` aimerait aussi rajouter son nom sur le projet et ouvre le fichier avec ``open(2)`` avec le drapeau ``O_WRONLY`` pour ensuite utiliser ``write(2)``. Que se passe-t-il? - - #. Finalement, ``quentin`` souhaite relire son code et fait appel à ``open(2)`` avec le drapeau ``O_RDONLY``, pour ensuite utiliser ``read(2)``. Que se passe-t-il? - - -#. Considérons le fichier ``/shared_folder/music.mp3`` avec les permissions ``644`` possédé par ``françois`` et associé au groupe ``boys``. - - #. Est-ce que ``quentin`` peut écouter le morceau? Qu'en est-il pour ``brigitte``? Quelles sont les permissions requises pour ``/shared_folder`` afin qu'ils y accèdent? - - #. Supposons maintenant que ``quentin`` et ``brigitte`` sont en train d'écouter le morceau MP3. Observant qu'il ne lui reste que peu d'espace disque disponible, ``françois`` supprime le fichier ``/shared_folder/music.mp3`` avec la commande ``rm``. - - #. Que se passe-t-il pour ``brigitte`` et ``quentin``? - - #. ``quentin`` ferme ensuite le fichier avec ``close(2)``. Qui a encore accès au fichier? - - #. ``brigitte`` ferme à son tour son file descriptor. Qui a encore accès au fichier? \ No newline at end of file diff --git a/Exercices/Programmes/prog-6.rst b/Exercices/Programmes/prog-6.rst deleted file mode 100644 index 56fa13a237beb1eefdf901241474539c59bfad0c..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/prog-6.rst +++ /dev/null @@ -1,196 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -Exercices -========= - -#. La fonction `pthread_join(3)`_ utilise un deuxième argument de type ``void **``. Pourquoi est-il nécessaire d'utiliser un pointeur vers un pointeur et pas simplement un pointeur ``void *`` ? - -#. A votre avis, pourquoi le premier argument de la fonction `pthread_create(3)`_ est-il un pointeur de type `pthread_t *` alors que le premier argument de la fonction `pthread_join(3)`_ est lui simplement de type `pthread_t`? - -#. Avec les threads POSIX, comment peut-on passer plusieurs arguments à la fonction démarrée par `pthread_create(3)`_ ? Ecrivez un petit exemple en C qui permet de passer un entier et un caractère à cette fonction. - -.. only:: staff - - Ecrivez un code qui permet de récupérer un tableau d'entiers d'un thread. Exercice disponible sur `INGInious threads_1 <https://inginious.info.ucl.ac.be/course/LSINF1252-new/threads_1>`_. - -#. Essayez de lancer un grand nombre de threads d'exécution sur votre machine. Quel est le nombre maximum de threads que `pthread_create(3)`_ vous autorise à lancer ? - -#. Quelle différence voyez-vous entre `pthread_exit(3)`_ et `exit(3)`_ ? - -#. Un étudiant souhaite passer un tableau d'entiers comme argument à un thread et écrit le code suivant. Qu'en pensez-vous ? - - .. literalinclude:: /Programmes/src/pthread-array.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - -#. Considérons le programme de test des threads POSIX ci-dessous. Ce programme utilise 4 threads qui incrémentent chacun un million de fois une variable globale. - - .. literalinclude:: /Programmes/src/pthread-test.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - - Exécutez ce programme (:download:`/Programmes/src/pthread-test.c`) et observez le résultat qu'il affiche à l'écran. Pouvez-vous expliquer le comportement de ce programme ? - -#. Lorsque l'on travaille avec des threads, il est important de bien se rappeler dans quelle zone de la mémoire les différents types d'information sont stockés dans un programme C. Le programme ci-dessous fournit quelques exemples de : - - * variable globale statique - * variable globale - * variable déclarée dans la fonction ``main`` et dont le pointeur est un des arguments aux threads - * variable statique déclarée à l'intérieur d'une fonction - * variable locale déclarée dans une fonction - - - .. code-block:: c - - #include <pthread.h> - #include <stdio.h> - #include <stdlib.h> - - #define N_THREADS 3 - - struct thread_args { - int *ptr; - int thread_num; - }; - - pthread_mutex_t mutex; - - static int global_static = 1; - int global_int = 11; - - static void *thread_work(void *ptr) - { - struct thread_args *arg = (struct thread_args *)ptr; - int thr_num = arg->thread_num; - - static int static_val = 111; - int local_val = 222; - int *main_val = arg->ptr; - - pthread_mutex_lock(&mutex); - - printf("thread no %d, global_static is %d\n", thr_num, global_static); - fflush(stdout); - global_static++; - - printf("thread no %d, global_int is %d\n", thr_num, global_int); - fflush(stdout); - global_int++; - - printf("thread no %d, static_val is %d\n", thr_num, static_val); - fflush(stdout); - static_val++; - - printf("thread no %d, local_val is %d\n", thr_num, local_val); - fflush(stdout); - local_val++; - - printf("thread no %d, main_val is %d\n", thr_num, *main_val); - fflush(stdout); - (*main_val)++; - - pthread_mutex_unlock(&mutex); - - pthread_exit(NULL); - } - - int main (int argc, char const *argv[]) - { - int i; - int val = 22; - struct thread_args args[N_THREADS]; - pthread_t threads[N_THREADS]; - - pthread_mutex_init(&mutex, NULL); - - for (i = 0; i < N_THREADS; ++i) { - args[i].ptr = &val; - args[i].thread_num = i; - pthread_create(&threads[i], NULL, thread_work, (void *)&args[i]); - } - - for (i = 0; i < N_THREADS; ++i) - pthread_join(threads[i], NULL); - - return 0; - } - -#. D'après vous (essayez d'expérimenter), que se passe-t-il si: - - * un thread exécute deux fois `pthread_mutex_lock(3posix)`_ sur le même mutex d'affilée ? - * un thread exécute deux fois d'affilée `pthread_mutex_unlock(3posix)`_ - - -#. Dans la partie théorie, nous avons vu comment s'assurer qu'un seul thread peut accéder à une zone critique à la fois. On vous propose deux solutions (dont une déjà vue dans la partie théorie): - - .. code-block:: c - - pthread_mutex_lock(&mutex_global); - global=increment(global); - pthread_mutex_unlock(&mutex_global); - - et - - .. code-block:: c - - while (pthread_mutex_trylock(&mutex_global)) ; - global=increment(global); - pthread_mutex_unlock(&mutex_global); - - Discuter les avantages et inconvénients des ces deux solutions. (Regardez la man page de `pthread_mutex_trylock(3posix)`_) - -#. L'outil ``helgrind`` (décrit dans la section :ref:`outils:helgrind-ref`) permet de trouver des deadlocks ou autres problèmes. Exécutez-le sur le petit programme suivant :download:`/Programmes/src/pthread-philo.c` et analysez ce qu'il affiche. - - - -.. only:: staff - - Résolvez des sudokus. Exercice disponible sur `INGInious sudoku <https://inginious.info.ucl.ac.be/course/LSINF1252-new/sudoku>`_. - -Mini-projet: Mesure de performance -================================== - -On vous demande de transformer un code monothreadé en un code multithreadé. Vous devez vous baser sur le code présent dans l'archive: :download:`/Programmes/src/prog-5-measure/prog-5-measure.tar.gz`. Le programme permet de chiffrer ou déchiffrer des mots de passe passés en argument au programme. Ce dernier prend plusieurs arguments additionels: - - * ``-p`` définit le mot de passe à utiliser - * ``-n`` définit le nombre de fois que chaque mot de passe est chiffré/déchiffré - * ``-d`` définit que le programme doit déchiffrer les mots de passes (il chiffre par défaut) - -Un exemple d'utilisation du programme est le suivant: - - .. code-block:: console - - $ ./crypt -p toto -n 10000 test Bonjour! - CAC7EF483F90C988 0F5766990DFA0914 - $ ./crypt -p toto -n 10000 -d CAC7EF483F90C988 0F5766990DFA0914 - test Bonjour! - -Vous devez donc vous baser sur le code existant afin de paralléliser le chiffrement/déchiffrement des mots de passe. Vous ne devez pas nécessairement afficher les mots de passe (ou chiffrés) dans l'ordre. Vous devez cependant ajouter un argument ``-t`` au programme qui définit le nombre de threads que le programme exécutera en parallèle. - -On vous demande également d'évaluer l'impact des arguments ``-t`` et ``-n`` sur l'exécution du programme. Pensez à exécuter votre programme avec un argument ``-n`` suffisamment grand si vous voulez évaluer l'impact de ``-t``. On vous demande plus spécifiquement de générer un graphique qui montre pour différentes valeurs le temps de calcul. Vous pouvez utiliser `time(1posix)`_ afin de récupérer le temps d'exécution d'un programme: - - .. code-block:: console - - $ time ./crypt -p toto -n 10000 -d CAC7EF483F90C988 0F5766990DFA0914 - test Bonjour! - - real 0m0.019s - user 0m0.016s - sys 0m0.000s - $ time ./crypt -p toto -n 9999999 -d 774069EB86ED86FA 7D1AC0A4CF56F942 - test Bonjour! - - real 0m16.104s - user 0m16.101s - sys 0m0.000s - - - -.. exemple et tutoriel intéressant -.. https://computing.llnl.gov/tutorials/pthreads/ - diff --git a/Exercices/Programmes/prog-7.rst b/Exercices/Programmes/prog-7.rst deleted file mode 100644 index adcdfdec23f4b9b0ace15ded4bfdec31d8800422..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/prog-7.rst +++ /dev/null @@ -1,120 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -Exercices -========= - - -#. Expliquez pourquoi la fonction `sem_wait(3)`_ doit prendre comme argument ``sem_t *``, un - pointeur vers une structure ``sem_t``, et non une structure ``sem_t``. - - .. only:: staff - - Parceque la valeur du sémaphore doit être modifiée par la fonction ou la queue associée au sémaphore - - -#. Dans quels cas la fonction `sem_init(3)`_ risque-t-elle de retourner une erreur ? - - .. only:: staff - - valeur initiale trop grande - - -#. La librairie POSIX contient également une fonction `sem_timedwait(3)`_. Quel intérêt voyez-vous à cette fonction ? Dans quel cas pourrait-elle servir en pratique ? - - .. only:: staff - - en pratique cela permet d'éviter de rester bloqué longtemps, mais cela ne remplace pas une solution correcte qui évite les deadlocks. A priori, ce n'est pas une fonction à utiliser dans le code qu'ils rendent. - - -#. Un étudiant propose d'implémenter le producteur du problème des producteurs-consommateurs comme ci-dessous : - - .. code-block:: c - - // Producteur - void producer(void) - { - int item; - while(true) - { - item=produce(item); - pthread_mutex_lock(&mutex); // modification - sem_wait(&empty); // modification - insert_item(); - pthread_mutex_unlock(&mutex); - sem_post(&full); - } - } - - Que pensez-vous de cette solution (en supposant que le consommateur continue à fonctionner comme indiqué dans les notes) ? - - .. only:: staff - - On a inversé les locks dans le producteur. Cela peut causer un deadlock puisque le producteur ayant pris mutex, si empty est bloquant, ce qui est le cas lorsque le buffer est vide, le producteur empêchera tout consommateur d'accéder au buffer et donc le système sera en deadlock - -#. Un étudiant propose d'implémenter le consommateur du problème des producteurs-consommateurs comme ci-dessous : - - .. code-block:: c - - // Consommateur - void consumer(void) - { - int item; - while(true) - { - sem_wait(&full); - pthread_mutex_lock(&mutex); - item=remove(item); - sem_post(&empty); // modification - pthread_mutex_unlock(&mutex); // modification - } - } - - Que pensez-vous de sa solution (en supposant que le producteur n'a pas été modifié) ? - - .. only:: staff - - L'ordre des unlock a changé. Ici, cela n'a pas d'impact sur la solution. - -#. Un étudiant propose de résoudre le problème du rendez-vous en utilisant le code ci-dessous. Comparez sa solution avec la solution qui a été vue au cours. - - .. code-block:: c - - premiere_phase(); - - pthread_mutex_lock(&mutex); - count++; - pthread_mutex_unlock(&mutex); // modification - if(count==N) - sem_post(&rendezvous); - - sem_wait(&rendezvous); - sem_post(&rendezvous); - - seconde_phase(); - - .. only:: staff - - Cela fonctionne aussi, voir [Downey2008]_. En gros, même si on place le test de ``count`` en dehors du mutex, ce n'est pas grave parce que lorsque count vaut N, il ne peut plus y avoir de thread qui soit en train de manipuler la variable count puisque tous les autres threads sont par définition bloqués. Le seul risque serait count=N-1, un thread fait unlock et est interrompu, le suivant rentre dans la section critique et increment count. Si le premier redémarre a ce moment, il verra que count==N et fera sem_post, ce que le dernier thread fera aussi. On aura donc un sem_post de trop, mais tous les threads auront atteints le rendez-vous - - -#. Considérons un problème du rendez-vous avec 13 threads. Lorsque tous les threads ont passé le rendez-vous, quelle sera la valeur du sémaphore ``rendezvous`` retournée par la fonction `sem_getvalue(3)`_ ? - - .. only:: staff - - 1 puisque tous les threads ont fait wait puis post alors que le dernier a fait post avant de faire son wait - -#. La librairie POSIX contient la fonction `sem_getvalue(3)`_ qui permet de récupérer la valeur d'un sémaphore sans pour autant effectuer d'opération `sem_wait(3)`_ sur ce sémaphore. Elle peut être utilisée pour observer l'évolution de la valeur d'un sémaphore. Modifiez le programme des philosophes contenant un deadlock (:download:`/Programmes/src/pthread-philo-sem.c`) et ajoutez-y un thread qui observe toutes les 10 secondes l'évolution des sémaphores et arrête tout le programme via `exit(3)`_ en affichant un message d'erreur si les valeurs des sémaphores n'ont pas changé. - -#. Les mutex et les sémaphores peuvent être utilisés pour résoudre des problèmes d'exclusion mutuelle. Le programme :download:`/QCM/S7/src/pthread-mutex-perf.c` utilise des mutex. Modifiez-le pour utiliser des sémaphores à la place et comparez le coût en termes de performance entre les mutex et les sémaphores. - -#. Faites l'exercice sur les `producteurs/consommateurs <https://inginious.info.ucl.ac.be/course/LSINF1252/PC>`_ sur `INGInious <https://inginious.info.ucl.ac.be>`_. - -Outils -====== - -#. Si vous ne l'aviez pas fait durant la troisième semaine, prenez le temps pour faire l'exercice relatif à `gdb(1)`_ . Le debugger pourra vous être très utile pour le projet. - -#. Un autre outil particulièrement intéressant est :ref:`outils:valgrind-ref` qui permet de détecter différents problèmes d'allocation de la mémoire. Prenez le temps nécessaire pour comprendre comment ce logiciel fonctionne, cette compétence vous fera gagner du temps plus tard et vous évitera de perdre du temps pour corriger un problème d'allocation de mémoire difficile à détecter. \ No newline at end of file diff --git a/Exercices/Programmes/prog-8.rst b/Exercices/Programmes/prog-8.rst deleted file mode 100644 index 92d010e275f4759516787fc4e2205e25db8e16ae..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/prog-8.rst +++ /dev/null @@ -1,79 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Exercices -========= - -1. Dans quels cas l'appel système `fork(2)`_ peut-il retourner une erreur? Pourriez-vous construire un programme dans lequel `fork(2)`_ retourne une erreur ? - - .. only:: staff - - Il suffit de créer trop de processus - -2. Dans quels cas l'appel système `wait(2)`_ peut-il retourner une erreur ? Pourriez-vous écrire un petit programme dans lequel `wait(2)`_ retourne une erreur ? - - .. only:: staff - - Voir page de manuel. Un exemple est lorsqu'il n'y a plus de processus fils - -3. L'appel système `fork(2)`_ retourne l'identifiant du processus fils dans le processus père. Imaginez qu'une variante de Unix choisisse d'implémenter `fork(2)`_ en retournant ``0`` dans le processus fils et ``1`` dans le processus père. Quel serait l'impact de cette modification pour un programme qui lance plusieurs processus fils ? - - .. only:: staff - - `waitpid(2)`_ ne pourrait plus fonctionner - -4. Combien de processus sont créés lors de l'exécution du programme ci-dessous ? - - .. code-block:: c - - // ... - fork(); - fork(); - // ... - - .. only:: staff - - le père crée un fils puis un second - - le premier fils crée également un fils - -5. En supposant que le processus père a comme identifiant la valeur ``1252``, représentez graphiquement sous forme d'un arbre l'ensemble des processus créés par le programme ci-dessus en supposant que les identifiants de processus sont attribués séquentiellement par le :term:`kernel`. - -6. L'appel système `fork(2)`_ est nécessaire au fonctionnement de Unix. Cependant, un programme qui abuse de `fork(2)`_ risque de perturber le fonctionnement du système. Que risque-t-il d'arriver si vous exécutez un programme qui par mégarde contient : - -.. code-block:: c - - while(true) { - fork(); - // ... - } - -Consultez les pages de manuel pour déterminer comment le système d'exploitation peut se protéger contre de telles `fork bomb <http://en.wikipedia.org/wiki/Fork_bomb>`_. - -7. Comparez les performances de la création et la terminaison de threads et de processus en compilant et exécutant sur un ordinateur non chargé les programmes :download:`/Programmes/src/fork-perf.c` et :download:`/Programmes/src/pthread-perf.c`. Utilisez la commande `time(1posix)`_ pour mesurer le temps d'exécution de chacun des ces programmes qui créent 100000 processus ou threads. Expliquez vos résultats. - - .. only:: staff - - Essayez de discuter avec les étudiants des avantages et inconvénients des threads et des processus pour voir dans quels cas un processus est plus utile qu'un thread. A ce stade, ils n'ont vu aucun mécanisme de partage entre processus et ils n'ont pas encore vu les fichiers. Le seul avantage des processus est que si le père crashe son fils ne crashe pas nécessairement, alors que dans les threads un crash provoque le crash de tous les threads du processus. - -8. Compilez le programme :download:`/Programmes/src/fork-zombie.c`. Ce programme crée un processus mais le processus père attend une minute pour récupérer sa valeur de retour. Lancez ce programme en tâche de fond (voir section outils) et utilisez `ps(1)`_ ou consultez ``/proc/`` - -9. La librairie standard comprend une fonction `system(3posix)`_ qui permet l'exécution d'une commande du shell. Ainsi, la ligne ``system("for f in {1..3} ; do echo $f ; done")`` va provoquer un appel au shell `bash(1)`_ qui va exécuter la commande passé en argument et donc afficher trois lignes contenant chacune un nombre sur la sortie standard. Quels sont les appels systèmes utilisées par une implémentation de cette fonction `system(3posix)`_ ? - -10. Quelles différences et similitudes voyez-vous entre : - - - `pthread_create(3)`_ et `fork(2)`_ - - `pthread_join(3)`_ et `waitpid(2)`_ - - -11. La commande `strace(1)`_ permet de tracer tous les appels systèmes faits par un programme. Recompilez un programme d'exemple et essayer d'identifier les principaux appels systèmes qui sont utilisés par ce programme. Les paramètres ``-c``, ``-t`` et ``-e`` peuvent être utiles pour explorer le comportement d'un programme et avoir une idée des appels systèmes qu'il effectue. - -12. La commande `pstree(1)`_ permet de visualiser sous forme d'arbre l'ensemble des processus actifs sur un ordinateur Linux. Exécutez `pstree(1)`_ et identifiez quels sont les processus qui sont les ancêtres de votre commande. - -13. Un shell tel que `bash(1)`_ permet à l'utilisateur de lancer plusieurs programmes simultanément. Par exemple, il est possible de lancer un programme en background (ou tâche de fond en français) en le suffixant avec le caractère ``&``. On peut faire de même en tapant `Ctrl-Z` (les touches `Ctrl` et `Z` simultanément) pendant qu'un programme s'exécute. Cela peut être utile pour taper une commande pour par exemple voir l'état du système pendant l'exécution du programme. Il est possible de revenir à l'exécution du programme via la commande `fg(1)`. La commande `jobs(1posix)`_ permet de lister les processus qui sont actuellement exécutés par le shell en tâche de fond. La section `JOB CONTROL` du manuel de `bash(1)`_ fournit plus d'informations à ce sujet. - -14. Le répertoire ``/proc`` contient une image de la table des processus maintenue par le :term:`kernel` et d'autres structures de données maintenues par le :term:`kernel`. Compilez le programme :download:`/Programmes/src/fork-pthread.c` qui lance un processus fils puis crée un thread à l'intérieur du processus père. Lancez ce programme en background via `bash(1)`_ et observez les entrées relatives au père, au fils et au thread créé par le processus père dans ``/proc``. - -15. Faites l'exercice sur les shell sur `IngiNIOUS <https://inginious.info.ucl.ac.be/course/LSINF1252/shell>`_ - diff --git a/Exercices/Programmes/prog-9.rst.old b/Exercices/Programmes/prog-9.rst.old deleted file mode 100644 index e89cae0e619e81b1fa423e4fe8ad91378c4c7852..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/prog-9.rst.old +++ /dev/null @@ -1,105 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Exercices ---------- - - -1. Consultez la page de manuel de `chmod(1)`_ ou d'autres sources pour déterminer la signification des bits de permissions lorsqu'ils sont associés à un répertoire. Expliquez notamment à quoi sert le bit d'exécution sur un répertoire. - - .. only:: staff - - le bit x permet d'autoriser le parcours du répertoire - -2. Quelles sont les permissions associées à votre répertoire de login ? Ces permissions permettent-elles à d'autres étudiants d'accéder à vos fichiers ? Si oui, utilisez `chmod(1)`_ pour supprimer cette autorisation de lecture par défaut dans votre répertoire. - -3. Comment feriez-vous en utilisant `chmod(1)`_ pour créer un répertoire dans lequel vous pouvez lire et écrire, tout étudiant peut lire mais aucun membre du staff (à part l'administrateur système bien entendu) ne peut lire ? - - .. only:: staff - - il faut que l'étudiant soit dans le même groupe et que le répertoire soit accessible au groupe, au minimum 00750 - -4. Le répertoire ``/tmp`` est particulier car il est destiné à pouvoir contenir des fichiers de n'importe quel utilisateur. Pouvez-vous expliquer les permissions utilisées pour ce répertoire ? - - .. only:: staff - - pas besoin de parler du sticky bit sauf si les étudiants l'abordent - -5. La commande `lsof(8)`_ permet de lister les fichiers ouverts par un processus. A votre avis, comment cette commande fonctionne-t-elle ? - - .. only:: staff - - L'OS maintient une table de tous les fichiers ouverts avec leur inode. Cette table est accessible via /proc - -6. Lorsqu'un exécutable est lancé avec `execve(2)`_, il hérite des descripteurs de fichiers qui étaient ouverts dans le processus qui a exécuté `execve(2)`_. Comment feriez-vous en utilisant uniquement l'appel système `open(2)`_ pour déterminer combien de descripteurs de fichiers étaient ouverts au démarrage de votre programme ? - - .. only:: staff - - Il suffit de regarder quelle est la valeur de retour de open. Si open retourne 3, cela indique que seuls stdin, stdout et stderr étaient ouverts - -7. Est-il possible dans un processus d'exécuter ``int fd1=open("f",O_RDWR);`` et juste après ``int fd2=open("f",O_RDONLY);`` ? Si oui, quelles seront les valeurs des descripteurs de fichiers retournés lors des appels système. Si non, quelles seront les valeurs de ``errno``? - - .. only:: staff - - Oui, c'est possible. Dans ce cas, les offset pointers sont différents pour les deux copies du même fichier. Il est utile de faire un dessin pour que les étudiants visualisent bien la situation - -8. Dans un shell, on exécute la commande ``/bin/echo "1234" > /test.txt``. Quels sont les appels systèmes effectués par le shell avant l'exécution de ``/bin/echo`` ? - - .. only:: staff - - fork, fermer stdout, ouvrir test.txt - par défaut il aura le premier fd libre, c-a-d celui de stdout qui vient d'être fermé et ensuite exécution avec execve - -9. Dans un shell, on exécute la commande ``./a.out < in.txt > out.txt``. Quelles sont les appels systèmes qui doivent être exécutés par le shell pour lancer cet exécutable comme demandé par l'utilisateur ? - - .. only:: staff - - fork puis dans le fils - close(stdin) - open(in.txt,O_RDONLY) - close(stdout) - open(out.txt,O_WRONLY) - execve (qui préserver les descripteurs ouverts) - -10. Dans un shell, on exécute la commande ``cat < in.txt | grep sinf1252``. Quelles sont les appels systèmes qui doivent être exécutés par le shell pour lancer cette commande comme demandé par l'utilisateur ? - - .. only:: staff - - deux forks - premier fils - close(stdin) - close(stdout) - -11. Dans un shel `bash(1)`_, lorsque l'on suffixe une commande avec ``2>&1``, le shell redirige la sortie d'erreur standard vers la sortie standard. Quels sont les appels systèmes utilisés par le shell pour réussir cette redirection ? - - .. only :: staff - - le shell va faire fork pour exécuter le programme, mais avant il doit fermer stdout et le dupliquer avec dup ou dup2 - - -12. Comment se comporte l'appel système `write(2)`_ lorsque le disque sur lequel on souhaite écrire des données est plein ? Peut-on distinguer cette erreur d'un problème d'écriture sur le disque ? - - .. only:: staff - - il retourne une erreur et met errno à ENOSPC - -13. A quoi sert l'appel système `sync(2)`_ ? - - .. only:: staff - - A forcer l'écriture des données sur le disque - -14. Le programme :download:`/Programmes/src/writeperf.c` permet de tester les performances des écritures dans write sur un système de fichiers. Compilez-le et exécutez le avec différents tailles de buffers passés à `write(2)`_. Mesurez le temps d'exécution avec la commande `time(1posix)`_ et comparez le temps qu'il faut pour écrire 100MB en blocs de 1 MB ou en blocs de 1 KB. Faites de même en activant la synchronisation avec le paramètre ``-s``. - - .. only:: staff - - Les performances décroissent car il y a plus d'appels systèmes qui sont effectués. sync force l'écriture et bypasse le buffer. Il est utile de mentionner l'existence de ce buffer - -15. Effectuez l'exercice sur la manipulation de fichiers sur `INGInious <https://inginious.info.ucl.ac.be/course/LSINF1252/fichiers>`_. - -.. 17. `tee(1)`_ est un utilitaire qui permet de recopier son entrée standard vers un ou plusieurs fichiers et également vers sa sortie standard. Il peut être utile pour par exemple inspecter des données échangées entre deux processus à travers un :term:`pipe`. Quels sont les appels systèmes exécutés par `tee(1)`_ lors de l'exécution de la commande ``cat /tmp/t | tee /tmp/tee.out | grep "sinf1252" `` - - - -.. pas de mini-projet à cause des vacances de Paques - diff --git a/Exercices/Programmes/s2_perf.c b/Exercices/Programmes/s2_perf.c deleted file mode 100644 index a31da934037b771956cf3979fcec0aa30e8e76ef..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/s2_perf.c +++ /dev/null @@ -1,53 +0,0 @@ -/*********************************************** - * perf.c - * - * Mesure de temps de calcul via gettimeofday - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <sys/time.h> - -/* Return t2-t1 in microseconds */ -long timeval_diff(struct timeval *t2, struct timeval *t1) -{ - long diff = (t2->tv_usec + 1000000 * t2->tv_sec) - (t1->tv_usec + 1000000 * t1->tv_sec); - return (diff); -} -// n : number of iterations of the loop -void compute(int n) { - // long computation - double sum=0; - int i; - for(i=0;i<n;i++) { - sum=sum+i; - } -} - -int main(int argc, char *argv[]) -{ - struct timeval tvStart, tvEnd; - int err; - int num; // number of operations for compute - if(argc!=2) - exit(EXIT_FAILURE); - else - num=atoi(argv[1]); - - err=gettimeofday(&tvStart, NULL); - if(err!=0) - exit(EXIT_FAILURE); - - // long computation - compute(num); - - err=gettimeofday(&tvEnd, NULL); - if(err!=0) - exit(EXIT_FAILURE); - - printf("Duration : %ld microseconds\n", timeval_diff(&tvEnd, &tvStart)); - - return(EXIT_SUCCESS); -} - diff --git a/Exercices/Programmes/s2_qbf.c b/Exercices/Programmes/s2_qbf.c deleted file mode 100644 index 4fb42a78bf4aee241ab36f0486b6df6736fb4b06..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/s2_qbf.c +++ /dev/null @@ -1,25 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <stdint.h> - -int main() { - char strtab[36] = "Coucou!! Je suis un grand string\n"; - char *str = strtab; - int i; - for (i = 0; i < 8; i++) { - char c = str[i]; - printf("Char %d, located at %p, is %c\n", i, &str[i], c); - } - uint32_t *str2 = (uint32_t *) str; - for (i = 0; i < 8; i++) { - uint32_t ui = str2[i]; - printf("UInt %d, located at %p, is %u\n", i, &str2[i], ui); - } - str2[0] = 1801675080; - str2[1] = 555836517; - for (i = 0; i < 8; i++) { - char c = str[i]; - printf("Char %d, located at %p, is %c\n", i, &str[i], c); - } - return 0; -} diff --git a/Exercices/Programmes/src/alarm.c b/Exercices/Programmes/src/alarm.c deleted file mode 100644 index 7e6f6894f76c385fc59508573cb0113f83f44f15..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/alarm.c +++ /dev/null @@ -1,45 +0,0 @@ -/************************************** - * alarm.c - * - * Programme d'exemple d'utilisation des - * signaux SIGUSR - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <unistd.h> -#include <stdbool.h> - -static void sig_handler(int); - -int main (int argc, char *argv[]) { - char c; - printf("Tapez return en moins de 5 secondes ! \n"); - fflush(stdout); - if(signal(SIGALRM,sig_handler)==SIG_ERR) { - perror("signal"); - exit(EXIT_FAILURE); - } - // sigalrm interrompt les appels système - if(siginterrupt(SIGALRM,true)<0) { - perror("siginterrupt"); - exit(EXIT_FAILURE); - } - alarm(5); - int r=read(STDIN_FILENO,&c,1); - if((r==1)&&(c=='\n')) { - alarm(0); // reset timer - printf("Gagné \n"); - exit(EXIT_SUCCESS); - } - printf("Perdu !\n"); - exit(EXIT_FAILURE); -} - -static void sig_handler(int signum) { - // rien à faire, read sera interrompu -} - -///BBB diff --git a/Exercices/Programmes/src/alarm3.c b/Exercices/Programmes/src/alarm3.c deleted file mode 100644 index 9dac8215c099653cbe12b4eda6cb5f7e4cabd7c4..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/alarm3.c +++ /dev/null @@ -1,57 +0,0 @@ -/************************************** - * alarm3.c - * - * Programme d'exemple de lecture avec temps - * limité via alarm - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <unistd.h> -#include <stdbool.h> -#include <setjmp.h> - -sig_atomic_t expired=false; - -static void sig_handler(int); - -int main (int argc, char *argv[]) { - char c; - printf("Tapez return en moins de 5 secondes ! \n"); - fflush(stdout); - if(signal(SIGALRM,sig_handler)==SIG_ERR) { - perror("signal"); - exit(EXIT_FAILURE); - } - // sigalrm interrompt les appels système - if(siginterrupt(SIGALRM,true)<0) { - perror("siginterrupt"); - exit(EXIT_FAILURE); - } - int r=0; - alarm(5); - if(!expired) { - r=read(STDIN_FILENO,&c,1); - } - else { - // sig_handler a déjà été exécuté - // le délai a déjà expiré, inutile de faire read - } - alarm(0); // arrêt du timer - if((r==1)&&(c=='\n')) { - printf("Gagné \n"); - exit(EXIT_SUCCESS); - } - else { - printf("Perdu !\n"); - exit(EXIT_FAILURE); - } -} - -static void sig_handler(int signum) { - expired=true; -} - -///BBB diff --git a/Exercices/Programmes/src/fork-perf.c b/Exercices/Programmes/src/fork-perf.c deleted file mode 100644 index 3c330d9569d6b947e69c2f0c557656898257f01b..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/fork-perf.c +++ /dev/null @@ -1,47 +0,0 @@ -/************************************** - * fork-perf.c - * - * Programme d'exemple pour calculer le coût - * de fork - * - *************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/wait.h> -#include <sys/types.h> - -#define N 100000 - -int main (int argc, char *argv[]) { - int status; - pid_t pid; - - for(int i=0;i<N;i++) { - pid=fork(); - if (pid==-1) { - // erreur à l'exécution de fork - perror("fork"); - exit(EXIT_FAILURE); - } - // pas d'erreur - if (pid==0) { - return(EXIT_SUCCESS); - } - else { - int fils=waitpid(pid,&status,0); - if(fils==-1) { - perror("wait"); - exit(EXIT_FAILURE); - } - if(!WIFEXITED(status)) { - fprintf(stderr,"Erreur de waitpid\n"); - exit(EXIT_FAILURE); - } - } - } - return(EXIT_SUCCESS); - -} - diff --git a/Exercices/Programmes/src/fork-pthread.c b/Exercices/Programmes/src/fork-pthread.c deleted file mode 100644 index ebb9b6d6bd6e9580d7942c92af6167ba8d2a993b..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/fork-pthread.c +++ /dev/null @@ -1,78 +0,0 @@ -/************************************** - * fork-pthread.c - * - * Programme d'exemple pour voir le contenu de /proc - * - *************************************/ - -#define _GNU_SOURCE -#include <stdio.h> -#include <stdlib.h> -#include <pthread.h> -#include <unistd.h> -#include <sys/wait.h> -#include <sys/types.h> -#include <sys/syscall.h> - -#define DELAY 600 - -pid_t gettid() { - pid_t tid; - tid = syscall(SYS_gettid); - return tid; -} - - -void *func(void * param) { - int slept=DELAY; - printf("thread : %d\n",gettid()); - fflush(stdout); - while((slept=sleep(slept))!=0) ; - pthread_exit(NULL); -} - -int main (int argc, char *argv[]) { - int err; - pid_t pid; - int status; - pthread_t thread; - int slept=DELAY; - printf("père : %d\n",getpid()); - fflush(stdout); - pid=fork(); - if (pid==-1) { - perror("fork"); - exit(EXIT_FAILURE); - } - if (pid==0) { - // fils - printf("fils : %d\n",getpid()); - fflush(stdout); - while((slept=sleep(slept))!=0) ; - return(EXIT_SUCCESS); - } - else { - // père - err=pthread_create(&(thread),NULL,&func,NULL); - if(err!=0) { - perror("pthread_create"); - exit(EXIT_FAILURE); - } - err=pthread_join(thread,NULL); - if(err!=0) { - perror("pthread_join"); - exit(EXIT_FAILURE); - } - int fils=waitpid(pid,&status,0); - if(fils==-1) { - perror("wait"); - exit(EXIT_FAILURE); - } - if(!WIFEXITED(status)) { - fprintf(stderr,"Erreur de waitpid\n"); - exit(EXIT_FAILURE); - } - } - return(EXIT_SUCCESS); -} - diff --git a/Exercices/Programmes/src/fork-zombie.c b/Exercices/Programmes/src/fork-zombie.c deleted file mode 100644 index 33959bf53a1bbcd70d980bd9fae5164fe48115d9..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/fork-zombie.c +++ /dev/null @@ -1,45 +0,0 @@ -/************************************** - * fork-zombie.c - * - * Programme d'exemple d'utilisation de - * fork qui crée un zombie - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/wait.h> -#include <sys/types.h> - - -int main (int argc, char *argv[]) { - pid_t pid; - int err; - - pid=fork(); - - if (pid==-1) { - // erreur à l'exécution de fork - perror("fork"); - exit(EXIT_FAILURE); - } - // pas d'erreur - if (pid==0) { - // fin du fils - printf("pid du zombie: %d\n",getpid()); - return(EXIT_SUCCESS); - } - else { - // processus père - sleep(50); - err=wait(NULL); - if(err!=0) { - perror("fork"); - exit(EXIT_FAILURE); - } - printf("Fin du processus père [%d]\n",getpid()); - return(EXIT_SUCCESS); - } -} -///BBB diff --git a/Exercices/Programmes/src/miniprojet.c b/Exercices/Programmes/src/miniprojet.c deleted file mode 100644 index 701af2f245a1e25fcade6a9279bb0072a6fdfd20..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/miniprojet.c +++ /dev/null @@ -1,134 +0,0 @@ - -/* Necessary for the correct compilation */ -#define _POSIX_C_SOURCE 200809L - -#include <fcntl.h> -#include <sys/stat.h> -#include <semaphore.h> -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> - - -/** Global variables */ - -int file; -sem_t *readsem; -sem_t *writesem; - -static void producer() -{ - int i = 0; - while (1) { - char buf[2]; - int val = rand() % 10; - - if (snprintf(buf, 2, "%d", val) < 0) { - perror("Error with snprintf\n"); - return; - } - - if (sem_wait(writesem) < 0) { - perror("Error with sem_wait\n"); - return; - } - - if (pwrite(file, buf, 1, i) < 0) { - perror("Error with pwrite\n"); - return; - } - - if (sem_post(readsem) < 0) { - perror("Error with sem_post\n"); - return; - } - - i++; - sleep(val); - } - - return; -} - -static void consumer() -{ - int i = 0; - - while (1) { - char buf[2]; - - buf[1] = 0; - - if (sem_wait(readsem) < 0) { - perror("Error with sem_wait\n"); - return; - } - - if (pread(file, buf, 1, i) < 0) { - perror("Error with pread\n"); - return; - } - - if (sem_post(writesem) < 0) { - perror("Error with sem_post\n"); - return; - } - - printf("Read done of: %s\n", buf); - - i++; - } - - return; -} - -int main (int argc, char const *argv[]) -{ - int pid, ret = 0; - - /* Open file */ - file = open("my_file.txt", O_RDWR | O_CREAT | O_TRUNC, 0644); - if (file < 0) { - ret = 1; - goto err_open; - } - - /* Create the shared read semaphore. */ - readsem = sem_open("minireader", O_CREAT, S_IRUSR | S_IWUSR, 0); - if (readsem == SEM_FAILED) { - ret = 1; - goto err_read; - } - - /* Create the shared write semaphore. - * Init to 1, because the producer can directly write a value. */ - writesem = sem_open("miniwriter", O_CREAT, S_IRUSR | S_IWUSR, 1); - if (writesem == SEM_FAILED) { - ret = 1; - goto err_write; - } - - /* Now create the son-process and start producing/consuming */ - pid = fork(); - if (pid < 0) { - ret = 1; - goto err_fork; - } - - /* Are we the parent? */ - if (pid) - producer(); - else - consumer(); - -err_fork: - sem_close(writesem); -err_write: - sem_close(readsem); -err_read: - close(file); -err_open: - if (ret) - perror("Error happened!\n"); - return ret; -} diff --git a/Exercices/Programmes/src/process-sem-after.c b/Exercices/Programmes/src/process-sem-after.c deleted file mode 100644 index 06ebd160fba30ad04514b35f928fa1b0386b78ce..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/process-sem-after.c +++ /dev/null @@ -1,58 +0,0 @@ -/************************************** - * process-sem-before.c - * - * Programme d'exemple de sémaphores nommés - * La fonction after ne peut s'exécuter - * qu'après la fonction before - **************************************/ - -#include <pthread.h> -#include <semaphore.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> /* For O_* constants */ -#include <sys/stat.h> /* For mode constants */ -#include <sys/types.h> -#include <unistd.h> - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - - -///AAA - -sem_t *semaphore; - -void after() { - sem_wait(semaphore); - // do something - for(int j=0;j<1000000;j++) { - } - printf("after done, pid=%d\n",(int) getpid()); -} - -int main (int argc, char *argv[]) { - int err; - - // semaphore a été créé par before - semaphore=sem_open("lsinf1252",0); - if(semaphore==SEM_FAILED) { - error(-1,"sem_open"); - } - after(); - - err=sem_close(semaphore); - if(err!=0) { - error(err,"sem_close"); - } - err=sem_unlink("lsinf1252"); - if(err!=0) { - error(err,"sem_unlink"); - } - return(EXIT_SUCCESS); -} -///BBB diff --git a/Exercices/Programmes/src/process-sem-before.c b/Exercices/Programmes/src/process-sem-before.c deleted file mode 100644 index 1356eb8678aaa5ef6b413163832cd8ba7fa42511..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/process-sem-before.c +++ /dev/null @@ -1,56 +0,0 @@ -/************************************** - * process-sem-before.c - * - * Programme d'exemple de sémaphores - * La fonction after ne peut s'exécuter - * qu'après la fonction before - **************************************/ - -#include <pthread.h> -#include <semaphore.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> /* For O_* constants */ -#include <sys/stat.h> /* For mode constants */ -#include <sys/types.h> - - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - - -///AAA - -sem_t *semaphore; - -void before() { - // do something - for(int j=0;j<1000000;j++) { - } - printf("before done, pid=%d\n",(int) getpid()); - sem_post(semaphore); -} - - -int main (int argc, char *argv[]) { - - int err; - - semaphore=sem_open("lsinf1252",O_CREAT,S_IRUSR | S_IWUSR,0); - if(semaphore==SEM_FAILED) { - error(-1,"sem_open"); - } - sleep(20); - before(); - err=sem_close(semaphore); - if(err!=0) { - error(err,"sem_close"); - } - return(EXIT_SUCCESS); -} -///BBB diff --git a/Exercices/Programmes/src/prog-5-measure/Makefile b/Exercices/Programmes/src/prog-5-measure/Makefile deleted file mode 100644 index 4ef1a98840d03ac79eaec2de2339112333b3d43d..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/prog-5-measure/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -BIN=crypt -CFLAGS=-Wall -Werror -LDFLAGS=-lcrypt -SRC=$(wildcard *.c) -OBJ=$(SRC:.c=.o) - -.PHONY: clean all - -all: $(BIN) - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - -$(BIN): $(OBJ) - $(CC) -o $@ $(OBJ) $(LDFLAGS) - -clean: - rm -f $(OBJ) \ No newline at end of file diff --git a/Exercices/Programmes/src/prog-5-measure/compute.c b/Exercices/Programmes/src/prog-5-measure/compute.c deleted file mode 100644 index 06d1633987e81df6a6dfac05f5bef0bcd2be2100..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/prog-5-measure/compute.c +++ /dev/null @@ -1,84 +0,0 @@ -#define _XOPEN_SOURCE -#include <unistd.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - -#include "compute.h" - -#define MIN(a,b) (a < b ? a : b) -#define SIZE 8 -#define SIZE_BITS (SIZE * 8) -#define SIZE_HEX (SIZE * 2) - -static void str2hex(const char *input, size_t len, char *output) -{ - int i; - - memset(output, 0, SIZE_HEX); - for (i = 0; i < SIZE_HEX; i += 2) - sprintf(output + i, "%02hhX", input[i / 2]); -} - -static void hex2str(const char *input, size_t len, char *output) -{ - int i; - - memset(output, 0, len / 2); - for (i = 0; i < len; i += 2) - sscanf(input + i, "%02hhX", &output[i / 2]); -} - -static void str2bits(const char *input, size_t len, char *output) -{ - int i; - - memset(output, 0, 64); - for(i = 0; i < MIN(len * 8, 64); ++i) - output[i] = (input[i / 8] >> (i % 8)) & 1; -} - -static void bits2str(const char *input, char *output) -{ - int i; - - memset(output, 0, SIZE); - for (i = 0; i < SIZE_BITS; ++i) - output[i / 8] |= input[i] << (i % 8); -} - - -static void __encrypt(char work[SIZE_BITS], int n, int decrypt) -{ - while (n--) - encrypt(work, decrypt); -} - -void pwd_init(const char *key) -{ - char work[SIZE_BITS]; - - str2bits(key, MIN(strlen(key), 8), work); - setkey(work); -} - -void pwd_encrypt(const char *pwd, char *cipher, int n) -{ - char work[SIZE_BITS], output[SIZE]; - - str2bits(pwd, strlen(pwd), work); - __encrypt(work, n, 0); - bits2str(work, output); - str2hex(output, SIZE, cipher); -} - -void pwd_decrypt(const char *hex, char *pwd, int n) -{ - char work[SIZE_BITS], input[SIZE]; - - hex2str(hex, strlen(hex), input); - str2bits(input, SIZE, work); - __encrypt(work, n, 1); - bits2str(work, pwd); -} - diff --git a/Exercices/Programmes/src/prog-5-measure/compute.h b/Exercices/Programmes/src/prog-5-measure/compute.h deleted file mode 100644 index 1e84f28aeacc8bcdab7022da6f32f0ee9188ad95..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/prog-5-measure/compute.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _COMPUTE_H_ -#define _COMPUTE_H_ - - -/* Initialize the password, only the first 8 bytes of key will be considered. */ -void pwd_init(const char *key); - -/* Encrypt pwd n times and store its output as a hexadecimal string in cipher. - * Only the first 8 bytes of pwd will be considered. cipher must have at least - * a size of 17 bytes. */ -void pwd_encrypt(const char *pwd, char *cipher, int n); - -/* Decrypt n times the cipher represented in hexadecimal and store its output -in pwd. pwd must have a size of at least 8 bytes. */ -void pwd_decrypt(const char *cipher, char *pwd, int n); - -#endif diff --git a/Exercices/Programmes/src/prog-5-measure/main.c b/Exercices/Programmes/src/prog-5-measure/main.c deleted file mode 100644 index 6d3f2e2dcd99a457e9fee69f51c3cc8dc204f2fc..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/prog-5-measure/main.c +++ /dev/null @@ -1,57 +0,0 @@ -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <stdlib.h> - -#include "compute.h" - -int main (int argc, char *const argv[]) -{ - char c; - char *password = NULL; - int i, decrypt = 0, n = 0; - char output[17]; - - while ((c = getopt (argc, argv, "dn:p:")) != -1) { - switch (c) { - case 'd': - decrypt = 1; - break; - case 'n': - n = strtol(optarg, NULL, 10); - break; - case 'p': - password = optarg; - break; - case '?': - fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); - default: - return 1; - } - } - - if (!password) { - fprintf (stderr, "You must specify a password.\n"); - return 1; - } - - if (optind == argc) { - fprintf (stderr, "You must specify at least one argument.\n"); - return 1; - } - - pwd_init(password); - - for (i = optind; i < argc; ++i) { - if (decrypt) { - pwd_decrypt(argv[i], output, n); - printf("%.*s ", 8, output); - } else { - pwd_encrypt(argv[i], output, n); - printf("%.*s ", 16, output); - } - } - printf("\n"); - - return 0; -} diff --git a/Exercices/Programmes/src/prog-5-measure/prog-5-measure.tar.gz b/Exercices/Programmes/src/prog-5-measure/prog-5-measure.tar.gz deleted file mode 100644 index af0ab777e352d82a6c480c46e5cd563f03e2f474..0000000000000000000000000000000000000000 Binary files a/Exercices/Programmes/src/prog-5-measure/prog-5-measure.tar.gz and /dev/null differ diff --git a/Exercices/Programmes/src/prog2.c b/Exercices/Programmes/src/prog2.c deleted file mode 100644 index bc13550745334df8a12c66e30ed7474657da664b..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/prog2.c +++ /dev/null @@ -1,156 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -struct fraction { - int num; - int den; -}; - - -struct fraction * simp1(struct fraction f); -struct fraction * simp2(struct fraction * f); -struct fraction simp3(struct fraction f) { - struct fraction f2= {.num=1, .den=2}; - return f2; -} - - -int main(int argc, char **argv){ - double d; - double tab[4]={1,2,3,4}; - double mat[3][4]={ {1,2,3,4},{5,6,7,8},{9,10,11,12}} ; - double *ptr1; - double *ptrl; - double *ptr2; - - ptr1=tab; - - printf("sizeof(d)=%d\n",sizeof(d)); - printf("&d=%p\n",&d); - for(int i=0;i<4;i++){ - printf("tab[%d]=%f at address %p\n",i,tab[i],&(tab[i]) ); - printf("tab[%d]=%f at address %p\n",i,*(ptr1+i),ptr1+i); - printf("tab[%d]=%f at address %p\n",i,*ptr1+i,ptr1+i); - printf("tab[%d]=%f at address %p\n",i,(*(ptr1))+(double)i,ptr1+i); - } - - ptr2=&(mat[0][0]); - - for(int i=0;i<3;i++){ - for(int j=0;j<4;j++) { - printf("mat[%d][%d]=%f at address %p\n",i,j,mat[i][j],&(mat[i][j])); - printf("mat[%d][%d]=%f at relative address %d\n",i,j,mat[i][j],&(mat[i][j])-&(mat[0][0])); - printf("mat[%d][%d]=%f at address %p\n",i,j,*(ptr2+i*4+j),ptr2+i*4+j); - } - } - - int l=1; - ptrl=mat[1]; - for(int c=0;c<4;c++){ - printf("mat[%d][%d]=%f at address %p\n",l,c,mat[l][c],&(mat[l][c])); - printf("mat[%d][%d]=%f at address %p\n",l,c,*(ptrl+c),ptrl+c); - } - - - struct record { - char c[3]; - double num; - char d; - int data[4]; - }; - - struct record t1; - t1.c[0]='A'; - t1.c[1]='B'; - t1.c[2]='C'; - t1.num=42.0; - t1.d='Z'; - t1.data[1]=2; - printf("sizeof(test)=%d\n",sizeof(t1)); - printf("&(t1)=%p\n",&(t1)); - printf("&(t1.c[0])=%p\n",&(t1.c[0])); - printf("&(t1.num)=%p\n",&(t1.num)); - printf("&(t1.d)=%p\n",&(t1.d)); - printf("&(t1.data)=%p\n",&(t1.data)); - - char *dp=(char *) &(t1) + 4 + 8; - printf("%p\n",dp); - - - - struct fraction f1; - f1.num=1; - f1.den=17; - - printf("sizeof(fraction)=%d\n",sizeof(f1)); - printf("&(f1)=%p\n",&(f1)); - printf("&(f1.num)=%p\n",&(f1.num)); - printf("&(f1.num)+1=%p\n",&(f1.num)+1); - printf("&(f1.den)=%p\n",&(f1.den)); - - struct fraction f2; - f2=simp3(f1); - printf("%d/%d\n",f2.num,f2.den); - - struct fraction tabfract[2]; - tabfract[0].num=1; - tabfract[0].den=7; - tabfract[1].num=2; - tabfract[1].den=3; - - struct fraction *p=tabfract; - printf("%d \n",(p+1)->den); - printf("&(tabfract[0])=%p\n",&(tabfract[0])); - printf("&(tabfract)=%p\n",&(tabfract)); - printf("tabfract=%p\n",tabfract); - - printf("&(tabfract[1])=%p\n",&(tabfract[1])); - - printf("argc=%d\n",argc); - for(int i=0;i<argc;i++) { - char *ptr=*(argv+i); - printf("argv[%d]=%s\n",i,ptr); - for(int j=0;j<strlen(ptr);j++) { - printf("%c is at %p\n",*(ptr+j),ptr+j); - } - } - - char *string="abcdef"; - char string2[]="abcdef"; - /* - char string3="ab"; - char *string4='A'; - char string5='B'; - char *string6="C"; - */ - printf("%s\n",string); - printf("%s\n",string2); - - - printf("%s\n",string+2); - - - printf("%c\n",*(string+3)); - - printf("%c\n",*(string+6)); - printf("test\n"); - - string2[0]='A'; - *(string2)='A'; - *(string2+5)='F'; - *(string2+strlen(string2))='G'; - *(string2+strlen(string2)+1)='H'; - - printf("%s\n",string2); - - // see https://stackoverflow.com/questions/1335786/c-differences-between-char-pointer-and-array - - // string++; - // printf("%s\n",string); - - - - - -} diff --git a/Exercices/Programmes/src/pthread-array.c b/Exercices/Programmes/src/pthread-array.c deleted file mode 100644 index d0ecf2329bad97f612381e0ca08bd9646a57bc0b..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/pthread-array.c +++ /dev/null @@ -1,50 +0,0 @@ -/************************************** - * pthread-neg.c - * - * Programme d'exemple de pthread utilisant les - * arguments et retournant une valeur - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -///AAA -#define SIZE 100 - -pthread_t mythread; - -void *f(void *param) { - int *v=(int *) param; - long r=0; - for(long i=0;i<SIZE;i++) { - r+=v[i]; - } - return((void *) r); -} - -void launch(void ){ - int v[SIZE]; - for(int i=0;i<SIZE;i++) { - v[i]=1; - } - int err=pthread_create(&(mythread),NULL,&f,(void *) v); - if(err!=0) - error(err,"pthread_create"); -} - - -int main (int argc, char *argv[]) { - - launch(); - // ... - return(EXIT_SUCCESS); -} diff --git a/Exercices/Programmes/src/pthread-perf.c b/Exercices/Programmes/src/pthread-perf.c deleted file mode 100644 index 07772a2c21ab37b146401686b55c6945b23ba375..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/pthread-perf.c +++ /dev/null @@ -1,41 +0,0 @@ -/************************************** - * pthread-perf.c - * - * Programme d'exemple pour calculer le coût - * de pthread - * - *************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <pthread.h> - -#define N 100000 - -void *func(void * param) { - pthread_exit(NULL); -} - - -int main (int argc, char *argv[]) { - int err; - pthread_t thread; - - - for(int i=0;i<N;i++) { - - err=pthread_create(&(thread),NULL,&func,NULL); - if(err!=0) { - perror("pthread_create"); - exit(EXIT_FAILURE); - } - err=pthread_join(thread,NULL); - if(err!=0) { - perror("pthread_join"); - exit(EXIT_FAILURE); - } - } - return(EXIT_SUCCESS); - -} - diff --git a/Exercices/Programmes/src/pthread-philo-sem.c b/Exercices/Programmes/src/pthread-philo-sem.c deleted file mode 100644 index 8d27d804b61277834c87a0cbc9d095413a8076a8..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/pthread-philo-sem.c +++ /dev/null @@ -1,69 +0,0 @@ -/************************************** - * pthread-philo-sem.c - * - * Programme d'exemple de pthread avec - * philosophes qui dinent et sémaphores - * - **************************************/ - -///AAA -#include <pthread.h> -#include <semaphore.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <unistd.h> - -#define PHILOSOPHES 3 - -pthread_t phil[PHILOSOPHES]; -sem_t baguette[PHILOSOPHES]; - -void mange(int id) { - printf("Philosophe [%d] mange\n",id); - for(int i=0;i< rand(); i++) { - // philosophe mange - } -} - -void* philosophe ( void* arg ) -{ - int *id=(int *) arg; - int left = *id; - int right = (left + 1) % PHILOSOPHES; - while(true) { - printf("Philosophe [%d] pense\n",*id); - sem_wait(&baguette[left]); - printf("Philosophe [%d] possède baguette gauche [%d]\n",*id,left); - sem_wait(&baguette[right]); - printf("Philosophe [%d] possède baguette droite [%d]\n",*id,right); - mange(*id); - sem_post(&baguette[left]); - printf("Philosophe [%d] a libéré baguette gauche [%d]\n",*id,left); - sem_post(&baguette[right]); - printf("Philosophe [%d] a libéré baguette droite [%d]\n",*id,right); - } - return (NULL); -} -///BBB -int main ( int argc, char *argv[]) -{ - long i; - int id[PHILOSOPHES]; - - srand(getpid()); - - for (i = 0; i < PHILOSOPHES; i++) - id[i]=i; - - for (i = 0; i < PHILOSOPHES; i++) - sem_init( &baguette[i], 0 , 1); - - for (i = 0; i < PHILOSOPHES; i++) - pthread_create(&phil[i], NULL, philosophe, (void*)&(id[i]) ); - - for (i = 0; i < PHILOSOPHES; i++) - pthread_join(phil[i], NULL); - - return (EXIT_SUCCESS); -} diff --git a/Exercices/Programmes/src/pthread-philo.c b/Exercices/Programmes/src/pthread-philo.c deleted file mode 100644 index 33d63c137ecf32e6359464660adb269648fdfb91..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/pthread-philo.c +++ /dev/null @@ -1,68 +0,0 @@ -/************************************** - * pthread-philo.c - * - * Programme d'exemple de pthread avec - * philosophes qui dinent et mutex - * - **************************************/ - -///AAA -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <unistd.h> - -#define PHILOSOPHES 3 - -pthread_t phil[PHILOSOPHES]; -pthread_mutex_t baguette[PHILOSOPHES]; - -void mange(int id) { - printf("Philosophe [%d] mange\n",id); - for(int i=0;i< rand(); i++) { - // philosophe mange - } -} - -void* philosophe ( void* arg ) -{ - int *id=(int *) arg; - int left = *id; - int right = (left + 1) % PHILOSOPHES; - while(true) { - printf("Philosophe [%d] pense\n",*id); - pthread_mutex_lock(&baguette[left]); - printf("Philosophe [%d] possède baguette gauche [%d]\n",*id,left); - pthread_mutex_lock(&baguette[right]); - printf("Philosophe [%d] possède baguette droite [%d]\n",*id,right); - mange(*id); - pthread_mutex_unlock(&baguette[left]); - printf("Philosophe [%d] a libéré baguette gauche [%d]\n",*id,left); - pthread_mutex_unlock(&baguette[right]); - printf("Philosophe [%d] a libéré baguette droite [%d]\n",*id,right); - } - return (NULL); -} -///BBB -int main ( int argc, char *argv[]) -{ - long i; - int id[PHILOSOPHES]; - - srand(getpid()); - - for (i = 0; i < PHILOSOPHES; i++) - id[i]=i; - - for (i = 0; i < PHILOSOPHES; i++) - pthread_mutex_init( &baguette[i], NULL); - - for (i = 0; i < PHILOSOPHES; i++) - pthread_create(&phil[i], NULL, philosophe, (void*)&(id[i]) ); - - for (i = 0; i < PHILOSOPHES; i++) - pthread_join(phil[i], NULL); - - return (EXIT_SUCCESS); -} diff --git a/Exercices/Programmes/src/pthread-test.c b/Exercices/Programmes/src/pthread-test.c deleted file mode 100644 index 0cfb277d9aa349afd6f0f8bf5dc9ec74bdab10d8..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/pthread-test.c +++ /dev/null @@ -1,56 +0,0 @@ -/************************************** - * pthread-test.c - * - * Programme d'exemple de pthread avec condition de course - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -///AAA - -#define NTHREADS 4 - -long global=0; - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -int increment(int i) { - return i+1; -} - -void *func(void * param) { - for(int j=0;j<1000000;j++) { - global=increment(global); - } - pthread_exit(NULL); -} - -int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&func,NULL); - if(err!=0) - error(err,"pthread_create"); - } - for(int i=0; i<1000000000;i++) { /*...*/ } - - for(int i=NTHREADS-1;i>=0;i--) { - err=pthread_join(thread[i],NULL); - if(err!=0) - error(err,"pthread_join"); - } - - printf("global: %ld\n",global); - - return(EXIT_SUCCESS); -} diff --git a/Exercices/Programmes/src/s4_qbf.c b/Exercices/Programmes/src/s4_qbf.c deleted file mode 100644 index bf5c07ec5f959d42fc0082e4142ca444097a7e8d..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/s4_qbf.c +++ /dev/null @@ -1,18 +0,0 @@ -#include <stdlib.h> - -int cours = 1252; - -int f(int *a, int b) { - int c = 97850**a + b; - int x = 2052; - *a = x * c; - return c; -} - -int main(int argc, char *argv[]) { - int d = 42; - char *tab = malloc(20 * sizeof(char)); - int *res = (int *) tab; - *res = f(&cours, d); - return 0; -} diff --git a/Exercices/Programmes/src/stack.c b/Exercices/Programmes/src/stack.c deleted file mode 100644 index d3ad20949c004cb6e54fd8ddfdb025f61949fa54..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/stack.c +++ /dev/null @@ -1,96 +0,0 @@ -/************************************** - * stack.c - * - * Programme d'exemple implémentant un stack comme structure - * chaînée - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -typedef struct fraction_t { - int num; - int den; -} fraction; - -///AAA -typedef struct node_t -{ - struct fraction_t *data; - struct node_t *next; -} node; - -struct node_t *stack; // sommet de la pile - -// ajoute un élément au sommet de la pile -void push(struct fraction_t *f) -{ - struct node_t *n; - n=(struct node_t *)malloc(sizeof(struct node_t)); - if(n==NULL) - exit(EXIT_FAILURE); - n->data = f; - n->next = stack; - stack = n; -} -// retire l'élément au sommet de la pile -struct fraction_t * pop() -{ - if(stack==NULL) - return NULL; - // else - struct fraction_t *r; - struct node_t *removed=stack; - r=stack->data; - stack=stack->next; - free(removed); - return (r); -} - -///BBB - -// affiche le contenu de la pile -void display() -{ - struct node_t *t; - t = stack; - while(t!=NULL) { - if(t->data!=NULL) { - printf("Item at addr %p : Fraction %d/%d Next %p \n",t,t->data->num,t->data->den,t->next); - } - else { - printf("Bas du stack %p \n",t); - } - t=t->next; - } -} - -// exemple -int main(int argc, char *argv[]) { - - struct fraction_t demi={1,2}; - struct fraction_t tiers={1,3}; - struct fraction_t quart={1,4}; - struct fraction_t zero={0,1}; - - // initialisation - stack = (struct node_t *)malloc(sizeof(struct node_t)); - stack->next=NULL; - stack->data=NULL; - - display(); - push(&zero); - display(); - push(&demi); - push(&tiers); - push(&quart); - display(); - - struct fraction_t *f=pop(); - if(f!=NULL) - printf("Popped : %d/%d\n",f->num,f->den); - - return(EXIT_SUCCESS); -} -///CCC diff --git a/Exercices/Programmes/src/string.c b/Exercices/Programmes/src/string.c deleted file mode 100644 index 0190db7f20704ba25d9f5f1dd317dc78660d3cc3..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/string.c +++ /dev/null @@ -1,60 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> - -/** - * Returns the number of characters in s - */ -size_t strlen(const char *s) -{ - int i = 0; - while(s[i] != '\0') - { - i++; - } - return i; -} - -/** - * Appends the src string to the dest string, overwriting - * the null byte ('\0') at the end of dest, and then adds - * a terminating null byte. The strings may not overlap, - * and the dest string must have enough space for the result. - */ -char * strcat(char *s1, const char *s2) -{ - int i; - for(i = 0; i < strlen(s2); i++) - { - *(s1 + strlen(s1) + i) = *(s2 + i); - } - *(s1 + strlen(s1) + i) = '\0'; - return s1; -} - -int main(int argc, char *argv[]) { - /* Test function */ - char *text_1 = "Hello"; - char *text_2 = " World!"; - char *text_3 = NULL; - char concat_1[100]; - char concat_2[100]; - int i; - - printf("Length of %s: %lu\n", text_1, strlen(text_1)); - printf("Length of %s: %lu\n", text_2, strlen(text_2)); - printf("Length of %s: %lu\n", text_3, strlen(text_3)); - - for (i = 0; i < strlen(text_1); i++) - concat_1[i] = *(text_1 + i); - printf("Putting %s and %s together gives %s\n", text_1, text_2, strcat(concat_1, text_2)); - - /* Taking arguments, if any */ - printf("Length of %s: %lu\n", argv[1], strlen(argv[1])); - printf("Length of %s: %lu\n", argv[2], strlen(argv[2])); - - for (i = 0; i < strlen(argv[1]); i++) - concat_1[i] = *(argv[1] + i); - printf("Putting %s and %s together gives %s\n", argv[1], argv[2], strcat(concat_2, argv[2])); - - return 0; -} diff --git a/Exercices/Programmes/src/sumarray.c b/Exercices/Programmes/src/sumarray.c deleted file mode 100644 index 63cf13852be1738026ca0f976d874025d34525cf..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/sumarray.c +++ /dev/null @@ -1,56 +0,0 @@ -/************************************** - * sumarray.c - * - * Programme d'exemple pour calculer la - * somme des éléments d'une matrice - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -/* Return t2-t1 in microseconds */ -long timeval_diff(struct timeval *t2, struct timeval *t1) -{ - long diff = (t2->tv_usec + 1000000 * t2->tv_sec) - (t1->tv_usec + 1000000 * t1->tv_sec); - return (diff); -} - -///AAA -#define SIZE 10000 - -int matrix[SIZE][SIZE]; - -int sum() { - int sum=0; - for(int i=0;i<SIZE;i++) { - for(int j=0;j<SIZE;j++) { - sum+=matrix[i][j]; - } - } - return sum; -} - -int sum2() { - int sum=0; - for(int i=0;i<SIZE;i++) { - for(int j=0;j<SIZE;j++) { - sum+=matrix[j][i]; - } - } - return sum; -} -///BBB - -int main(int argc, char *argv[]) { - - for(int i=0;i<SIZE;i++) { - for(int j=0;j<SIZE;j++) { - matrix[i][j]=1; - } - } - printf("%d \n",sum()); - printf("%d \n",sum2()); - - return(EXIT_SUCCESS); -} diff --git a/Exercices/Programmes/src/vector.c b/Exercices/Programmes/src/vector.c deleted file mode 100644 index d41579c3e55a0bac3702941e812cefdedb5039e6..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/vector.c +++ /dev/null @@ -1,59 +0,0 @@ -/************************************** - * vector.c - * - * Programme de manipulation de vecteurs - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> -///AAA -struct vector_t { - int size; - float *v; -}; -// initialise le vecteur à la valeur du réel -struct vector_t * init(int, float) ; -// récupère le nième élément -float get(struct vector_t *, int) ; -// fixe la valeur du nième élément -void set(struct vector_t *, int , float); -// supprime un vecteur -void destroy(struct vector_t *); - -///BBB -struct vector_t * init(int size, float val) -{ - struct vector_t *v=(struct vector_t *)malloc(sizeof(struct vector_t)); - v->v=(float *)malloc(size*sizeof(float)); - v->size=size; - for(int i=0;i<size;i++) { - *(v->v+i)=val; - } - return v; -} - -float get(struct vector_t *v, int i) { - return *(v->v+i); -} - -void set(struct vector_t *v, int i, float val) { - if(i<v->size) - *(v->v+i)=val; -} - -void destroy(struct vector_t *v) { - free(v->v); - free(v); -} - -int main(int argc, char *argv[]) { - - struct vector_t *v1=init(10,2.0); - printf("v1[%d]=%f\n",3,get(v1,3)); - set(v1,3,17.0); - printf("v1[%d]=%f\n",3,get(v1,3)); - destroy(v1); - - return(EXIT_SUCCESS); -} diff --git a/Exercices/Programmes/src/writeperf.c b/Exercices/Programmes/src/writeperf.c deleted file mode 100644 index 0fee8dc85c0baccbfa2f085d2f3ef0841eff6219..0000000000000000000000000000000000000000 --- a/Exercices/Programmes/src/writeperf.c +++ /dev/null @@ -1,92 +0,0 @@ -/************************************** - * writeperf.c - * - * Programme d'exemple d'utilisation de - * write - performances - * - *************************************/ -///AAA -#define _BSD_SOURCE // pour mkstemp - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <inttypes.h> -#include <stdbool.h> -#include <getopt.h> - - - -#define TESTSIZE 100000000 // 100 MB - -extern char *optarg; -extern int optind, opterr, optopt; - -void exit_on_error(char *s) { - perror(s); - exit(EXIT_FAILURE); -} - -void usage() { - printf("Usage : writeperf [-s] -l size\n"); - printf(" -s synchronisation des ecritures avec sync (defaut : off)\n"); - printf(" -l size taille des write en bytes (defaut : 10000)\n"); - exit(EXIT_FAILURE); -} - -int main (int argc, char *argv[]) { - int fd; - int err; - char **endptr=NULL; - - int c; - - int syncflag=false; - long size=10000; - - while ((c = getopt (argc, argv, "sl:")) != -1) { - switch (c) - { - case 's': - syncflag = true; - break; - case 'l': - size=strtol(optarg,endptr,10); - if(endptr!=NULL||size<0||size>(TESTSIZE/10)) - usage(); - break; - case 'h': - case '?': - usage(); - } - } - - void *mem=malloc(TESTSIZE); - char template[]="testperfXXXXXX"; - fd=mkstemp(template); - if(fd==-1) - exit_on_error("mkstemp"); - err=unlink(template); - if(err==-1) - exit_on_error("unlink"); - for(void *ptr=mem;ptr<mem+TESTSIZE;ptr=ptr+size) { - if( write(fd, (void *) ptr, size) == -1 ) - exit_on_error("write"); - if(syncflag) - sync(); - } - - err=close(fd); - if(err==-1){ - perror("close"); - exit(EXIT_FAILURE); - } - - return(EXIT_SUCCESS); -} -///BBB diff --git a/Exercices/Projets/P1/Makefile b/Exercices/Projets/P1/Makefile deleted file mode 100644 index c879091b9d52f16ca496df626c6e3e0e79f13a2e..0000000000000000000000000000000000000000 --- a/Exercices/Projets/P1/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -ARCHIVE=projet-1.tar.gz -SOURCES=$(wildcard src/*) - -all: $(ARCHIVE) - -$(ARCHIVE): $(SOURCES) - cd src && tar -pczf ../$@ * - -clean: - rm -f $(ARCHIVE) - -.PHONY: all clean \ No newline at end of file diff --git a/Exercices/Projets/P1/projet-1.rst.old b/Exercices/Projets/P1/projet-1.rst.old deleted file mode 100644 index 5a20627512d769e64181021c97db8d8c0d1a905a..0000000000000000000000000000000000000000 --- a/Exercices/Projets/P1/projet-1.rst.old +++ /dev/null @@ -1,43 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. _projet1: - -Premier Projet: Manipulation de bits ------------------------------------- - -On vous demande d'implémenter quelques fonctions de manipulation de bits. Dans -ce projet nous utiliserons une notation specifique pour représenter un nombre -non-signé de taille variable: ``struct bitstring``. Nous vous demandons de -définir vous même cette structure afin d'implémenter éfficacement les fonctions -déclarés dans le fichier :download:`/Projets/P1/src/bitstring.h` dans un -fichier ``bitstring.c``. Vous devez partir du code fourni dans l'archive -:download:`/Projets/P1/projet-1.tar.gz`. L'archive contient déjà un fichier -``test.c`` qui contient un exemple d'utilisation de la librarie CUnit (voir -:ref:`ref_cunit` pour installer la librarie). Vous devez bien entendu compléter -ce fichier pour la soumission. - -Ce projet sera évalué et comptera dans la note finale. Les critères de cotations (non-exhaustifs) sont les suivants: - - - Qualité du code (indentation, respect d'une convention, etc.); - - Commentaires; - - Tests de la valeur de retour des fonctions; - - Exhaustivité et qualité des tests; - - Gestion de la mémoire (efficacité, memory leak, etc.). - -Ce projet se fait par -groupes de deux et vous devez vous inscrire au SVN ``SINF1252_2013_P1`` sur le -site `<https://scm.info.ucl.ac.be/cgi-bin/inscription.sh>`_. Faites bien -attention à introduire aussi l'adresse mail de votre binôme lors de votre -inscription. Le projet doit être soumis avant lundi 4 mars 2013 à 23h55. Votre -dossier doit contenir **tous** les fichiers source nécessaires à la compilation -et l'utilisation de votre implémentation ainsi que les fonctions de test que -vous avez défini pour valider votre implémentation. Ces fichiers sont: - - - ``bitstring.h`` (non-modifée) - - ``bitstring.c`` - - ``test.c`` - - ``Makefile`` (non-modifiée) - - Ils doivent être placé sur le svn dans votre dossier ``grpXX``. diff --git a/Exercices/Projets/P1/projet-1.tar.gz b/Exercices/Projets/P1/projet-1.tar.gz deleted file mode 100644 index 7763a9feaddd0740e57ff41a5c5f4916ea8e2b3e..0000000000000000000000000000000000000000 Binary files a/Exercices/Projets/P1/projet-1.tar.gz and /dev/null differ diff --git a/Exercices/Projets/P1/src/Makefile b/Exercices/Projets/P1/src/Makefile deleted file mode 100644 index 2653f88fef17cb351663880bdaacaf09828a92e1..0000000000000000000000000000000000000000 --- a/Exercices/Projets/P1/src/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -TEST=test_bitstring -CFLAGS=-I$(HOME)/local/include -Wall -Werror -LDFLAGS=-L$(HOME)/local/lib -lcunit -SRC=$(wildcard *.c) -OBJ=$(SRC:.c=.o) - -all: test - -%.o: %.c - $(CC) $(CFLAGS) -c -o $@ $< - -$(TEST): $(OBJ) - $(CC) -o $@ $(OBJ) $(LDFLAGS) - -test: $(TEST) - @LD_LIBRARY_PATH=$(HOME)/local/lib ./$(TEST) - -.PHONY: exec test diff --git a/Exercices/Projets/P1/src/bitstring.c b/Exercices/Projets/P1/src/bitstring.c deleted file mode 100644 index 190f2a46067ca060c25126f86e7984463c7bb7a4..0000000000000000000000000000000000000000 --- a/Exercices/Projets/P1/src/bitstring.c +++ /dev/null @@ -1 +0,0 @@ -// A compléter \ No newline at end of file diff --git a/Exercices/Projets/P1/src/bitstring.h b/Exercices/Projets/P1/src/bitstring.h deleted file mode 100644 index e298e72577fe6cf82ae28f22eb75f2c911780509..0000000000000000000000000000000000000000 --- a/Exercices/Projets/P1/src/bitstring.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef __BITSTRING_H__ -#define __BITSTRING_H__ - -/* /!\ Fichier à ne pas changer */ - -#include <stdlib.h> - -struct bitstring; -/* A vous de définir votre structure dans bitstring.c */ - -typedef struct bitstring bitstring_t; -typedef enum { - BITNULL = 0, - BITSET = 1 -} bit_t; - -/* Alloue un bitstring de 'n' bits initialisés à 0. - * 'n' est un multiple de 8! - * - * En cas d'erreur, NULL est retourné. - */ -bitstring_t *bitstring_alloc(size_t n); - -/* Alloue un bitstring dont la séquence de bits représente 'x'. - * - * En cas d'erreur, NULL est retourné. - */ -bitstring_t *bitstring_alloc_from_int(unsigned int x); - -/* Met le n'ième bit du bitstring 'b' à la valeur de 'bit'. - * Pour trouver le n'ième bit on compte à partir du bit de poids fort. - * - * 'n' est plus grand ou égal à 0 et strictement plus petit que - * bitstring_len(b) - */ -void bitstring_set(bitstring_t *b, unsigned int n, bit_t bit); - -/* Retourne la valeur du n'ième bit du bitstring 'b' - * Pour trouver le n'ième bit on compte à partir du bit de poids fort. - * - * 'n' est plus grand ou égal à 0 et strictement plus petit que - * bitstring_len(b) - */ -bit_t bitstring_get(bitstring_t *b, int n); - -/* Renvoi la longueur du bitstring */ -size_t bitstring_len(bitstring_t *b); - -/* Applique une rotation vers la gauche de 'n' bits sur le bitstring - * 'b'. - * Par exemple, pour un b = 00111101 et n = 3, - * b deviendra 11101001 après l'appel à cette fonction. - */ -void bitstring_rotate(bitstring_t *b, int n); - -/* Concate les bitstrings de 'b1' et 'b2'. - * - * Le résultat est stocké dans 'b1'. - * - * Retourne 0 en cas de succès, -1 en cas d'erreur. - */ -int bitstring_concat(bitstring_t *b1, bitstring_t *b2); - -/* Effectue l'opération ou exclusif entre 'b1' et 'b2' - * (b1 ^ b2). - * - * Si les bitstring 'b1' et 'b2' sont de taille - * différente, une erreur est renvoyée. Sinon, le résultat est fourni à - * l'appellant via 'res'. 'b1' et 'b2' sont inchangés. - * - * La valeur de retour est 0 en cas de succès, -1 en cas d'erreur. - */ -int bitstring_xor(bitstring_t *b1, bitstring_t *b2, bitstring_t **res); - -/* Affiche en représentation hexadécimale le bitstring 'b' dans - * le buffer 'buf' de taille 'len'. - * Retourne -1 si le buffer ne peut contenir toute la representation. - * Retourne le nombre de caractères hexadécimals (+'\0') écrits sinon. - */ -int bitstring_print(bitstring_t *b, char *buf, size_t len); - -/* Libère la mémoire du bitstring */ -void bitstring_free(bitstring_t *b); - -#endif diff --git a/Exercices/Projets/P1/src/test.c b/Exercices/Projets/P1/src/test.c deleted file mode 100644 index b7c68b715403f521afe45a7a6933f02c64ab5cbe..0000000000000000000000000000000000000000 --- a/Exercices/Projets/P1/src/test.c +++ /dev/null @@ -1,171 +0,0 @@ -#include "bitstring.h" - -#include <stdio.h> -#include <string.h> -#include <CUnit/Basic.h> - -#define LEN 24 - -#define MY_CU_ASSERT(value, args...) do { \ - int __b__ = (value); \ - if(! __b__) printf(args); \ - CU_ASSERT_FATAL(__b__); \ -} while(0) - -/* Ptr vers les bitstring employés pour les tests */ -static bitstring_t * b; - -/* The suite initialization function. -* Returns zero on success, non-zero otherwise. -*/ -int init_suite1(void) { - /* code pour l'init de la suite de tests, alloc ou autre... */ - b = NULL; - return 0; /* elle marche tjrs */ -} - -/* The suite cleanup function. -* Returns zero on success, non-zero otherwise. -*/ -int clean_suite1(void) { - /* nettoyage des données employées par la suite : free, etc... */ - if(b) - bitstring_free(b); - return 0; -} - -/* Teste bitstring_alloc() */ -void testAlloc() { - int i; - b = bitstring_alloc(LEN); - - printf("\n"); - /* verif mémoire allouée */ - MY_CU_ASSERT(b != NULL, - "Erreur : Le ptr bitstring 'b' ne pointe vers aucune addresse" - " mémoire. Lui avez-vous alloué de la mémoire (malloc()) ?" - " Renvoyez-vous le bon pointeur ?\n"); - - MY_CU_ASSERT(bitstring_len(b) == LEN, - "Erreur : Le bitstring n'a pas la bonne longueur (en bits)." - " Avez-vous pensé à l'affecter à une variable de la structure après avoir" - " alloué la mémoire ? Il se peut que ce soit votre fonction 'bitstring_len()'" - " qui n'est pas correcte.\n"); - - for (i = 0; i < LEN; i++) { - MY_CU_ASSERT(bitstring_get(b, i) == 0, - "Erreur : Au moins un des bits du bitstring ne vaut pas 0. Assurez-vous" - " que l'espace mémoire pour les données du bitstring soit bien mis" - " à 0 après l'allocation. De plus, est-ce que bitstring_get est correcte?\n"); - } - - bitstring_free(b); - b = bitstring_alloc(18); /* 18 n'est pas multiple de 8 */ - - MY_CU_ASSERT(b == NULL, - "Erreur : Le ptr bitstring 'b' devrait être NULL car on a essayé de l'allouer" - " pour une longueur de 18 bits, ce qui n'est pas multiple de 8." - " Avez-vous pensé à vérifier que la longueur passée en paramètre" - " était bien un multiple de 8 avant d'allouer de la mémoire ?" - " Renvoyez-vous bien le ptr NULL si ce n'est pas un multiple de 8 ?\n"); - - bitstring_free(b); - b = NULL; - printf("\n\tVotre fonction 'bitstring_alloc()' a l'air correcte.\n"); - printf("\t"); -} - -/* Teste bitstring_set() */ -void testSet() { - int i; - int testbit = 19; - - b = bitstring_alloc(LEN); - - printf("\n"); - - printf("\tMise du bit %d à 1\n", testbit); - bitstring_set(b, testbit, 1); /*on met le bit testbit à 1*/ - - /* vérifie que tous les bits sont à 0 (ignore le testbit) */ - for(i = 0; i < LEN; ++i) { - if(i == testbit) - continue; - MY_CU_ASSERT(bitstring_get(b, i) == 0, - "Erreur : Impossible de tester la fonction 'bitstring_set()' car" - " votre fonction 'bitstring_get()' ou 'bitstring_alloc()' n'est pas correcte.\n"); - } - - /* vérifie que le bit testbit est bien à 1 */ - MY_CU_ASSERT(bitstring_get(b, testbit) == 1, - "Erreur : Tous les bits semblent être à 0 dans votre bitstring alors" - " que le n°%d (0 étant le premier) devrait être à 1. Le problème" - " peut venir de 'bitstring_set()', mais aussi de 'bitstring_get()'.\n", - testbit); - - - /* on assigne un autre bit dans le même octet pour voir si ça n'efface pas l'autre */ - printf("\tMise du bit %d à 1\n", testbit+2); - bitstring_set(b, testbit + 2, 1); - - /* revérifie tous les bits */ - /* intéressant uniquement si les étudiants codent 8 bits par octet, -mais ne devrait pas trigger dans le cas contraire */ - for(i = 0; i < LEN; ++i) { - if(i == testbit || i == testbit + 2) { - MY_CU_ASSERT(bitstring_get(b, i) == 1, - "Erreur : Affecter un seul bit fonctionne correctement, mais en" - " affecter un second dans le même octet semble effacer le premier (ou ne" - " pas affecter correctement le second). Vérifiez que vous ne mettez pas" - " tout l'octet à 0 avant d'y set un bit. (Il se peut aussi que ce soit du" - " à 'bitstring_get()')\n"); - } else { - MY_CU_ASSERT(bitstring_get(b, i) == 0, - "Erreur : Affecter un seul bit fonctionne correctement, mais en" - " affecter un second dans le même octet altère des bits qui ne devraient pas" - " l'être. (Il se peut aussi que ce soit dû à 'bitstring_get()')\n"); - } - } - - - /* Il faudrait éventuellement penser à ajouter un test sur le premier et dernier bit du bitstring, -pour voir s'il n'y a pas d'effet de bord : les numéros de bits allant de 0 à bitstring_len() − 1 */ - - /* succès */ - printf("\n\tVotre fonction 'bitstring_set()' a l'air correcte.\n"); - printf("\t"); -} - -/* The main() function for setting up and running the tests. -* Returns a CUE_SUCCESS on successful running, another -* CUnit error code on failure. -*/ -int main() -{ - CU_pSuite pSuite = NULL; - - /* initialize the CUnit test registry */ - if(CUE_SUCCESS != CU_initialize_registry()) - return CU_get_error(); - - /* add a suite to the registry */ - pSuite = CU_add_suite("Suite de tests pour bitstring", init_suite1, clean_suite1); - if(NULL == pSuite) { - CU_cleanup_registry(); - return CU_get_error(); - } - - /* add the tests to the suite */ - /* NOTE - ORDER IS IMPORTANT - first fct added = first to be run */ - if(NULL == CU_add_test(pSuite, "test de 'bitstring_alloc()'", testAlloc) || - NULL == CU_add_test(pSuite, "test de 'bitstring_set()'", testSet)) { - CU_cleanup_registry(); - return CU_get_error(); - } - - /* Run all tests using the CUnit Basic interface */ - CU_basic_set_mode(CU_BRM_SILENT); - CU_basic_run_tests(); - CU_cleanup_registry(); - return CU_get_error(); -} diff --git a/Exercices/Projets/P2/Makefile b/Exercices/Projets/P2/Makefile deleted file mode 100644 index 59a2c8411cc6116e65047befa4e2d2878c3de4b4..0000000000000000000000000000000000000000 --- a/Exercices/Projets/P2/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -ARCHIVE=projet-2.tar.gz -SOURCES=$(wildcard src/*) - -all: $(ARCHIVE) - -$(ARCHIVE): $(SOURCES) - cd src && tar -pczf ../$@ * - -clean: - rm -f $(ARCHIVE) - -.PHONY: all clean - diff --git a/Exercices/Projets/P2/enonce.rst.old b/Exercices/Projets/P2/enonce.rst.old deleted file mode 100644 index a329b59028dda90baf68970d375586d2012e1f60..0000000000000000000000000000000000000000 --- a/Exercices/Projets/P2/enonce.rst.old +++ /dev/null @@ -1,101 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Application de filtres sur des images -===================================== - -Une image numérique est composée de petits points appelée pixels. Chaque -pixel a une couleur bien spécifique qui est définie par 3 couleurs primaires: -le rouge, le vert et le bleu. Ces 3 couleurs primaires permettent de représenter, en les additionnants, un grand nombre de couleurs. - -Le format bitmap est un format de fichier pour stocker l'information sur les pixels -d'une image. C'est un format très simple qui utilise le format RGB pour chaque pixel. -Dans ce format, l'intensité de chacune des couleurs primaires d'un pixel est exprimé par un -entier sur 8 bits. Ces couleurs ont donc une valeur entre 0 et 255 avec 0 étant l'intensité -la plus faible (le noir) et 255 l'intensité la plus forte (le blanc). -Pour chaque pixel le format bitmap requiert donc -24 bits afin de stocker l'information nécessaire. - -Dans ce projet, vous allez combiner des filtres sur des images. Un filtre est une opération appliquée sur les pixels d'une image. Par exemple, dans ce projet, vous allez implémenter un filtre qui retire la composante rouge d'une -image en changeant son intensité à 0. - - -Programme attendu ------------------ - -On vous demande d'implémenter des filtres parallélisés sur les images bitmap. -Votre programme reçoit en argument un dossier contenant des fichiers bitmap, -une liste de filtres à appliquer et le nombre de threads utilisés par filtre. Votre programme doit se baser sur le code présent dans l'archive :download:`/Projets/P2/projet-2.tar.gz`. - -Plus en détails, votre programme doit supporter la ligne de commande suivante: - - .. code-block:: console - - $ ./filter -f filter1[,filter2[,...]] -t numThreads1[,numThreads2[,...]] input-folder output-folder - -L'option ''-f'' permet de spécifier les filtres et l'ordre dans lesquels ils sont appliqués sur chaque image. -La liste des filtres est la suivante: - - * ''red'' Filtre, qui enlève la composante 'rouge' de l'image. - * ''green'' Filtre, qui enlève la composante 'vert' de l'image (déjà fourni). - * ''blue'' Filtre, qui enlève la composante 'bleu' de l'image. - * ''grayscale'' Filtre, qui transforme l'image en niveau de gris. Le niveau du gris est calculé en mettant chaque couleur primaire du pixel égale à la moyenne des trois couleurs primaires. - * ''blur'' Filtre, qui ajoute un flou gaussien dans l'image. Voyez :download:`/Projets/P2/src/filter.h` pour plus d'informations sur ce filtre. - -Nous vous demandons également de définir et d'implémenter vous-mêmes un filtre. Ce filtre sera évalué en fonction de son originalité. Vous pouvez bien sûr vous baser sur des filtres déjà existants. Il est cependant interdit de copier/coller un code existant. - -L'option ''-t'' permet de spécifier le nombre de threads par filtre. Il y a donc toujours ''numThreads1'' threads pour le filtre ''filter1''. L'option ''-t'' doit avoir autant d'arguments que l'option ''-f''. - -Les arguments ''input-folder'' et ''output-folder'' fournissent au programme respectivement le dossier où les fichiers bitmap se trouvent et le dans lequel il faut écrire les images. Chaque image à la sortie aura le même nom et extension qu'à l'entrée. - -Voici un exemple d'utilisation du programme: - - .. code-block:: console - - $ ./filter -f red,blur,green -t 2,4,2 images/ out_images/ - - -API fournie ------------ - -Nous vous fournissons une API pour lire un fichier bitmap et écrire l'image dans le format bitmap. - - .. code-block:: c - - int load_bmp(char *file, struct image **res_image); - -''load_bmp'' charge l'image donnée par ''file'' et alloue une structure ''struct image'' qui représente l'image entière. Regardez :download:`/Projets/P2/src/bitmap.h` pour plus d'informations. - - .. code-block:: c - - int write_bmp(struct image *img, char *file); - -''write_bmp'' écrit l'image ''img'' dans le fichier dont le chemin est spécifié par ''file''. :download:`/Projets/P2/src/bitmap.h` fournit plus d'informations. - -Pour pouvoir tester votre programme, nous avons mis à votre disposition un ensemble d'images sur `<http://sinf1252.info.ucl.ac.be/data/images.tar.gz>`_ - -Séance intermédiaire --------------------- - -Afin d'au mieux vous aider dans vos choix de désign, nous organisons une séance intermédiaire *obligatoire*. Pour cela nous vous demandons d'écrire un petit rapport de *2 pages maximum* qui doit être présent sur le SVN du projet dans le votre dossier de groupe et doit se nommer *prerapport.pdf*. Ce pré-rapport doit être fourni avant le 14 mars à 23h55 et doit contenir la solution que vous comptez implémenter. Une discussion de maximum 10 minutes aura alors lieu avec les assistants du cours et sera organisée le 18 mars. Vous devez vous inscrire en indiquant votre numéro de groupe (du SVN) pour le projet (voir section suivante) sur le doodle: `<http://doodle.com/fskwhh22u56xxn5w>`_. - -Consignes ---------- - -Le projet est à soumettre pour le 17 avril à 12h00 via le SVN du deuxième projet. Vous devez donc vous inscrire ensemble avec votre binôme sur le SVN ''SINF1252_2013_PROJET_2'' sur le -site `<https://scm.info.ucl.ac.be/cgi-bin/inscription.sh>`_. -Vous devez fournir sur le SVN dans votre dossier de groupe: - - - Le code source de votre projet (pas de binaires) ainsi qu'un ``Makefile`` (lorsque l'on tape ``make`` un binaire ``filter`` doit être généré.). Vous devez compiler votre programme avec les options *-Wall* et *-Werror* de gcc. - - Un rapport de *4 pages maximum* (12pt) qui décrit vos choix architecturaux ainsi que les problèmes rencontrés. Le rapport doit être nommé *rapport.pdf* et présent dans votre dossier de groupe. - -Les critères de cotation sont les suivants (liste non-exhaustive): - - - Votre impémentation doît fonctionner dans les salles informatiques du département; - - Création et gestion des threads; - - Synchronisation des threads; - - Gestion de la mémoire; - - Implémentation des filtres; - - Respect des consignes. - diff --git a/Exercices/Projets/P2/projet-2.tar.gz b/Exercices/Projets/P2/projet-2.tar.gz deleted file mode 100644 index f4621e13a9489f90e025ca30ffb17b805766dd78..0000000000000000000000000000000000000000 Binary files a/Exercices/Projets/P2/projet-2.tar.gz and /dev/null differ diff --git a/Exercices/Projets/P2/src/bitmap.h b/Exercices/Projets/P2/src/bitmap.h deleted file mode 100644 index 0f787e635ae87f93a6ef28dde7765b3fa2581e88..0000000000000000000000000000000000000000 --- a/Exercices/Projets/P2/src/bitmap.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef BITMAP_H -#define BITMAP_H - -struct pixel { - unsigned char b; /* Bleu */ - unsigned char g; /* Vert */ - unsigned char r; /* Rouge */ -} __attribute__((packed)); - -struct image { - int width; /* Largeur en pixels */ - int height; /* Hauteur en pixels */ - - int hor_res; /* Résolution horizontale - Ne pas modifier */ - int ver_res; /* Résolution verticale - Ne pas modifier */ - - /* pixel est un tableu de taille width * height et représente les composantes - * RGB de tous les pixels. Le pixel (0,0) est le pixel en bas à gauche et - * le pixel (width-1, height-1) est celui en haut à droite. - */ - struct pixel *pixels; -} __attribute__((packed)); - -/* Charge le bitmap spécifié par 'file' dans la nouvelle image 'res_image'. - * - * Si la fonction retourne 0 (succès), *res_image pointe vers une nouvelle - * zone mémoire allouée contenant le bitmap. Si la fonction retourne une - * une valeur différente de zero, une erreur s'est produite et la valeur - * errno est mis à jour. - */ -int load_bmp(char *file, struct image **res_image); - -/* Ecrit le bitmap spécifié par 'img' dans le fichier nomé 'file'. - * - * Si l'écriture est réussie, 0 est renvoyé. Lors d'une erreur, une valeur - * différente de zero est renvoyée et errno est mis à jour. - */ -int write_bmp(struct image *img, char *file); - -#endif diff --git a/Exercices/Projets/P2/src/bitmapio.c b/Exercices/Projets/P2/src/bitmapio.c deleted file mode 100644 index 69210a1b903201eb26c9462b90b9ce383128fb61..0000000000000000000000000000000000000000 --- a/Exercices/Projets/P2/src/bitmapio.c +++ /dev/null @@ -1,184 +0,0 @@ -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include "bitmap.h" - -struct bitmap_file_header { - char id[2]; - u_int32_t size; - char reserved[4]; - u_int32_t offset; -} __attribute__((packed)); - -struct bitmap_info_header { - u_int32_t hdrsize; - int32_t width; - int32_t height; - int16_t color_planes; /* Must be 1 */ - int16_t bits_per_pixel; /* We only support 24 */ - u_int32_t compression; /* We only support '0' */ - u_int32_t bitmap_size; - u_int32_t hor_res; - u_int32_t ver_res; - u_int32_t num_colors; - u_int32_t important_colors; -} __attribute__((packed)); - -static u_int32_t power(a, b) -{ - int i; - int res = 1; - for (i = 0; i < b ; i++) - res *= a; - - return res; -} - -int load_bmp(char *file, struct image **res_image) -{ - FILE *fp; - struct bitmap_file_header hdr; - struct bitmap_info_header infohdr; - struct image *img; - int num_pixels; - int j, pad; - - - if (!res_image) { - printf("**res_image pointer to pointer is not initialized!!!\n"); - errno = -EAGAIN; - return -EAGAIN; - } - - img = (struct image *) malloc(sizeof(*img)); - if (!img) - return errno; - - *res_image = img; - - /* open the file */ - if ((fp = fopen(file,"r")) == NULL) - return errno; - - /* Read bitmap header */ - if (fread(&hdr, sizeof(hdr), 1, fp) != 1) - goto error; - - /* Check format */ - if (hdr.id[0] != 'B' || hdr.id[1] != 'M') { - printf("%s is not a bitmap file in windows-format.\n", file); - errno = -EAGAIN; - goto error; - } - - /* Read bitmap info header */ - if (fread(&infohdr, sizeof(infohdr), 1, fp) != 1) - goto error; - - if (infohdr.color_planes != 1 || infohdr.bits_per_pixel != 24 || - infohdr.compression != 0 || infohdr.num_colors != 0 || - infohdr.important_colors != 0) { - printf("The bmp image is not in a supported format!\n"); - printf("The supported format requires: colorplanes == 0, 24 bits per " - "pixel, no compression, num-colors == 0 and important-colors == 0\n"); - printf("But we got: colorplanes %u bits per pixel %u compression %u " - "num-colors %u important-colors %u\n", infohdr.color_planes, - infohdr.bits_per_pixel, infohdr.compression, infohdr.num_colors, - infohdr.important_colors); - errno = -EAGAIN; - goto error; - } - - if (infohdr.num_colors == 0) - /* This means, the number of colors in the color-pallette is 2**bits_per_pixel */ - infohdr.num_colors = power(2, infohdr.bits_per_pixel); - - img->width = infohdr.width; - img->height = infohdr.height; - img->hor_res = infohdr.hor_res; - img->ver_res = infohdr.ver_res; - - /* Now, move the pointer to the pixel-array */ - if (fseek(fp, infohdr.hdrsize - sizeof(infohdr), SEEK_CUR)) - goto error; - - num_pixels = img->width * img->height; - img->pixels = (struct pixel *) malloc(sizeof(struct pixel)*num_pixels); - - if (!img->pixels) - goto error; - - pad = (4 - (img->width * 3) % 4) % 4; - for (j = 0; j < img->height; j++) { - if (fread(&img->pixels[j*img->width], 3, img->width, fp) != img->width) - goto error; - - if (fseek(fp, pad, SEEK_CUR)) - goto error; - } - - fclose(fp); - return 0; - -error: - fclose(fp); - return errno; -} - -int write_bmp(struct image *img, char *file) -{ - FILE *fp; - struct bitmap_file_header hdr; - struct bitmap_info_header infohdr; - int num_pixels = img->width * img->height; - int j, pad; - struct pixel padding = {0,0,0}; - - - /* open the file */ - if ((fp = fopen(file,"w")) == NULL) - return errno; - - hdr.id[0] = 'B'; - hdr.id[1] = 'M'; - hdr.size = sizeof(hdr) + sizeof(infohdr) + num_pixels * 3; - hdr.reserved[0] = 0; - hdr.reserved[1] = 0; - hdr.reserved[2] = 0; - hdr.reserved[3] = 0; - hdr.offset = sizeof(hdr) + sizeof(infohdr); - - if (fwrite(&hdr, sizeof(hdr), 1, fp) != 1) - goto write_error; - - infohdr.hdrsize = sizeof(infohdr); - infohdr.width = img->width; - infohdr.height = img->height; - infohdr.color_planes = 1; - infohdr.bits_per_pixel = 24; - infohdr.compression = 0; - infohdr.bitmap_size = num_pixels * 3; - infohdr.num_colors = 0; - infohdr.hor_res = img->hor_res; - infohdr.ver_res = img->ver_res; - infohdr.important_colors = 0; - - if (fwrite(&infohdr, sizeof(infohdr), 1, fp) != 1) - goto write_error; - - pad = (4 - (img->width * 3) % 4) % 4; - for (j = 0; j < img->height; j++) { - if (fwrite(&img->pixels[j*img->width], 3, img->width, fp) != img->width) - goto write_error; - - if (fwrite(&padding, 1, pad, fp) != pad) - goto write_error; - } - - fclose(fp); - return 0; - -write_error: - fclose(fp); - return errno; -} diff --git a/Exercices/Projets/P2/src/filter.h b/Exercices/Projets/P2/src/filter.h deleted file mode 100644 index 444a50cd11bb722dfee49c77fa169cb50bb1612e..0000000000000000000000000000000000000000 --- a/Exercices/Projets/P2/src/filter.h +++ /dev/null @@ -1,54 +0,0 @@ -#include "bitmap.h" - -/* Signature de fonction pour les filtres. - * Chaque filtre prend une image en argument et - * lui applique une opération. Retourne 0 en cas - * de succès, -1 sinon. - */ -typedef int(filter_t)(struct image *); - -/* Retire la composante rouge de l'image */ -filter_t filter_red; - -/* Retire la composante verte de l'image */ -filter_t filter_green; - -/* Retire la composante bleue de l'image */ -filter_t filter_blue; - -/* Transforme l'image en niveau de gris en calculant - * la moyenne sur les différentes composantes. - */ -filter_t filter_grayscale; - -/* Ajoute de flou gaussien dans l'image en utilisant la - * matrice carrée de taille 3 comme matrice de poids: - * 0.0 0.2 0.0 - * 0.2 0.2 0.2 - * 0.0 0.2 0.0 - * - * Si on considère la composante rouge de l'image suivante - * (chaque element a une valeur entre 0 et 255) de taille - * 6x5: - * - * 1 2 5 2 0 3 - * ------- - * 3 |2 5 1| 6 0 0.0*2 + 0.2*5 + 0.0*1 + - * | | - * 4 |3 6 2| 1 4 -> 0.2*3 + 0.2*6 + 0.2*2 + -> 3.2 - * | | - * 0 |4 0 3| 4 2 0.0*4 + 0.2*0 + 0.0*3 - * ------- - * 9 6 5 0 3 9 - * - * La nouvelle valeur du pixel (3, 4) devient round(3.2) = 3. - * - * Lorsque les élements de la matrice se retrouvent en dehors - * de l'image (c'est-à -dire pour les pixels à la bordure de l'image), - * la valeur du pixel central sera utilisé pour les valeurs des pixels - * en dehors des limites de l'image. C'est-à -dire, la nouvelle valeur - * du pixel (0, 0) dans l'image précédente sera: - * 0.2 * 0 + 0.2 * 9 + 0.2 * 6 + 0.2 * 9 + 0.2 * 9 = 6.6 -> 7 - */ -filter_t filter_blur; - diff --git a/Exercices/Projets/P2/src/filters.c b/Exercices/Projets/P2/src/filters.c deleted file mode 100644 index 167fb90c1633ad17b6269609c3e9f3695fbc92b0..0000000000000000000000000000000000000000 --- a/Exercices/Projets/P2/src/filters.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "filter.h" -#include <stdio.h> - -int filter_green(struct image *img) -{ - int x, y; - for (x = 0; x < img->width; ++x) { - for (y = 0; y < img->height; y++) - img->pixels[x + y * img->width].g = 0; - } - - return 0; -} - -/* TODO implémenter les filtres */ diff --git a/Exercices/Projets/P2/src/main.c b/Exercices/Projets/P2/src/main.c deleted file mode 100644 index 6043247637b44ec025c62334ed460b722e0be031..0000000000000000000000000000000000000000 --- a/Exercices/Projets/P2/src/main.c +++ /dev/null @@ -1,28 +0,0 @@ -#include <stdio.h> -#include "bitmap.h" -#include "filter.h" - -/* Exemple d'utilisation des fonctions fournies. - * Vous devez impérativement changer le code ci-dessous. - */ -int main(int argc, char *argv[]) -{ - struct image *img; - - if (load_bmp(argv[1], &img)) { - perror("Error calling load_bmp"); - return 1; - } - - if (filter_green(img)) { - perror("Error calling filter_green"); - return 1; - } - - if (write_bmp(img, argv[2])) { - perror("Error calling write_bmp"); - return 1; - } - - return 0; -} diff --git a/Exercices/Projets/P3/enonce.rst.old b/Exercices/Projets/P3/enonce.rst.old deleted file mode 100644 index 6745442ca6c885e00db8f396a066e8f1087db068..0000000000000000000000000000000000000000 --- a/Exercices/Projets/P3/enonce.rst.old +++ /dev/null @@ -1,86 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Implémentation d'un encodeur et extension de l'outil `cat(1)`_ -============================================================== - -Le monde de l'informatique est fortement influencé par la mentalité "Open Source". Par exemple, les systèmes GNU/Linux sont basés sur ce genre d'outils. Le but de l'open source est d'ouvrir l'accès au code source des programmes et permettre à tout le monde de le modifier par rapport à ses besoins. - -Pour ce dernier projet du cours SINF1252 on vous demande d'étendre la librairie open source: *GNU core utilities* ou ``coreutils``. Le package ``coreutils`` contient tout les programmes nécessaire à la gestion de votre système, comme `kill(1)`_, `cp(1)`_, `tail(1)`_, et beaucoup d'autres. - -Programme attendu ------------------ - -On vous demande d'implémenter un outil de compression de fichier dans la librairie ``coreutils`` ainsi qu'étendre l'outil `cat(1)`_ (qui fait partie de ``coreutils``) pour qu'il puisse lire ce type de fichiers. De plus, on vous demande de modifier `cat(1)`_ pour qu'il utilise des fichier mappé en mémoire (`mmap(2)`_). On vous demande également d'utiliser `mmap(2)`_ dans votre encodeur. - -L'encodeur est donc un nouveau binaire que vous devriez intégrer dans le package ``coreutils``. Son utilisation est défini comme suit: - - .. code-block:: console - - $ encode input-file output-file - -L'outil ``encode`` lit le fichier ``input-file``, le compresse avec l'algorithme de "Run-length encoding" et écrit la version compressée dans le fichier ``output-file``. Pour avoir des informations sur l'algorithme, voyez la section ci-dessous. - -Pour le décodage, vous devez étendre l'outil `cat(1)`_ avec l'option ``-x``. Cette option (qui ne prend pas d'argument), spécifie que l'input doît être interprété comme étant un fichier créé par l'outil ``encode``. - -N'oubliez pas d'adapter le Makefile, les manpages dans le dossier ``man`` de la librairie ``coreutils``. - -Run-length encoding -------------------- - -Le run-length encoding est un algorithme de compression de fichier qui essaye de profiter du fait que le même caractère se répète plusieurs fois, pour réduire la taille d'un fichier. Le run-length encoding est donc une suite de octets, dont le premier est identifié comme étant le ``length``. Ce dernier est un entier non-signé sur 8 bits avec la signification suivante: - - * si ``length <= 128``, le byte suivant est repété ``length`` fois. - * si ``length > 128``, les ``length - 128`` octets suivant ne sont pas repèté. - -Voici un exemple sur un fichier contenant du texte: - - * ``aaaabcdaaaa`` peut être encodé de la façon suivant: Le premier octet est mis à '4', suivi par un 'a'. Ensuite, on encode un '131' sur un octet suivi de la séquence 'bcd'. Cela signifie donc que les 131 - 128 = 3 octets suivant le '131' ne sont pas répété. Ensuite vous pouvez de nouveau encoder un '4', suivi par un 'a'. - -Vous êtes libre à décider si dans votre encodage vous utilisez un ``length`` plus grand que 128, ou pas. Cela a une forte influence sur le taux de compression de l'encodeur. - -Compilation de coreutils ------------------------- - -Vous pouvez récupérer le code source de ``coreutils`` en suivant le lien `<http://ftp.gnu.org/gnu/coreutils/coreutils-8.21.tar.xz>`_. - -Pour l'extraire, vous exécutez la commande `tar(1)`_: - - .. code-block:: console - - $ tar -xJf coreutils-8.21.tar.xz - -Les différents outils et leur code-source se trouvent dans le dossier ``src``. Les manpages sont dans le dossier ``man``. - -Pour compiler, suivez les étapes suivantes dans le dossier ``coreutils-8.21``: - - .. code-block:: console - - $ ./configure - $ make - -Les binaires vont se trouver dans le dossier ``src``. - - -Consignes ---------- - -Le projet est à soumettre pour le jeudi 16 mai à 23h55 via le SVN du troisième projet. Vous devez donc vous inscrire ensemble avec votre binôme sur le SVN ''SINF1252_2013_P3'' sur le -site `<https://scm.info.ucl.ac.be/cgi-bin/inscription.sh>`_. -Vous devez fournir sur le SVN dans votre dossier de groupe: - - - Le code source de votre projet (pas de binaires). Les codes sources doivent se trouver dans le répertoire *grpXY/coreutils-8.21/*. Il doit être possible pour les assistants du cours de générer un patch de vos changements à l'aide de la commande: ``diff -rNu grpXY/coreutils-8.21/ <source_originale_de_coreutils>``. Cette commande doit uniquement retourner vos changements. - - - Un rapport de *2 pages maximum* (12pt) qui décrit vos choix de design ainsi que les problèmes rencontrés. Le rapport doit être nommé *rapport.pdf* et présent dans votre dossier de groupe (*grpXY/rapport.pdf*). - -Les critères de cotation sont les suivants (liste non-exhaustive): - - - Votre impémentation doit fonctionner dans les salles informatiques du département; - - Intégration de vos changements dans l'infrastructure de coreutils; - - L'appel à ``make`` génère correctement un binaire ``src/encode`` (sans warning ni erreurs). - - Intégralité de votre implémentation (manpages, ...); - - Optimalité de votre algorithme d'encodage; - - Respect des consignes; - - ... - diff --git a/Exercices/QCM/S1/Makefile b/Exercices/QCM/S1/Makefile deleted file mode 100755 index 89160a7ca54290262ca3a25d73aca04e0469d41b..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S1/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -#################################################################### -# -# Makefile for SINF1252 QCM -# OB, Jan 2013 -# -#################################################################### - -MISSION=1 - -DEST=../../../web/qcm - -EXNAME=$(DEST)/Mission-$(MISSION)-qcm.html - -RST_FILES=qcm-$(MISSION).rst - -CSS=../rst-form/css/html4css1.css,../rst-form/css/rst-form.css,../rst-form/css/pygments.css - -.PHONY : qcm all - -qcm: $(EXNAME) - -$(EXNAME): $(RST_FILES) - @for i in $(RST_FILES); do\ - ( rst2html.py --stylesheet-path=$(CSS) $$i > $(EXNAME) ; ) ; done - -all: qcm - -clean: - -rm -r $(EXNAME) diff --git a/Exercices/QCM/S1/qcm-1.rst b/Exercices/QCM/S1/qcm-1.rst deleted file mode 100644 index 4048656d04940972f28438a70688b4b36dda83dc..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S1/qcm-1.rst +++ /dev/null @@ -1,309 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. raw:: html - - <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script> - <script type="text/javascript" src="js/jquery-shuffle.js"></script> - <script type="text/javascript" src="js/rst-form.js"></script> - <script type="text/javascript">$nmbr_prop = 4</script> - - -========================= -Mission 1 : Mise en Route -========================= - -Ces questions ont pour objectif de vous permettre de tester vous-même votre compréhension de la matière couverte par cette mission de mise en route. - -Ces questions supposent que vous avez lu le premier chapitre du syllabus contenant l'introduction à Unix et au langage C. - - -Question 1. Commande `man(1)`_ ------------------------------- - -La commande `man(1)`_ permet de lire les pages de manuel d'un système Unix. Elle est particulièrement utile pour vérifier les arguments à donner à un programme en ligne de commande ou pour savoir comment utiliser certaines fonctions de la librairie standard ou appels systèmes. Comment faut-il appeler la commande `man(1)`_ pour lister toutes les pages de manuel dont le résumé contient le mot ''intro'' ? - -.. class:: positive - -- - .. code:: console - - man -k intro - - -.. class:: negative - -- - .. code:: console - - man intro - - .. class:: comment - - Cette commande permet d'obtenir la page dénommée ``intro`` mais uniquement dans la première section du manuel. Elle ne liste pas toutes les pages dont le résumé contient le mot clé ``intro``. - -- - .. code:: console - - man -k *intro* - - .. class:: comment - - Par défaut, lorsque vous passez un argument tel que ``*intro*`` en ligne de commande, le shell va tenter de remplacer ``*intro*`` par tous les noms de fichiers du répertoire courant qui contiennent l'expression régulière qui commence par n'importe quelle suite de caractères, contient ``intro`` et se termine par n'importe quelle suite de caractères. Si le répertoire dans lequel vous exécutez cette commande contient les fichiers ``intro.txt`` et ``intro.dat``, ``man`` recevra ces deux noms de fichiers comme arguments. - -Question 2. Commande `ls(1)`_ ------------------------------ - -La commande `ls(1)`_ permet de lister le contenu d'un répertoire. Elle supporte de nombreux paramètres. Parmi les groupes d'affirmation suivants, un seul est valide, lequel ? - -.. class:: positive - -- - - Dans un répertoire, la commande ``ls -a`` sans argument permet d'afficher la liste de tous les fichiers et répertoires présents - - La commande ``ls -r`` permet de lister les répertoires présents dans le répertoire courant en inversant l'ordre - - La commande ``ls -l`` permet d'obtenir la liste détaillée du contenu du répertoire courant avec toutes les informations relatives à chaque fichier et répertoire non cachés - - -- - - Dans un répertoire, la commande ``ls -a`` sans argument permet d'afficher la liste de tous les fichiers et répertoires présents - - La commande ``ls -R`` permet de lister de façon récursive le contenu du répertoire courant et de ses sous-répertoires - - La commande ``ls -l`` permet d'obtenir la liste détaillée du contenu du répertoire courant avec toutes les informations relatives à chaque fichier et répertoire non cachés - - -.. class:: negative - -- - - Dans un répertoire, la commande ``ls *`` permet d'afficher la liste de tous les fichiers et répertoires présents - - La commande ``ls -f`` permet de lister le contenu du répertoire courant sans trier les fichiers par nom - - La commande ``ls -l`` permet d'obtenir la liste détaillée du contenu du répertoire courant avec toutes les informations relatives à chaque fichier et répertoire - - .. class:: comment - - Relisez la page de manuel de `ls(1)`_. Sous Unix, le shell va remplacer ``*`` par l'ensemble des fichiers présents dans le répertoire courant - -- - - Dans un répertoire, l'appel à `ls(1)`_ sans argument permet d'afficher la liste de tous les fichiers et répertoires présents - - La commande ``ls -r`` permet de lister de façon récursive le contenu du répertoire courant et de ses sous-répertoires - - La commande ``ls -l`` permet d'obtenir la liste détaillée du contenu du répertoire courant avec toutes les informations relatives à chaque fichier et répertoire - - .. class:: comment - - Relisez la page de manuel de `ls(1)`_. Sous Unix, l'appel à `ls(1)`_ sans argument dans le shell affichera l'ensemble des fichiers présents dans le répertoire courant - - - -Question 3. Premier programme en langage C ------------------------------------------- - -Depuis la publication du livre de référence [KernighanRitchie1998], le premier programme écrit en langage C affiche à l'écran la chaîne de caractères "Hello, world". Parmi les codes source ci-dessous, un seul est entièrement correct. Lequel ? - - -.. class:: positive - -- - .. code:: c - - #include <stdio.h> - int main(int argc, const char *argv[]) { - printf("Hello, world\n"); - } - -- - .. code:: c - - #include <stdio.h> - int main(int argc, const char *argv[]) { - printf("Hello,"); - printf(" world\n"); - } - -.. class:: negative - -- - .. code:: c - - #include <stdio.h> - void main(int argc, const char *argv[]) { - printf("Hello, world\n"); - } - - - .. class:: comment - - En C, contrairement à Java, la fonction ``main`` retourne une valeur de type ``int``. - -- - .. code:: c - - int main(int argc, const char *argv[]) { - printf("Hello, world\n"); - } - - - .. class:: comment - - La fonction `printf(3)`_ utilisée par ce programme fait partie de la librairie standard de gestion des I/O. Pour l'utiliser, il faut inclure le header `stdio.h`_. Même si certains compilateurs pouvaient l'inclure par défaut, il est préférable de spécifier ce header explicitement. - -- - .. code:: c - - #include <stdlib.h> - int main() { - printf("Hello, world\n"); - } - - - .. class:: comment - - En C, la signature de la fonction ``main`` est ``int main(int argc, const char *argv[])`` même si certains compilateurs peuvent être tolérants. `printf(3)`_ est défini via `stdio.h`_ et non `stdlib.h`_. - -- - .. code:: c - - #include <stdlib.h> - void main() - printf("Hello, world\n"); - } - - - .. class:: comment - - En C, la signature de la fonction ``main`` est ``int main(int argc, const char *argv[])`` même si certains compilateurs peuvent être tolérants. `printf(3)`_ est défini via `stdio.h`_ et non `stdlib.h`_. - - -Question 4. Deuxième programme en langage C --------------------------------------------- - -Votre deuxième programme en langage C doit afficher à l'écran la chaîne de caractères `SINF1252`. Lequel parmi les programmes ci-dessous affiche-t-il correctement cette chaîne de caractères ? - -.. class:: positive - -- - .. code:: c - - #include <stdio.h> - int main(int argc, const char *argv[]) { - int a = 1252; - printf("SINF%d\n", a); - } - - .. class:: comment - - En C, la fonction `printf(3)`_ prend un nombre variable d'arguments. Le premier est toujours une spécification de formatage qui indique la chaîne de caractères à afficher. Les autres arguments sont des identifiants de variables dont les valeurs seront utilisées pour construire la chaîne de caractères à afficher. Le deuxième argument remplace le premier format `%d`, le troisième argument le deuxième format, etc. La page de manuel de `printf(3)`_ fournit de nombreux détails sur le fonctionnement de cette fonction qui accepte de nombreux paramètres. - -- - .. code:: c - - #include <stdio.h> - int main(int argc, const char *argv[]) { - int a = 1252; - printf("SINF"); - printf("%d\n", a); - } - - .. class:: comment - - En C, la fonction `printf(3)`_ prend un nombre variable d'arguments. Le premier est toujours une spécification de formatage qui indique la chaîne de caractères à afficher. Les autres arguments sont des identifiants de variables dont les valeurs seront utilisées pour construire la chaîne de caractères à afficher. Le deuxième argument remplace le premier format `%d`, le troisième argument le deuxième format, etc. La page de manuel de `printf(3)`_ fournit de nombreux détails sur le fonctionnement de cette fonction qui accepte de nombreux paramètres. - -.. class:: negative - -- - .. code:: c - - #include <stdio.h> - int main(int argc, const char *argv[]) { - int a = 1252; - printf("SINF%a\n", a); - } - - .. class:: comment - - Dans la fonction `printf(3)`_, ``%a`` est utilisé lorsque l'on veut placer dans une chaîne de caractères un nombre réel en notation hexadécimale. Dans ce cas, ``a`` étant un entier, il aurait fallu utiliser ``%d``. - -- - .. code:: c - - #include <stdio.h> - int main(int argc, const char *argv[]) { - int a = 1252; - printf(SINF); - printf(%d\n, a); - } - - .. class:: comment - - En C, une chaîne de caractères (ou un descripteur de format pour `printf(3)`_ qui est aussi une chaîne de caractères) commence et se termine par le caractère ``"``. - -- - .. code:: c - - #include <stdio.h> - int main(int argc, const char *argv[]) { - int a = 1252; - printf("SINF$a\n", a); - } - - .. class:: comment - - Dans la fonction `printf(3)`_ en C, et contrairement à d'autres langages, le caractère ``$`` ne joue pas de rôle particulier. Le programme ci-dessus affichera donc simplement ``SINF$a`` à l'écran. - - -Question 5. Arguments passés à un programme C ------------------------------------------------ - -Considérons le programme C ci-dessous qui permet de manipuler les arguments passés en ligne de commande. - - .. code-block:: c - - #include <stdio.h> - #include <stdlib.h> - int main(int argc, const char *argv[]) - { - int a = atoi(argv[1]); - printf("%d\n", a); - } - -Parmi les groupes d'affirmations ci-dessous, un seul ne contient que des affirmations qui sont toutes vraies. Lequel ? - - -.. class:: positive - -- - - - Lors de l'exécution de la fonction ``main``, ``argc`` est initialisé au nombre d'arguments passés au programme (y compris le nom de l'exécutable lui-même). - - Lors de l'exécution de la fonction ``main``, le tableau ``argv[]`` contient dans ```argv[0]`` le nom du programme, dans ``argv[1]`` le premier argument, etc. - - La fonction ``atoi`` permet de convertir une chaîne de caractères en l'entier équivalent. - - -.. class:: negative - -- - - Lors de l'exécution de la fonction ``main``, ``argc`` est initialisé à zéro. - - Lors de l'exécution de la fonction ``main``, le tableau ``argv[]`` contient dans ``argv[0]`` le premier argument, dans ``argv[1]`` le second argument, etc. - - La fonction ``atoi`` calcule la taille de son argument. - - .. class:: comment - - Les trois affirmations sont fausses. ``argc`` sera toujours initialisé à un vu que le nom du programme est toujours passé en argument. Le premier élément du tableau ``argv[]``, ``argv[0]``, est le nom du programme qui est exécuté. Enfin, la fonction ``atoi`` permet de convertir une chaîne de caractères en l'entier équivalent. - -- - - Lors de l'exécution de la fonction ``main``, ``argc`` est le nombre maximum d'arguments que l'on peut lui passer. - - Lors de l'exécution de la fonction ``main``, le tableau ``argv[]`` contient dans ``argv[0]`` le premier argument, dans ``argv[1]`` le second argument, etc. - - La fonction ``atoi`` doit prendre comme argument une chaîne de caractères qui ne contient que des chiffres. - - .. class:: comment - - Les deux premières affirmations sont fausses. ``argc`` contient le nombre d'arguments passés effectivement au programme. Le premier élément du tableau ``argv[]``, ``argv[0]``, est le nom du programme qui est exécuté. - -- - - Lors de l'exécution de la fonction ``main``, le tableau ``argv[]`` contient dans ```argv[0]`` le premier argument, dans ``argv[1]`` le second argument, etc. - - La fonction ``atoi`` permet de convertir une chaîne de caractères en l'entier équivalent. - - .. class:: comment - - Le premier élément du tableau ``argv[]``, ``argv[0]``, est le nom du programme qui est exécuté. - -.. include:: ../../../links.rst -.. include:: ../../../man_links.rst -.. include:: ../../../incl_links.rst diff --git a/Exercices/QCM/S11/Makefile b/Exercices/QCM/S11/Makefile deleted file mode 100755 index f22d6ec2586c4904cf9527b6cc4028adac63bf65..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S11/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -#################################################################### -# -# Makefile for SINF1252 QCM -# OB, Jan 2013 -# -#################################################################### - -MISSION=11 - -EXNAME=../../../web/qcm/Mission-$(MISSION)-qcm.html - -RST_FILES=qcm-$(MISSION).rst - -CSS=../rst-form/css/html4css1.css,../rst-form/css/rst-form.css,../rst-form/css/pygments.css - -.PHONY : qcm all - -qcm: $(EXNAME) - -$(EXNAME): $(RST_FILES) - @for i in $(RST_FILES); do\ - ( rst2html.py --stylesheet-path=$(CSS) $$i > $(EXNAME) ; ) ; done - - -all: qcm - -clean: - -rm -r $(EXNAME) diff --git a/Exercices/QCM/S11/qcm-11.rst b/Exercices/QCM/S11/qcm-11.rst deleted file mode 100644 index 86ca74c92e69b5dbd0c9d21c7db7fce7244199a1..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S11/qcm-11.rst +++ /dev/null @@ -1,259 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2014 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_ -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. raw:: html - - <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script> - <script type="text/javascript" src="js/jquery-shuffle.js"></script> - <script type="text/javascript" src="js/rst-form.js"></script> - <script type="text/javascript" src="js/prettify.js"></script> - <script type="text/javascript">$nmbr_prop = 4</script> - - -=============== -Onzième semaine -=============== - - -La matière couverte cette semaine porte sur la mémoire virtuelle. - -Question 1. Taille d'une page ------------------------------ - -Laquelle des tailles ci-dessous correspond à une taille courante pour une page en mémoire virtuelle ? - -.. class:: positive - -- 4096 bytes - - -- 4 KBytes - - -.. class:: negative - -- 4 bytes - -- 32 bits - -- 512 bytes - -- 4096 bits - -- 32 KBytes - -- 4 MBytes - -- 4 Kbits - - -Question 2. Table des pages ---------------------------- - -Un ordinateur expérimental utilise une table des pages à un seul niveau. Parmi les affirmations suivantes relatives au nombre d'entrées dans la table des pages, une seule est valide. Laquelle ? - -.. class:: positive - -- Si l'ordinateur utilise des adresses virtuelles sur 30 bits et des pages de 4 KBytes, alors la table des pages contient :math:`2^18` entrées - -- Si l'ordinateur utilise des adresses virtuelles sur 30 bits et des pages de 1 KByte, alors la table des pages contient :math:`2^20` entrées - - -.. class:: negative - -- Si l'ordinateur utilise des adresses virtuelles sur 32 bits et des pages de 4 KBytes, alors la table des pages contient :math:`2^18` entrées - -- Si l'ordinateur utilise des adresses virtuelles sur 30 bits et des pages de 1 KByte, alors la table des pages contient :math:`2^18` entrées - -- Si l'ordinateur utilise des adresses virtuelles sur 34 bits et des pages de 1 KByte, alors la table des pages contient :math:`2^18` entrées - -- Si l'ordinateur utilise des adresses virtuelles sur 32 bits et des pages de 1 KByte, alors la table des pages contient :math:`2^20` entrées - - -Question 3. Bit de validité ---------------------------- - -Parmi les affirmations suivantes relatives au bit de validité utilisé dans la mémoire virtuelle, une seule est vraie. Laquelle - -.. class:: positive - -- lorsque le bit de validité d'une entrée de la table des pages est 'vrai', cela indique que la page correspondante se trouve en mémoire RAM - -- Seules les pages dont le bit de validité est 'vrai' se trouvent en mémoire RAM - -.. class:: negative - -- il y a un seul bit de validité pour une table des pages - - .. class:: comment - - Il y a un bit de validité par entrée de la table des pages - -- le bit de validité est mis à 'faux' lorsqu'une donnée se trouvant dans une page est modifiée - -- le bit de validité est toujours mis à 'vrai' dans la table des pages - -- le bit de validité est mis à 'vrai' à chaque accès à une donnée se trouvant dans une page - -Question 4. Création et suppression de pages --------------------------------------------- - -Durant l'exécution d'un processus, certains événements peuvent provoquer la création de nouvelles pages en mémoire. Parmi les opérations ci-dessous, laquelle ne provoque surement pas la création de nouvelles pages en mémoire : - -.. class:: positive - -- l'exécution de `free(3)`_ - -- l'exécution de `waitpid(2)`_ - -.. class:: negative - -- l'exécution de l'appel système `fork(2)`_ - -- l'exécution de l'appel système `execve(2)`_ - -- l'appel récursif à une fonction - -- l'exécution de `malloc(3)`_ - -- la création d'un thread via la librairie POSIX - - - -Question 5. Bits de contrôle ----------------------------- - - -Chaque entrée de la table des pages contient plusieurs bits de contrôles relatifs à chaque page : - - - bit de validité - - bit de modification - - bit de reference - -Considérons une mémoire virtuelle composée de 8 pages, numérotées de 0 à 7 par simplicité. Au démarrage du programme, les pages 0, 1, 2 et 7 sont utilisées. Les pages 0 à 3 contiennent les instructions du programme et la page 7 contient la pile. Les bits de modification et de référence sont remis à zéro puis le programme exécute les opérations suivantes : - - - modification (via des instructions se trouvant en page 1) d'une variable globale stockée dans la page 2 - - appel à une fonction qui alloue un tableau nécessitant 2 pages sur la pile. Les instructions de la fonction sont dans la page 1. - -Après exécution de ce programme, quels sont les bits de contrôle de la table des pages ? - -.. class:: positive - -- - - bit de validité vrai pour les pages 0, 1, 2, 5, 6 et 7 - - bit de modification vrai pour les pages 2, 5, 6 et 7 - - bit de référence vrai pour les pages 1, 2, 5, 6 - - -.. class:: negative - -- - - bit de validité vrai pour les pages 0, 1, 2, 3, 4, 5, 6 et 7 - - bit de modification vrai pour les pages 2, 5, 6 et 7 - - bit de référence vrai pour les pages 1, 2, 5, 6, 7 - -- - - bit de validité vrai pour les pages 5, 6 et 7 - - bit de modification vrai pour les pages 5, 6 et 7 - - bit de référence vrai pour les pages 5, 6 - - -- - - bit de validité vrai pour les pages 0, 1, et 2 - - bit de modification vrai pour les pages 5, 6 et 7 - - bit de référence vrai pour les pages 1, 2 - - -Question 5. Bits de contrôle ----------------------------- - -Parmi les affirmations suivantes, une seule est vraie. Laquelle - -.. class:: positive - -- Si lors d'un accès à la mémoire le bit de modification est mis à vrai, alors le bit de référence est aussi mis à vrai - -.. class:: negative - -- Si lors d'un accès à la mémoire le bit de référence est mis à vrai, alors le bit de modification est aussi mis à vrai - -- Si lors d'un accès à la mémoire le bit de validité est mis à vrai, alors le bit de modification est aussi mis à vrai - -- Si lors d'un accès à la mémoire le bit de validité est mis à vrai, alors le bit de référence est aussi mis à vrai - - - -Question 6. Bits de permissions -------------------------------- - -Parmi les affirmations suivantes, une seule est correcte. Laquelle ? - -.. class:: positive - -- Les pages contenant le code d'un programme ont `R-X` comme permissions tandis que les pages contenant le heap et le stack ont `RW-` comme permissions - -- Les pages contenant le heap et le stack ont `RW-` comme permissions tandis que les pages contenant le code ont `R-X` comme permissions - -.. class:: negative - -- Toutes les pages d'un programme doivent nécessairement avoir `RWX` comme permissions - -- Toutes les pages de la pile d'un programme doivent nécessairement avoir `-WX` comme permissions - -- Les pages de la pile d'un programme ont toujours `-W-` comme permissions - -- Les pages contenant le code d'un programme ont toujours `--X` comme permissions - - -Question 7. Bits de contrôle ----------------------------- - -Parmi les affirmations suivantes relatives à l'exécution d'instruction en assembleur, une seule est correcte. Laquelle ? - -.. class:: positive - -- l'exécution de ``mov %ecx, 0x12345678`` provoque la modification de deux bits de référence et un bit de modification - -- l'exécution de ``mov 4(%eax), %ecx`` provoque la modification de deux bits de référence et un bit de modification - -.. class:: negative - -- l'exécution de ``mov %ecx, 0x8765412`` provoque la modification d'un bit de référence et un bit de modification - -- l'exécution de ``mov 8(%eax), %ebx`` provoque la modification d'un bit de référence et un bit de modification - -- l'exécution de ``mov 8(%eax), %ebx`` provoque la modification de deux bits de référence et deux bits de modification - -- l'exécution de ``add %eax, %ebx`` provoque la modification d'un bit de référence et un bit de modification - -- l'exécution de ``j label`` provoque la modification de deux bits de référence - -Question 8. TLB ---------------- - -Parmi les affirmations suivantes relatives au fonctionnement du TLB, une seule est correcte. Laquelle ? - -.. class:: positive - -- lors d'un accès en écriture à une page, les bits de modification et de référence sont mis à jour dans le TLB mais pas dans la table des pages - -- lors d'un accès en lecture à une page, le bit de référence est mis à jour dans le TLB mais pas dans la table des pages - -.. class:: negative - -- les bits de contrôle stockés dans le TLB pour la page `p` sont toujours identiques aux bits de contrôle de la même page dans la table des pages - - .. class:: comment - - Les bits de contrôle stockés dans le TLB sont mis à jour à chaque accès à une page sans passer par la table des pages. Ils ne sont mis à jour dans la table des pages que lorsque l'entrée correspondant à une page retourne dans la table des pages. - -- lors d'un accès en écriture à une page, les bits de modification et de référence sont mis à jour dans le TLB et dans la table des pages - -- lors d'un accès en lecture à une page, le bit de référence est mis à jour dans le TLB et dans la table des pages - - - -.. include:: ../../../links.rst -.. include:: ../../../man_links.rst -.. include:: ../../../incl_links.rst diff --git a/Exercices/QCM/S2/Makefile b/Exercices/QCM/S2/Makefile deleted file mode 100755 index 0b569938e4c75a3be9c015199ba68b3b3922eae3..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S2/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -#################################################################### -# -# Makefile for SINF1252 QCM -# OB, Jan 2013 -# -#################################################################### - -MISSION=2 - -DEST=../../../web/qcm - -EXNAME=$(DEST)/Mission-$(MISSION)-qcm.html - -RST_FILES=qcm-$(MISSION).rst - -CSS=../rst-form/css/html4css1.css,../rst-form/css/rst-form.css,../rst-form/css/pygments.css - -.PHONY : qcm all - -qcm: $(EXNAME) - -$(EXNAME): $(RST_FILES) - @for i in $(RST_FILES); do\ - ( rst2html.py --stylesheet-path=$(CSS) $$i > $(EXNAME) ; ) ; done - -all: qcm - -clean: - -rm -r $(EXNAME) diff --git a/Exercices/QCM/S2/qcm-2.rst b/Exercices/QCM/S2/qcm-2.rst deleted file mode 100644 index d7de148864e733fa49c09d9b8e3fc1459e58fdc9..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S2/qcm-2.rst +++ /dev/null @@ -1,819 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. raw:: html - - <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script> - <script type="text/javascript" src="js/jquery-shuffle.js"></script> - <script type="text/javascript" src="js/rst-form.js"></script> - <script type="text/javascript" src="js/prettify.js"></script> - <script type="text/javascript">$nmbr_prop = 3</script> - - -============================ -Semaine 2 : Types de données -============================ - -La matière couverte cette semaine la section relative aux `types de données <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/C/datatypes.html>`_ (jusque et y compris la section relative aux `expressions de manipulation de bits <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/C/datatypes.html#les-expressions-de-manipulation-de-bits>`_ - - -Question 1. Conversion de types -------------------------------- - -En C tout comme dans des langages comme Java, il est possible de convertir des nombres d'un type primitif vers un autre. Cependant, alors que le compilateur Java vérifie si la conversion est sans risque, le compilateur C ne fait aucune vérification et suppose que si le programmeur a effectué une conversion explicite entre types, il a pris ses précautions. Sur une architecture où les types de données sont stockés comme suit : - -.. code:: c - - // char 1 octet(s) - // unsigned char 1 octet(s) - // short 2 octet(s) - // unsigned short 2 octet(s) - // int 4 octet(s) - // unsigned int 4 octet(s) - - - int i; - short s; - long l; - char c; - unsigned int ui; - unsigned char uc; - unsigned long ul; - unsigned short us; - -Un seul des fragments de code ci-dessous contient des conversions de type qui sont sans risque. Lequel ? - -.. class:: positive - -- - .. code:: c - - i=(int ) s; - s=(short) uc; - l=(long )i; - -- - .. code:: c - - ui=(unsigned int) us; - s=(short) c; - ul=(unsigned long )ui; - - -.. class:: negative - -- - .. code:: c - - ui=(unsigned int ) s; - us=(unsigned short) uc; - l=(long )i; - - .. class:: comment - - Si ``s`` est négatif, la conversion en ``unsigned int`` risque de poser problème. - - -- - .. code:: c - - i=(int ) us; - us=(unsigned short) i; - l=(long )c; - - .. class:: comment - - La conversion d'un ``int`` en un ``unsigned short`` risque de poser problème. - -- - .. code:: c - - ui=(unsigned int) s; - s=(short) c; - ul=(unsigned long )ui; - - .. class:: comment - - La première conversion risque de poser des problèmes. - -Question 2. Notation hexadécimale ---------------------------------- - -Parmi les affirmations suivantes relatives aux nombres en représentation hexadécimale, une seule est vraie. Laquelle ? - -.. class:: positive - -- La représentation hexadécimale du nombre entier positif ``27`` est ``1B`` - -- La représentation hexadécimale du nombre entier positif ``67`` est ``43`` - -.. class:: negative - -- La représentation hexadécimale du nombre entier positif ``67`` est ``34`` - - .. class:: comment - - :math:`3*16+4` ne vaut pas ``67`` - - -- La représentation hexadécimale du nombre entier positif ``27`` est ``B1`` - - .. class:: comment - - :math:`11*16+1` ne vaut pas ``27`` - -- La représentation hexadécimale du nombre entier positif ``62`` est ``B1`` - - .. class:: comment - - :math:`11*16+1` ne vaut pas ``62`` - -- La représentation hexadécimale du nombre entier positif ``128`` est ``FF`` - - .. class:: comment - - :math:`15*16+15` ne vaut pas ``128`` - - -Question 3. Notation binaire ----------------------------- - -Parmi les affirmations suivantes relatives aux nombres en représentation binaire, une seule est vraie. Laquelle ? - - -.. class:: positive - -- La représentation binaire du nombre entier positif ``99`` est ``1100011`` - -- La représentation binaire du nombre entier positif ``176`` est ``10110000`` - -.. class:: negative - -- La représentation binaire du nombre entier positif ``90`` est ``1100011`` - - .. class:: comment - - La représentation binaire de ``90`` est ``1011010`` - -- La représentation binaire du nombre entier positif ``176`` est ``10110001`` - - .. class:: comment - - C'est la représentation de ``177``. - -- La représentation binaire du nombre entier positif ``166`` est ``10110001`` - - .. class:: comment - - C'est la représentation de ``177``. - -- La représentation binaire d'un nombre entier positif impair a toujours ``0`` comme bit de poids faible. - - .. class:: comment - - Ce sont les entiers positifs pairs (et zéro) qui ont ``0`` comme bit de poids faible. - - -Question 4. Notation binaire ----------------------------- - -Parmi les affirmations suivantes relatives aux nombres signés en représentation binaire, une seule est vraie. Laquelle ? - - -.. class:: positive - -- Si la variable ``x`` est un ``short`` (signé) sur 16 bits, alors la représentation binaire de ``-17`` est ``11111111 11101111`` - -- Si la variable ``x`` est un ``short`` (signé) sur 16 bits, alors la représentation binaire de ``-23`` est ``11111111 11101001`` - -.. class:: negative - -- Si la variable ``x`` est un ``short`` (signé) sur 16 bits, alors la représentation binaire de ``-17`` est ``00000000 00010001`` - - .. class:: comment - - C'est la représentation de ``17`` mais en non-signé - - -- Si la variable ``x`` est un ``short`` (signé) sur 16 bits, alors la représentation binaire de ``-17`` est ``10000000 00010001`` - - .. class:: comment - - C'est la représentation de ``-32751`` - -- Si la variable ``x`` est un ``short`` (signé) sur 16 bits, alors la représentation binaire de ``-23`` est ``00000000 00010111`` - - - .. class:: comment - - C'est la représentation de ``23`` - - -- Si la variable ``x`` est un ``short`` (signé) sur 16 bits, alors la représentation binaire de ``-23`` est ``11111111 11100110`` - - - .. class:: comment - - C'est la représentation de ``-26`` - - -.. http://www.binaryconvert.com/ pour des conversions sur le web - - - -Question 5. Manipulations de bits ---------------------------------- - - -Si la variable ``c`` est de type ``unsigned char`` sur 8 bits, laquelle des suites d'instructions ci-dessous permet d'en échanger les 4 bits de poids faible avec les 4 bits de poids fort ? - - -.. class:: positive - -- - .. code:: c - - unsigned char temp1, temp2; - temp1 = c & 0x0F; - temp2 = c & 0xF0; - temp1=temp1 << 4; - temp2=temp2 >> 4; - c= temp2|temp1; - -- - .. code:: c - - unsigned char temp1, temp2; - temp1=c << 4; - temp2=c >> 4; - c= temp2|temp1; - - -.. class:: negative - -- - .. code:: c - - unsigned char temp1, temp2; - temp1=c << 4; - temp2=c >> 4; - c= temp2||temp1; - - - .. class:: comment - - Ne confondez pas l'opérateur binaire ``|`` avec la disjonction logique ``||``. - - -- - .. code:: c - - unsigned char temp1, temp2; - temp1=4 << temp1; - temp2=4 >> temp2; - c= temp2|temp1; - - - .. class:: comment - - Cette utilisation de l'opérateur ``>>`` est incorrecte. Vous décalez de ``temp1`` bits (c'est-à -dire 0) la représentation binaire de ``4``. - -- - .. code:: c - - unsigned char temp1, temp2; - temp1 = c && 0x0F; - temp2 = c && 0xF0; - temp1=temp1 << 4; - temp2=temp2 >> 4; - c= temp2|temp1; - - - .. class:: comment - - Ne confondez pas la l'opérateur binaire ``&`` avec la conjonction logique ``&&``. - - -Question 6. Multiplication entière ----------------------------------- - - -Parmi les expressions suivantes, une seule permet de calculer ``x*7`` lorsque ``x`` est un nombre entier. Laquelle ? - - -.. class:: positive - -- - .. code:: c - - (x<<3)-x - - - .. class:: comment - - Cette expression calcule en effet ``x<<3=x*8`` puis retire ``x``. - -.. class:: negative - -- - .. code:: c - - (x>>3)-x - - - .. class:: comment - - Cette expression divise d'abord ``x`` par ``8`` puis retire x au résultat de cette division. - -- - .. code:: c - - (x<<3)+x - - .. class:: comment - - Cette expression multiplie ``x`` par ``8`` puis ajoute ``x`` au résultat. Elle multiple donc ``x`` par ``9``. - - -- - .. code:: c - - (x<<7) - - - .. class:: comment - - Cette expression multiplie ``x`` par :math:`2^7` - - -- - .. code:: c - - (x>>7) - - - .. class:: comment - - Cette expression divise ``x`` par :math:`2^7` - -Question 7. Extraction de bits ------------------------------- - - -Il est parfois nécessaire en C de manipuler directement la représentation binaire d'un nombre. Si ``f`` est un nombre de type ``float`` stocké sur 32 bits, laquelle des expressions ci-dessous peut-elle être intégrée dans ce code pour afficher positif ou négatif en fonction du signe de ce nombre ? - -.. code:: c - - if(<à compléter>) - printf("positif\n"); - else - printf("negatif\n"); - - -.. class:: positive - -- - .. code:: c - - !(((unsigned int) f) & 0x80000000) - -- - .. code:: c - - !(((unsigned int) f) >> 31) - -.. class:: negative - -- - .. code:: c - - !(((unsigned int) f) & 0x10000000) - - .. class:: comment - - En faisant ``& 0x10000000``, vous mettez tous les bits de ``f`` à ``0`` sauf le bit ``28`` alors que le bit de signe est le bit de poids fort (``31``). - -- - .. code:: c - - !(((unsigned int) f) << 31) - - .. class:: comment - - Cette opération décale la représentation binaire de ``f`` de 31 bits vers la gauche, c'est-à -dire que seul le bit de poids faible reste. Malheureusement, le signe se trouve dans le bit de poids faible et non dans le bit de poids fort. - - -- - .. code:: c - - !(((unsigned int) f) > 31) - - .. class:: comment - - Ne confondez pas ``>`` et ``>>``. - - -- - .. code:: c - - !(((unsigned int) f) & 31) - - .. class:: comment - - Cette opération masque le nombre ``f`` avec ``00000000 00000000 00000000 00011111`` - - - -Question 8. Chaînes de caractères ---------------------------------- - -Une seule des fonctions ci-dessous retourne correctement le nombre d'occurrences du caractère ``c`` dans la chaîne de caractères ``c``. Laquelle ? - -.. class:: positive - -- - .. code:: c - - int count1(char *s, char c) { - int i=0; - int count=0; - while(*(s+i)!='\0') { - if(*(s+i)==c) { - count++; - } - i++; - } - return(count); - } - - -- - .. code:: c - - int count(char *s, char c) { - int count=0; - while(*(s)!='\0') { - if(*(s)==c) { - count++; - } - s++; - } - return(count); - } - - -.. class:: negative - - -- - .. code:: c - - int count1(char *s, char c) { - int i=0; - int count=0; - while(i<s.length) { - if(*(s+i)==c) { - count++; - } - i++; - } - return(count); - } - - .. class:: comment - - ``s`` est un pointeur vers une chaînes de caractères et non une structure. Ce code ne compile pas. - -- - .. code:: c - - int count1(char *s, char c) { - int i=0; - int count=0; - while(*s!='\0') { - if(*(s+i)==c) { - count++; - } - i++; - } - return(count); - } - - .. class:: comment - - La boucle ``while`` se termine-t-elle ? Quelle est sa condition d'arrêt ? - -- - .. code:: c - - int count(char *s, char c) { - int count=0; - while(*(s)!='\0') { - s++; - if(*(s)==c) { - count++; - } - } - return(count); - } - - .. class:: comment - - Ce code compte-il correctement le caractère si il est présent en première position de la chaîne ? - - -- - .. code:: c - - int count(char *s, char c) { - int count=0; - while(s!='\0') { - if(s==c) { - count++; - } - s++; - } - return(count); - } - - .. class:: comment - - Ce code compare le pointeur ``s`` c'est-à -dire *l'adresse* du première caractère de la chaîne ``s`` en mémoire avec ``\0`` et ``c`` et non le caractère pointé par ``s``. - - -Question 9. Pointeurs ---------------------- - -Si ``ptr`` a été déclaré sous la forme ``int *ptr``, un seul des groupes d'affirmations suivantes est vrai, lequel ? - -.. class:: positive - -- - - l'expression ``*(ptr + 1)`` est une valeur entière - - l'expression ``ptr[1]`` est une valeur entière - - l'expression ``ptr`` est une adresse en mémoire - - -- - - l'expression ``*(ptr) + 1`` est une valeur entière - - l'expression ``ptr[2]`` est une valeur entière - - l'expression ``ptr++`` est une adresse en mémoire - - -.. class:: negative - -- - - l'expression ``&(ptr) + 1`` est un nombre entier - - l'expression ``ptr[2]`` est une valeur entière - - l'expression ``&ptr`` est une adresse en mémoire - -- - - l'expression ``*(ptr+1)==ptr[1]`` est syntaxiquement invalide - - l'expression ``ptr[2]`` est une valeur entière - - l'expression ``&ptr`` est une adresse en mémoire - -- - - l'expression ``*(ptr+1)==ptr[1]`` est toujours vraie - - l'expression ``ptr--`` est syntaxiquement invalide - - -Question 10. Pointeurs et tableaux ----------------------------------- - -Considérons le tableau ``tab`` déclaré comme suit : - - .. code:: c - - #define SIZE 30 - int tab[SIZE]; - int *ptr; - -Dans une architecture 32 bits, un seul des groupes d'affirmations ci-dessous est vrai. Lequel ? - - -.. class:: positive - -- - - l'expression ``tab[i]`` correspond à la même valeur dans le tableau que ``*(tab+i)`` lorsque ``0<=i<29`` - - l'assignation ``ptr=(tab+i)`` est valide et après cette assignation, ``*ptr`` retourne la même valeur que ``tab[i]`` lorsque ``0<=i<29`` - - -- - - l'expression ``tab[0]`` correspond à la même valeur dans le tableau que ``*(tab)`` - - l'assignation ``ptr=(tab+i)`` est valide et après cette assignation, ``*ptr`` retourne la même valeur que ``tab[i]`` lorsque ``0<=i<29`` - - -.. class:: negative - -- - - l'expression ``tab[i]`` correspond à la même valeur dans le tableau que ``*(tab+i)`` lorsque ``0<=i<29`` - - l'assignation ``tab=(tab+i)`` est valide et après cette assignation, ``*tab`` retourne le ième élément du tableau lorsque ``0<=i<29`` - - .. class:: comment - - Lorsque ``tab`` est déclaré comme étant un tableau, il est interdit de modifier sa valeur. - -- - - l'expression ``tab[0]`` correspond à la même valeur dans le tableau que ``&(tab)`` - - l'assignation ``tab=(tab+i)`` est valide et après cette assignation, ``*tab`` retourne le ième élément du tableau lorsque ``0<=i<29`` - - .. class:: comment - - Les deux affirmations sont fausses. - -- - - l'expression ``tab[i]`` correspond à la même valeur dans le tableau que ``*(tab)+i`` lorsque ``0<=i<29`` - - l'assignation ``ptr=(tab)`` est valide et après cette assignation, ``*(ptr+i)`` retourne le ième élément du tableau lorsque ``0<=i<29`` - - .. class:: comment - - La première affirmation est fausse, ``*(tab)+i`` équivaut à ``tab[0]+i`` - - -Question 11. Pointeurs ----------------------- - -Considérons le fragment de code ci-dessous. - -.. code:: c - - int tab[]={ 10, 20, 30, 40 }; - int *ptr1=&tab[1]; - int *ptr2=&tab[3]; - -Dans ce code, une seule des affirmations suivantes est vraie, laquelle ? - -.. class:: positive - -- l'expression ``ptr2-ptr1`` vaut ``2`` - -- les expressions ``*(ptr1-1)`` et ``*(ptr2-3)`` retournent toutes les deux la même valeur, ``10`` - -.. class:: negative - -- l'expression ``ptr2-ptr1`` vaut ``20`` - - .. class:: comment - - ``ptr2`` et ``ptr1`` sont des pointeurs vers des entiers. L'arithmétique des pointeurs s'applique pour cette opération. Vu leur initialisation, la différence vaut ``2``. - -- les expressions ``*(ptr1-1)`` et ``*(ptr2-3)`` retournent toutes les deux la même valeur, ``1`` - - .. class:: comment - - L'expression ``*(ptr1-1)`` équivaut à ``tab[0]`` et ``*(ptr2-3)`` à ``tab[0]``. Cet élément du tableau contient la valeur ``10``. - -- l'expression ``*(ptr2-ptr1)`` retourne la valeur ``20`` - - .. class:: comment - - ``ptr2`` et ``ptr1`` sont des pointeurs vers des entiers. L'arithmétique des pointeurs s'applique pour cette opération. Vu leur initialisation, la différence vaut ``2``. L'expression ``*(2)`` correspond à une donnée à une adresse dans le bas de la mémoire qui n'est normalement pas accessible au programme. - - - -Question 12. Pointeurs et fonctions ------------------------------------ - -En C, il est parfois nécessaire d'échanger le contenu de deux variables. Si ``a`` et ``b`` sont des variables de type ``int``, laquelle des fonctions ci-dessous permet de réaliser cette échange entre les contenu des variables ? - - -.. class:: positive - -- - .. code:: c - - void swap(int *i, int *j) { - int k; - k=*i; - *i=*j; - *j=k; - } - //échange - swap(&a,&b); - - -- - .. code:: c - - void swap(int *i, int *j) { - int k; - k=*j; - *j=*i; - *i=k; - } - //échange - swap(&a,&b); - -.. class:: negative - -- - .. code:: c - - void swap(int i, int j) { - int k; - k=i; - i=j; - j=k; - } - //échange - swap(a,b); - - .. class:: comment - - Cette fonction ne fait rien du tout d'utile. - -- - .. code:: c - - void swap(int i, int j) { - int k; - k=i; - i=j; - } - //échange - swap(&a,&b); - - .. class:: comment - - Cette fonction reçoit comme argument l'adresse de ``a`` et l'adresse de ``b`` mais ne modifie en rien le contenu de ces variables. - -- - .. code:: c - - void swap(int i, int j) { - int k; - int *i_ptr=&i; - int *j_ptr=&j; - k=i; - *(i_ptr)=j; - *(j_ptr)=k; - } - //échange - swap(a,b); - - .. class:: comment - - Lors de son exécution, la fonction ``swap`` ci-dessus reçoit les valeurs des variables ``a`` et ``b``, mais elle n'a aucune idée de l'endroit où ces variables sont stockées en mémoire. Elle ne peut donc pas modifier leur contenu. - -Question 13. Pointeurs et structures ------------------------------------- - - -Dans un programme de manipulation de fractions, on définit la structure suivante pour représenter une fraction entière : - - .. code:: c - - struct fract_t { - int num; - int denum; - }; - - On veut pouvoir facilement écrire une fonction de type ``void`` qui remplace la valeur stockée dans la fraction par le résultat de l'addition de la fraction et un nombre entier passé en fragment. La spécification de cette fonction pourrait être : - - .. code:: c - - /* - * augmente la fraction passé en argument de l'entier n et place - * la somme calculée dans la fraction - * Exemples - * Si f vaut 1/3, alors l'application de la fonction avec f et 2 comme - * arguments a comme résultat de stocker la valeur 7/3 dans f - * Si f vaut 2/1, alors l'application de la fonction avec f et 1 comme - * arguments a comme résultat de stocker la valeur 3/1 dans f - */ - - -Laquelle des signatures ci-dessous peut-elle être utilisée pour effectuer cette opération et modifier la fraction passé en argument ? - - -.. class:: positive - - -- - .. code:: c - - void scale(struct fract_t *f, int s); - // appel à la fonction : - // scale(&f,3); - -.. class:: negative - -- - .. code:: c - - void scale(struct fract_t f, int s); - // appel à la fonction : - // scale(f,3); -- - .. code:: c - - void scale(int num, int den, int s); - // appel à la fonction : - // scale(f.num, f.denum,3); - - - -.. include:: ../../../links.rst -.. include:: ../../../man_links.rst -.. include:: ../../../incl_links.rst diff --git a/Exercices/QCM/S2/src/charcount.c b/Exercices/QCM/S2/src/charcount.c deleted file mode 100644 index 5078502274d9cc5b4c3e74e50c81934413fa7342..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S2/src/charcount.c +++ /dev/null @@ -1,43 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int count1(char *s, char c) { - int i=0; - int count=0; - while(*(s+i)!='\0') { - if(*(s+i)==c) { - count++; - } - i++; - } - return(count); -} - - -int count2(char *s, char c) { - int count=0; - while(*(s)!='\0') { - if(*(s)==c) { - count++; - } - s++; - } - return(count); -} - - - -int main() { - - char* s1="absbbbsba"; - char* s2="xbbsjjjqiz"; - printf("%s -> %d\n",s1,count1(s1,'a')); - printf("%s -> %d\n",s2,count1(s2,'a')); - - printf("%s -> %d\n",s1,count2(s1,'a')); - printf("%s -> %d\n",s2,count2(s2,'a')); - - -} - - diff --git a/Exercices/QCM/S2/src/conversion.c b/Exercices/QCM/S2/src/conversion.c deleted file mode 100644 index 308daf6cf72fa59f50979237c5d0eae3b455fff5..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S2/src/conversion.c +++ /dev/null @@ -1,27 +0,0 @@ -// Conversion entre types de données - -#include <stdio.h> - -int main() { - - #define SIZE 5 - int tab[]={1,-7, 1025,234567890, -2345678901}; - - - int i; - - for(i=0; i<SIZE;i++) { - int n=tab[i]; - short s=(short) n; - long l=(long) n; - unsigned int ui=(unsigned int) n; - unsigned char uc=(unsigned char) n; - unsigned long ul=(unsigned long) n; - unsigned short us=(unsigned short) n; - printf("%d -> %d (short) %ld (long) %d (unsigned int) %d (unsigned char) %ld (unsigned long) %d (unsigned short)\n",n,s,l,ui,uc,ul,us); - } - - - -} - diff --git a/Exercices/QCM/S3/Makefile b/Exercices/QCM/S3/Makefile deleted file mode 100755 index 5fee1a14740e52d023c2c230f163f97ec5b7bb4f..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S3/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -#################################################################### -# -# Makefile for SINF1252 QCM -# OB, Jan 2013 -# -#################################################################### - -MISSION=3 - -DEST=../../../web/qcm - -EXNAME=$(DEST)/Mission-$(MISSION)-qcm.html - -RST_FILES=qcm-$(MISSION).rst - -CSS=../rst-form/css/html4css1.css,../rst-form/css/rst-form.css,../rst-form/css/pygments.css - -.PHONY : qcm all - -qcm: $(EXNAME) - -$(EXNAME): $(RST_FILES) - @for i in $(RST_FILES); do\ - ( rst2html.py --stylesheet-path=$(CSS) $$i > $(EXNAME) ; ) ; done - -all: qcm - -clean: - -rm -r $(EXNAME) diff --git a/Exercices/QCM/S3/qcm-3.rst b/Exercices/QCM/S3/qcm-3.rst deleted file mode 100644 index 42b20c0a535877a30d03f3493747ce006ccf3506..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S3/qcm-3.rst +++ /dev/null @@ -1,590 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. raw:: html - - <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script> - <script type="text/javascript" src="js/jquery-shuffle.js"></script> - <script type="text/javascript" src="js/rst-form.js"></script> - <script type="text/javascript" src="js/prettify.js"></script> - <script type="text/javascript">$nmbr_prop = 3</script> - - - -================= -Troisième semaine -================= - -Cette semaine, la matière porte sur l'organisation de la mémoire et l'utilisation des fonctions `malloc(3)`_ et `free(3)`_ - - - http://sites.uclouvain.be/SystInfo/notes/Theorie/html/C/malloc.html#organisation-de-la-memoire - - - -Question 1. Portée des variables --------------------------------- - -Lorsque l'on écrit un programme C, il est préférable d'éviter d'avoir deux variables qui ont le même nom et peuvent être utilisées dans une fonction. Un étudiant a écrit le programme ci-dessous : - - .. code-block:: c - - #include <stdio.h> - int i = 1; - int main(int argc, char * argv[]) - { - int k; - printf("A:%d\n", i); - for(k=0; k<1; k++) - { - int i = 2, j = 1252; - printf("B:%d %d\n", i, j); - { - int i = 0; - printf("C:%d %d\n", i, j); - } - printf("D:%d\n", i); - } - return 0; - } - -Lors de son exécution, ce programme affiche : - -.. class:: positive - -- - .. code-block:: console - - A:1 - B:2 1252 - C:0 1252 - D:2 - - -.. class:: negative - -- Le programme ne se compile pas, il est interdit de redéfinir la variable globale ``i``. - - .. class:: comment - - On peut redéfinir une variable dans plusieurs niveaux de portée différents, même si il vaut mieux l'éviter. - -- - .. code-block:: console - - A:1 - B:1 1252 - C:1 1252 - D:1 - -- - .. code-block:: console - - A:1 - B:2 1252 - C:2 1252 - D:2 - -- - .. code-block:: console - - A:1 - B:2 1252 - C:0 1252 - D:0 - -Question 2. Portée des variables --------------------------------- - -L'extrait ci-dessous provient d'un programme écrit par un étudiant. - - .. code-block:: c - - #include <stdio.h> - int i = 1252; - void f(int i) { - // code non fourni - } - void g(char* c) { - // code non fourni - } - int main(int argc, char * argv[]) - { - f(argc); - g(argv[0]); - } - -Parmi les affirmations suivantes, un seul groupe est correct. Lequel ? - -.. class:: positive - -- - - La fonction ``g`` peut accéder à la variable globale ``i`` et modifier sa valeur - - La fonction ``g`` ne peut lire la valeur de ``argc`` - - La fonction ``f`` ne peut modifier la valeur de la variable globale ``i`` - -.. class:: negative - -- - - La fonction ``g`` peut lire la variable globale ``i`` mais pas modifier sa valeur - - La fonction ``g`` ne peut lire la valeur de ``argc`` - - La fonction ``f`` peut modifier la valeur de la variable globale ``i`` - - .. class:: comment - - La fonction ``g`` peut accéder à la variable globale ``i`` et modifier sa valeur par contre la fonction ``f`` ne peut pas le faire car elle ne peut accéder qu'à son argument nommé également ``i``. - - -- - - La fonction ``f`` peut lire la variable globale ``i`` mais pas modifier sa valeur - - La fonction ``g`` peut lire la valeur de ``argc`` - - La fonction ``f`` peut modifier la valeur de la variable globale ``i`` - - .. class:: comment - - Aucune de ces affirmations n'est vraie - - -- - - La fonction ``f`` peut lire la variable globale ``i`` et modifier sa valeur - - La fonction ``g`` ne peut lire la valeur de ``argc`` - - La fonction ``f`` ne peut modifier la valeur de la variable globale ``i`` - - .. class:: comment - - La fonction ``f`` n'a pas accès à la variable globale ``i``. - - - -Question 3. Organisation de la mémoire --------------------------------------- - -Considérons le fragment de programme ci-dessous. - - .. code-block:: c - - #include <stdio.h> - int i,j,k = 1252; // ligne A - int tab[1000]; // ligne B - void f(int i) { // ligne C - int j; // ligne D - // code non fourni - } - void g(char c) { - int i; // ligne E - // code non fourni - } - int main(int argc, char * argv[]) - { - int k=1; // ligne F - - f(argc); - g('a'); - } - - -Lors de l'exécution de ce programme, les valeurs des différentes variables sont stockées en mémoire. Un seul des groupes d'affirmations ci-dessous est correct. Lequel ? - - -.. class:: positive - -- - - la variable ``i`` déclarée et initialisée en ``ligne A`` est stockée dans la zone des variable initialisées - - l'argument ``i`` déclaré en ``ligne C`` est stocké sur la pile - - la variable ``j`` déclarée en ``ligne D`` est stockée sur la pile - - la variable ``k`` déclarée en ``ligne F`` est stockée sur la pile - - -- - - la variable ``i`` déclarée et initialisée en ``ligne A`` est stockée dans la zone des variable initialisées - - le tableau ``tab`` déclaré en ``ligne B`` est stocké dans la zone des variables non-initialisées - - l'argument ``i`` déclaré en ``ligne C`` est stocké sur la pile - - la variable ``i`` déclarée en ``ligne E`` est stockée sur la pile - - - -.. class:: negative - -- - - - le tableau ``tab`` déclaré en ``ligne B`` est stocké dans la zone des variables initialisées - - l'argument ``i`` déclaré en ``ligne C`` est stocké sur la pile - - la variable ``j`` déclarée en ``ligne D`` est stockée sur la pile - - la variable ``i`` déclarée en ``ligne E`` est stockée sur la pile - - la variable ``k`` déclarée en ``ligne F`` est stockée dans la zone des variables non-initialisées - -- - - - le tableau ``tab`` déclaré en ``ligne B`` est stocké dans la zone des variables non-initialisées - - l'argument ``i`` déclaré en ``ligne C`` est stocké sur le tas - - la variable ``k`` déclarée en ``ligne F`` est stockée sur la pile - - -- - - le tableau ``tab`` déclaré en ``ligne B`` est stocké dans la zone des variables non-initialisées - - l'argument ``i`` déclaré en ``ligne C`` est stocké sur la pile - - la variable ``j`` déclarée en ``ligne D`` est stockée sur la pile - - la variable ``i`` déclarée en ``ligne E`` est stockée sur le tas - - la variable ``k`` déclarée en ``ligne F`` est stockée sur la pile - - -- - - la variable ``i`` déclarée et initialisée en ``ligne A`` est stockée dans la zone des variable initialisées - - le tableau ``tab`` déclaré en ``ligne B`` est stocké dans la zone des variables non-initialisées - - l'argument ``i`` déclaré en ``ligne C`` est stocké sur la pile - - la variable ``k`` déclarée en ``ligne F`` est stockée sur le tas - - -Question 4. Initialisation des variables ----------------------------------------- - -En C, une règle de bonne pratique est d'initialiser toutes les variables avant leur utilisation. Utiliser une variable qui n'a pas été correctement initialisée pour être une source de problèmes. Un étudiant a écrit les déclarations ci-dessous : - - .. code-block:: c - - int k=0; - int i; - short j; - float f; - double d; - char c[10]; - char* string; - void* v; - int* ptr; - ptr=(int*) malloc(5*sizeof(int)); - - -Après exécution de ces lignes, un seul des groupes d'affirmations ci-dessous est correct. Lequel ? - -.. class:: positive - -- - - la variable ``i`` est initialisée à la valeur ``0`` - - le pointeur ``string`` est initialisé à la valeur ``NULL`` - - ``c[2]`` contient le caractère ``'\0'`` - - Après exécution de ``malloc``, le contenu de l'adresse ``ptr+1`` est indéterminé - - .. class:: comment - - Pour des raisons d'efficacité, `malloc(3)`_ n'initialise pas à zéro les zones mémoires allouées, contrairement à `calloc(3)`_ - -- - - la variable ``j`` est initialisée à la valeur ``0`` - - le pointeur ``v`` est initialisé à la valeur ``NULL`` - - ``c[4]`` contient le caractère ``'\0'`` - - Après exécution de ``malloc``, le contenu de l'adresse ``ptr+4`` est indéterminé - - .. class:: comment - - Pour des raisons d'efficacité, `malloc(3)`_ n'initialise pas à zéro les zones mémoires allouées, contrairement à `calloc(3)`_ - -.. class:: negative - -- - - la variable ``f`` est initialisée à la valeur ``0.0`` - - le pointeur ``string`` n'a aucune valeur et n'est pas utilisable - - ``c[2]`` contient le caractère espace - - Après exécution de ``malloc``, l'adresse ``ptr+1`` contient le caractère ``'\0'`` - - .. class:: comment - - `malloc(3)`_ n'initialise pas la zone mémoire allouée. ``string`` contient ``NULL`` et ``c[2]`` le caractère ``'\0'`` - -- - - la variable ``f`` est initialisée à la valeur ``0.0`` - - le pointeur ``v`` n'a aucune valeur et n'est pas utilisable - - ``c[2]`` contient le caractère espace - - Après exécution de ``malloc``, l'adresse ``ptr`` contient le caractère ``'\0'`` - -- - - la variable ``f`` est initialisée à la valeur ``0.0`` - - le pointeur ``string`` est initialisé à ``NULL`` - - ``c[10]`` contient le caractère espace - - Après exécution de ``malloc``, l'adresse ``ptr+3`` contient le caractère ``'\0'`` - - .. class:: comment - - ``c[10]`` est hors du tableau ``c``. `malloc(3)`_ n'initialise pas la zone mémoire allouée. - -- - - la variable ``f`` est initialisée à la valeur ``0.0`` - - le pointeur ``v`` est initialisé à ``NULL`` - - ``c[6]`` contient le caractère ``'\0'`` - - Après exécution de ``malloc``, l'adresse ``ptr+5`` contient le caractère ``'\0'`` - - .. class:: comment - - `malloc(3)`_ n'initialise pas la zone mémoire allouée. De plus, ``ptr+5`` se trouve en dehors de la zone mémoire allouée par `malloc(3)`_ - - -Question 5. `malloc(3)`_ et compagnie -------------------------------------- - - -Les fonctions `malloc(3)`_ et `free(3)`_ sont importantes pour la manipulation de la mémoire sur le tas. Parmi les groupes d'affirmation suivants, un seul est correct. Lequel ? - -.. class:: positive - -- - - la fonction `malloc(3)`_ retourne un pointeur de type ``void *`` - - la fonction `free(3)`_ prend comme argument un pointeur de type ``void *`` qui a été précédemment alloué par la fonction `malloc(3)`_ - - si l'appel à `calloc(3)`_ a retourné un pointeur différent de ``NULL``, alors la zone mémoire demandée a été allouée et est initialisée à zéro - - une implémentation possible (non efficace) de `realloc(3)`_ est : - - .. code-block:: c - - void *realloc(void *ptr, size_t len) - { - void *r; - - r = malloc(len); - if(r!=NULL) - { - memcpy(r, ptr, len); - free(ptr); - } - return r; - } - - - -.. class:: negative - -- - - la fonction `malloc(3)`_ retourne un pointeur de type ``void *`` - - la fonction `free(3)`_ prend comme argument n'importe quel type de pointeur - - si l'appel à `malloc(3)`_ a retourné un pointeur différent de ``NULL``, alors la zone mémoire demandée a été allouée mais n'est pas initialisée à zéro - - une implémentation possible (non efficace) de `realloc(3)`_ est : - - .. code-block:: c - - void *realloc(void *ptr, size_t len) - { - void *r; - r = malloc(len); - memcpy(r, ptr, len); - return r; - } - - - -- - - la fonction `calloc(3)`_ retourne un pointeur de type ``void *`` - - la fonction `free(3)`_ prend comme argument un pointeur de type ``void *`` qui a été précédemment alloué par la fonction `malloc(3)`_ - - si l'appel à `malloc(3)`_ a retourné un pointeur différent de ``NULL``, alors la zone mémoire demandée a été allouée et est initialisée - - une implémentation possible (non efficace) de `realloc(3)`_ est : - - .. code-block:: c - - void *realloc(void *ptr, size_t len) - { - return malloc(len); - } - - -- - - la fonction `calloc(3)`_ retourne un pointeur de type ``void *`` - - la fonction `free(3)`_ prend comme argument un pointeur de type ``void *`` qui a été précédemment alloué par la fonction `malloc(3)`_ - - si l'appel à `malloc(3)`_ a retourné un pointeur différent de ``NULL``, alors la zone mémoire demandée a été allouée et est initialisée - - une implémentation possible (non efficace) de `realloc(3)`_ est : - - .. code-block:: c - - void *realloc(void *ptr, size_t len) - { - void *r; - - r = malloc(len); - if(r) - { - return r; - } - else - { - return NULL; - } - } - - - -Question 6. Stack ------------------ - -Considérons le programme `stack.c` présenté dans le syllabus. Cette implémentation d'une pile permet d'ajouter et de retirer un élément de la pile. Laquelle des implémentations ci-dessous est-elle une implémentation correcte d'une fonction ``size`` permettant de calculer le nombre d'éléments stockés dans la pile ? - -.. class:: positive - -- - .. code-block:: c - - int size(struct node_t* stack) - { - struct node_t *curr = stack; - int count = 0; - while (curr!=NULL) { - count ++; - curr = curr->next; - } - return count; - } - - -- - .. code-block:: c - - int size(struct node_t* stack) - { - int count = 0; - while (stack!=NULL) { - count ++; - stack = stack->next; - } - return count; - } - - - -.. class:: negative - -- - .. code-block:: c - - int size(struct node_t* stack) - { - int count = 0; - while (stack!=NULL) { - count ++; - stack++; - } - return count; - } - - -- - .. code-block:: c - - int size(struct node_t* stack) - { - return sizeof(stack); - } - - - -- - .. code-block:: c - - int size(struct node_t* stack) - { - struct node_t *curr = stack; - int count = 0; - while (curr) { - count ++; - curr++; - } - return count; - } - -- - .. code-block:: c - - int size(struct node_t stack) - { - struct node_t curr = stack; - int count = 0; - while (curr) { - count ++; - curr = stack->next; - } - return count; - } - - -Question 7. `strdup(3)`_ ------------------------- - -La librairie standard contient la fonction `strdup(3)`_. Laquelle des fonctions ci-dessous est-elle -une implémentation de `strdup(3)`_ ? - -.. class:: positive - -- - .. code-block:: c - - char *strdup(const char *s) - { - char *new = (char *) malloc ((strlen(s)+1) * sizeof(char)); - if (new == NULL) - return NULL; - return memcpy(new, s, (strlen(s)+1) * sizeof(char)); - } - -- - .. code-block:: c - - char *strdup(const char *s) - { - char *new = (char *) malloc ((strlen(s)+1) * sizeof(char)); - if (!new) - return NULL; - return memcpy(new, s, (strlen(s)+1) * sizeof(char)); - } - - -.. class:: negative - -- - .. code-block:: c - - char *strdup(const char s) - { - void *new = malloc (strlen(s)); - if (new == NULL) - return NULL; - return memcpy(new, s, strlen(s)); - } - -- - .. code-block:: c - - char *strdup(const char *s) - { - char new [strlen(s)+1]; - return memcpy(new, s, (strlen(s)+1) * sizeof(char)); - } - - -- - .. code-block:: c - - char *strdup(const char * s) - { - void *new = malloc (strlen(s+1)); - return memcpy(new, s, strlen(s+1)); - } - -- - .. code-block:: c - - char *strdup(const char *s) - { - char *new = (char *) calloc (strlen(s) * sizeof(char)); - if (new == NULL) - return NULL; - return memcpy(new, s, (strlen(s) * sizeof(char))); - } - -- - .. code-block:: c - - char *strdup(const char *s) - { - char *new = (char *) malloc (strlen(s) * sizeof(char)); - return memcpy(new, s, (strlen(s) * sizeof(char)); - } - - - - -.. include:: ../../../links.rst -.. include:: ../../../man_links.rst -.. include:: ../../../incl_links.rst diff --git a/Exercices/QCM/S4/Makefile b/Exercices/QCM/S4/Makefile deleted file mode 100755 index d1c8d362d9c6293c7eeb695b6e5997559b24ed5e..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S4/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -#################################################################### -# -# Makefile for SINF1252 QCM -# OB, Jan 2013 -# -#################################################################### - -MISSION=4 - -DEST=../../../web/qcm - -EXNAME=$(DEST)/Mission-$(MISSION)-qcm.html - -RST_FILES=qcm-$(MISSION).rst - -CSS=../rst-form/css/html4css1.css,../rst-form/css/rst-form.css,../rst-form/css/pygments.css - -.PHONY : qcm all - -qcm: $(EXNAME) - -$(EXNAME): $(RST_FILES) - @for i in $(RST_FILES); do\ - ( rst2html.py --stylesheet-path=$(CSS) $$i > $(EXNAME) ; ) ; done - - -all: qcm - -clean: - -rm -r $(EXNAME) diff --git a/Exercices/QCM/S4/qcm-4.rst b/Exercices/QCM/S4/qcm-4.rst deleted file mode 100644 index ce764e24b3cc3cbce234f51f46e964266e8be297..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S4/qcm-4.rst +++ /dev/null @@ -1,1536 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. raw:: html - - <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script> - <script type="text/javascript" src="js/jquery-shuffle.js"></script> - <script type="text/javascript" src="js/rst-form.js"></script> - <script type="text/javascript" src="js/prettify.js"></script> - <script type="text/javascript">$nmbr_prop = 3</script> - - - -================= -Quatrième semaine -================= - -Cette semaine, la matière porte sur l'organisation de la mémoire et sur le langage assembleur IA32. La matière couverte se trouve dans les sections suivantes du syllabus : - - - `Organisation des ordinateurs <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/Assembleur/memory.html>`_ - - `Etude de cas : IA32 <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/Assembleur/memory.html#etude-de-cas-architecture-ia32>`_ - -Question 1. Instruction ``mov`` -------------------------------- - -Les instructions de la famille ``mov`` permettent de déplacer des données entre registres ou d'initialiser des registres. Considérons le fragment de code C suivant (dans lequel ``g``, ``g2`` et ``s`` sont des variables globales de type ``int``) : - -.. code-block:: c - - g=1234; - g2=5678; - s=g; - g=g2; - g2=s; - -Parmi les traductions en assembleur ci-dessus, une seule est correcte. Laquelle ? - - -.. class:: positive - - -- - .. code-block:: nasm - - movl $1234, g - movl $5678, g2 - movl g, %ecx - movl %ecx, s - movl g2, %ecx - movl %ecx, g - movl s, %ecx - movl %ecx, g2 - -- - .. code-block:: nasm - - movl $1234, g - movl $5678, g2 - movl g, %eax - movl %eax, s - movl g2, %eax - movl %eax, g - movl s, %eax - movl %eax, g2 - - -.. class:: negative - -- - .. code-block:: nasm - - movl g, $1234 - movl g2, $5678 - movl %eax, g - movl s, %eax - movl %eax, g2 - movl g, %eax - movl s, %eax - movl g2, %eax - - .. class:: comment - - L'instruction ``mov`` prend comme premier argument la source et comme second la destination. - -- - .. code-block:: nasm - - movl $1234, g - movl $5678, g2 - movl g2, %eax - movl %edx, s - movl g, %eax - movl %edx, g2 - movl s, %eax - movl %eax, g2 - - .. class:: comment - - Ce code utilise les registres ``%edx`` et ``%eax``. ``%edx`` est utilisé sans être initialisé. - - -- - .. code-block:: nasm - - movw $1234, g - movw $5678, g2 - movb g2, %eax - movb %eax, s - movb g, %eax - movb %eax, g2 - movb s, %eax - movb %eax, g2 - - .. class:: comment - - L'instruction ``movb`` déplace un ``byte`` et non le contenu complet d'un registre de 32 bits. - -- - .. code-block:: nasm - - movw $1234, g - movw $5678, g2 - movb g2, %edx - movb %edx, s - movb g, %edx - movb %edx, g2 - movb s, %edx - movb %edx, g2 - - - .. class:: comment - - L'instruction ``movb`` déplace un ``byte`` et non le contenu complet d'un registre de 32 bits. - -Question 2. Opérations arithmétiques ------------------------------------- - -Considérons le fragment de programme C ci-dessous : - - .. code-block:: c - - a=a+b; - b=b+b; - c=b-a; - -Une seule des séquences d'instructions assembleur ci-dessous est une traduction correcte de cette séquence d'instructions. Laquelle ? - -.. class:: positive - -- - .. code-block:: nasm - - movl a, %eax - addl b, %eax - movl %eax, a - movl b, %eax - addl b, %eax - movl %eax, b - movl b, %eax - subl a, %eax - movl %eax, c - -- - .. code-block:: nasm - - movl b, %eax - addl a, %eax - movl %eax, a - movl b, %eax - addl b, %eax - movl %eax, b - movl b, %eax - subl a, %eax - movl %eax, c - - -.. class:: negative - -- - .. code-block:: nasm - - movl b, %eax - addl a, %eax - movl %eax, a - movl b, %eax - movl %eax, %ecx - addl $1, %ecx - movl %ecx, b - movl %eax, b - movl a, %eax - subl b, %eax - movl %eax, c - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - a=b+a; - b=b++; - c=a-b; - -- - .. code-block:: nasm - - movl b, %eax - addl a, %eax - movl %eax, c - movl b, %eax - movl %eax, %ecx - addl $1, %ecx - movl %ecx, b - movl %eax, b - movl a, %eax - subl b, %eax - movl %eax, a - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - c=b+a; - b=b++; - a=a-b; - -- - .. code-block:: nasm - - movl b, %eax - addl a, %eax - movl %eax, b - movl b, %eax - movl %eax, %ecx - addl $1, %ecx - movl %ecx, b - movl %eax, a - movl b, %eax - subl a, %eax - movl %eax, c - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - b=b+a; - a=b++; - c=b-a; - -Question 3. Instructions conditionnelles ----------------------------------------- - -Les instructions conditionnelles sont fréquemment utilisées en langage C et en assembleur. Considérons le fragment de programme C ci-dessous (``a`` et ``b`` sont des variables globales de type ``int``): - - .. code-block:: c - - if(b<4) - a++; - -Une seule des séquences d'instructions assembleur ci-dessous est une traduction correcte de cette séquence d'instructions. Laquelle ? - -.. class:: positive - -- - .. code-block:: nasm - - begin: - cmpl $4, b - jge end - movl a, %eax - addl $1, %eax - movl %eax, a - end: - -- - .. code-block:: nasm - - begin: - cmpl $4, b - jl next - jmp end - next: - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - if((b>=4)) - {} - else - a++; - - -.. class:: negative - -- - .. code-block:: nasm - - begin: - cmpl $4, b - jg end - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - if(b<=4) - a++; - - -- - .. code-block:: nasm - - begin: - cmpl $4, b - je end - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - if(b!=4) - a++; - -- - .. code-block:: nasm - - begin: - cmpl $4, b - jl end - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - if(!(b<4)) - a++; - -- - .. code-block:: nasm - - begin: - cmpl $4, b - jl end - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - if(b>=4) - a++; - - -Question 4. Instructions conditionnelles ----------------------------------------- - -Les instructions conditionnelles sont fréquemment utilisées en langage C et en assembleur. Considérons le fragment de programme C ci-dessous : - - .. code-block:: c - - if(a<=b) - c++; - - -Une seule des séquences d'instructions en assembleur ci-dessous correspond à ce fragment de code C. Laquelle ? - - -.. class:: positive - -- - .. code-block:: nasm - - if: - movl a, %eax - cmpl b, %eax - jg next - movl c, %eax - addl $1, %eax - movl %eax, c - next: - -- - .. code-block:: nasm - - if: - movl b, %eax - cmpl a, %eax - jl next - movl c, %eax - addl $1, %eax - movl %eax, c - next: - - .. class:: comment - - Ceci est en fait l'implémentation de : - - .. code-block:: c - - if(b>=a) - c++; - - -.. class:: negative - -- - .. code-block:: nasm - - if: - movl a, %eax - cmpl b, %eax - jne next - movl c, %eax - addl $1, %eax - movl %eax, c - next: - - .. class:: comment - - Ceci est l'implémentation de : - - .. code-block:: c - - if(a==b) - c++; - -- - .. code-block:: nasm - - if: - movl a, %eax - cmpl b, %eax - jle next - movl c, %eax - addl $1, %eax - movl %eax, c - next: - - .. class:: comment - - Ceci est l'implémentation de : - - .. code-block:: c - - if(a>b) - c++; - -- - .. code-block:: nasm - - if: - movl a, %eax - cmpl b, %eax - jge next - movl c, %eax - addl $1, %eax - movl %eax, c - next: - - .. class:: comment - - Ceci est l'implémentation de : - - .. code-block:: c - - if(a<b) - c++; - -- - .. code-block:: nasm - - if: - movl a, %eax - cmpl b, %eax - je next - movl c, %eax - addl $1, %eax - movl %eax, c - next: - - .. class:: comment - - Ceci est l'implémentation de : - - .. code-block:: c - - if(a!=b) - c++; - -Question 5. Instructions conditionnelles ----------------------------------------- - -L'instruction conditionnelle ``if() ... else `` se retrouve dans de nombreux programmes en langage C. Considérons l'instruction ``if() ... else`` simple ci-dessous dans laquelle ``a`` et ``b`` sont des variables globales de type ``int`` : - -.. code-block:: c - - if(a>=b) - a++; - else - b++; - -Parmi les séquences d'assembleur ci-dessous, une seule est une traduction correcte de cette instruction conditionnelle. Laquelle ? - -.. class:: positive - -- - .. code-block:: nasm - - movl a, %eax - cmpl b, %eax - jl label - movl a, %eax - addl $1, %eax - movl %eax, a - jmp end - label: - movl b, %eax - addl $1, %eax - movl %eax, b - end: - -- - .. code-block:: nasm - - movl b, %eax - cmpl a, %eax - jg label - movl a, %eax - addl $1, %eax - movl %eax, a - jmp end - label: - movl b, %eax - addl $1, %eax - movl %eax, b - end: - - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - if(b<=a) - a++; - else - b++; - - -.. class:: negative - - -- - .. code-block:: nasm - - - movl a, %eax - cmpl b, %eax - jl label - movl b, %eax - addl $1, %eax - movl %eax, b - jmp end - label: - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - if(a>=b) - b++; - else - a++; - -- - .. code-block:: nasm - - - movl b, %eax - cmpl a, %eax - jge label - movl a, %eax - addl $1, %eax - movl %eax, a - jmp end - label: - movl b, %eax - addl $1, %eax - movl %eax, b - end: - - - - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - if(b<a) - a++; - else - b++; - -- - .. code-block:: nasm - - movl b, %eax - cmpl a, %eax - jle label - movl b, %eax - addl $1, %eax - movl %eax, b - jmp .LBB4_3 - label: - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - if(b>a) - b++; - else - a++; - -- - .. code-block:: nasm - - movl a, %eax - cmpl b, %eax - jl label - movl a, %eax - addl $1, %eax - movl %eax, a - label: - movl b, %eax - addl $1, %eax - movl %eax, b - end: - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - if(a>=b) { - a++; - } - b++; - - - -Question 6. Boucles ``while`` ------------------------------ - -Les boucles ``while`` sont fréquemment utilisées dans des programmes C. Considérons la boucle suivante qui utilise des variables globales (toutes de type ``int``): - - .. code-block:: c - - while(a!=c) - { - a++; - b=b+c; - } - - -Parmi les séquences d'assembleur ci-dessous, une seule est une traduction correcte de cette boucle ``while``. Laquelle ? - -.. class:: positive - -- - .. code-block:: nasm - - begin: - movl a, %eax - cmpl c, %eax - je end - movl a, %eax - addl $1, %eax - movl %eax, a - movl b, %eax - addl c, %eax - movl %eax, b - jmp begin - end: - -- - .. code-block:: nasm - - begin: - movl c, %eax - cmpl a, %eax - je end - movl a, %eax - addl $1, %eax - movl %eax, a - movl b, %eax - addl c, %eax - movl %eax, b - jmp begin - end: - - -.. class:: negative - -- - .. code-block:: nasm - - begin: - movl c, %eax - cmpl a, %eax - jle end - movl a, %eax - addl $1, %eax - movl %eax, a - movl b, %eax - addl c, %eax - movl %eax, b - jmp begin - end: - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - while(c>a) - { - a++; - b=b+c; - } - -- - .. code-block:: nasm - - begin: - movl a, %eax - addl $1, %eax - movl %eax, a - movl b, %eax - addl c, %eax - movl %eax, b - movl c, %eax - cmpl a, %eax - jne begin - end: - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - do - { - a++; - b=b+c; - } - while(c!=a); - -- - .. code-block:: nasm - - begin: - movl c, %eax - cmpl a, %eax - jne end - movl a, %eax - addl $1, %eax - movl %eax, a - movl b, %eax - addl c, %eax - movl %eax, b - jmp begin - end: - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - while(c==a) - { - a++; - b=b+c; - } - - -Question 7. Boucles ``for`` ---------------------------- - -Rares sont les programmes C qui ne contiennent pas de boucles ``for``. Considérons la boucle ci-dessous qui utilise uniquement des variables globales (de type ``int``) : - -.. code-block:: c - - for(a=0;a<c;a++) { - b=b-c; - } - -Parmi les séquences d'instructions en assembleur ci-dessous, une seule traduit correctement la boucle ``for`` ci-dessus. Laquelle ? - - -.. class:: positive - -- - .. code-block:: nasm - - begin: - movl $0, a - loop: - movl a, %eax - cmpl c, %eax - jge end - movl b, %eax - subl c, %eax - movl %eax, b - movl a, %eax - addl $1, %eax - movl %eax, a - jmp loop - end: - -- - .. code-block:: nasm - - begin: - movl $0, a - loop: - movl c, %eax - cmpl a, %eax - jle end - movl b, %eax - subl c, %eax - movl %eax, b - movl a, %eax - addl $1, %eax - movl %eax, a - jmp loop - end: - -.. class:: negative - -- - .. code-block:: nasm - - begin: - movl a, %eax - addl $1, %eax - movl %eax, a - loop: - movl c, %eax - cmpl a, %eax - jle end - movl b, %eax - subl c, %eax - movl %eax, b - movl $0, a - jmp loop - end: - - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - for(a=a+1;c>a;a=0) { - b=b-c; - } - -- - .. code-block:: nasm - - begin: - movl $0, a - loop: - movl a, %eax - cmpl c, %eax - jg end - movl b, %eax - subl c, %eax - movl %eax, b - movl a, %eax - addl $1, %eax - movl %eax, a - jmp loop - end: - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - for(a=0;a<=c;a++) { - b=b-c; - } - -- - .. code-block:: nasm - - begin: - movl $0, a - movl a, %eax - cmpl c, %eax - jge end - movl b, %eax - subl c, %eax - movl %eax, b - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - a=0; - if(a<c) { - b=b-c; - a++; - } - -- - .. code-block:: nasm - - begin: - loop: - movl a, %eax - cmpl c, %eax - jge end - movl $0, a - movl b, %eax - subl c, %eax - movl %eax, b - movl a, %eax - addl $1, %eax - movl %eax, a - jmp loop - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - for(;a<c;a++) { - a=0; - b=b-c; - } - - -Question 8. Fonctions ---------------------- - -Un programme C contient en général de nombreuses fonctions. Considérons une fonction simple qui effectue un calcul en utilisant un argument et une variable globale (``a``) : - -.. code-block:: c - - - int f(int i) - { - return i+a; - } - - -Parmi les séquences d'instructions en assembleur ci-dessous, une seule traduit correctement la fonction ci-dessus. Laquelle ? - -.. class:: positive - -- - .. code-block:: nasm - - pushl %eax - movl 8(%esp), %eax - movl %eax, (%esp) - movl (%esp), %eax - addl a, %eax - popl %edx - ret - - - -- - .. code-block:: nasm - - subl $8, %esp - movl 12(%esp), %eax - movl %eax, 4(%esp) - movl a, %eax - movl %eax, (%esp) - movl (%esp), %eax - addl 4(%esp), %eax - addl $8, %esp - ret - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - int f(int i) - { - int j=a; - return j+i; - } - - -.. class:: negative - -- - .. code-block:: nasm - - subl $8, %esp - movl 12(%esp), %eax - movl %eax, 4(%esp) - movl 4(%esp), %eax - addl a, %eax - movl %eax, (%esp) - addl $8, %esp - ret - - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - void f3(int i) // incorrect - { - int j=i+a; - } - -- - .. code-block:: nasm - - pushl %eax - movl (%esp), %eax - addl a, %eax - popl %edx - ret - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - - int f() - { - int i; - return i+a; - } - - -- - .. code-block:: nasm - - pushl %eax - movb 8(%esp), %al - movb %al, 3(%esp) - movsbl 3(%esp), %ecx - addl a, %ecx - movl %ecx, %eax - popl %edx - ret - - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - int f(char c) - { - return c+a; - } - -- - .. code-block:: nasm - - pushl %eax - movb 8(%esp), %al - movb %al, 3(%esp) - movsbl 3(%esp), %ecx - addl a, %ecx - movb %cl, %al - movsbl %al, %eax - popl %edx - ret - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - char f(char c) - { - return c+a; - } - - - - - -Question 9. Fonction ``max`` ----------------------------- - -Considérons la fonction C qui calcule le maximum entre deux entiers : - -.. code-block:: c - - int max(int i, int j) { - if (i>j) - return i; - else - return j; - } - -Parmi les groupes d'instructions ci-dessous, un seul est la traduction de cette fonction. Lequel ? - -.. class:: positive - -- - .. code-block:: nasm - - - max: - subl $12, %esp - movl 20(%esp), %eax - movl 16(%esp), %ecx - movl %ecx, 4(%esp) - movl %eax, (%esp) - movl 4(%esp), %eax - cmpl (%esp), %eax - jle next - movl 4(%esp), %eax - movl %eax, 8(%esp) - jmp label - next: - movl (%esp), %eax - movl %eax, 8(%esp) - label: - movl 8(%esp), %eax - addl $12, %esp - ret - - -- - .. code-block:: nasm - - max2: - subl $12, %esp - movl 20(%esp), %eax - movl 16(%esp), %ecx - movl %ecx, 4(%esp) - movl %eax, (%esp) - movl 4(%esp), %eax - cmpl (%esp), %eax - jge label1 - movl (%esp), %eax - movl %eax, 8(%esp) - jmp label2 - label1: - movl 4(%esp), %eax - movl %eax, 8(%esp) - label2: - movl 8(%esp), %eax - addl $12, %esp - ret - - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - int max(int i, int j) { - if (i<j) - return j; - else - return i; - } - - -.. class:: negative - -- - .. code-block:: nasm - - max: - subl $8, %esp - movl 12(%esp), %eax - movl %eax, (%esp) - movl (%esp), %eax - cmpl (%esp), %eax - jge label1 - movl (%esp), %eax - movl %eax, 4(%esp) - jmp label2 - label1: - movl (%esp), %eax - movl %eax, 4(%esp) - label2: - movl 4(%esp), %eax - addl $8, %esp - ret - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - - int max(int i) { - if (i<i) - return i; - else - return i; - } - -- - .. code-block:: nasm - - max: - subl $12, %esp - movl 20(%esp), %eax - movl 16(%esp), %ecx - movl %ecx, 4(%esp) - movl %eax, (%esp) - movl 4(%esp), %eax - cmpl (%esp), %eax - jge label1 - movl (%esp), %eax - movl %eax, 8(%esp) - jmp label2 - label1: - movl (%esp), %eax - movl %eax, 8(%esp) - label2: - movl 8(%esp), %eax - addl $12, %esp - ret - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - int max4(int i, int j) { //incorrect - if (i<j) - return j; - else - return j; - } - - -- - .. code-block:: nasm - - max: - subl $12, %esp - movl 20(%esp), %eax - movl 16(%esp), %ecx - movl %ecx, 4(%esp) - movl %eax, (%esp) - movl 4(%esp), %eax - cmpl (%esp), %eax - jge label1 - movl 4(%esp), %eax - movl %eax, 8(%esp) - jmp label2 - label1: - movl (%esp), %eax - movl %eax, 8(%esp) - label2: - movl 8(%esp), %eax - addl $12, %esp - ret - - - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - int max5(int i, int j) { //incorrect - if (i<j) - return i; - else - return j; - } - -Question 10. Fonctions récursives ---------------------------------- - -Les fonctions récursives sont parfois utilisées en langage C. Lors de leur exécution, la pile permet de stocker temporairement les valeurs des variables et les adresses de retour. Considérons la fonction récursive suivante (où ``a`` est une variable globale) : - -.. code-block:: c - - int f(int i) - { - return a+f(i-1); - } - -Parmi les séquences d'instructions assembleur ci-dessous, une seule est une traduction correctement de cette fonction. Laquelle ? - -.. class:: positive - -- - .. code-block:: nasm - - - f: - pushl %ebp - movl %esp, %ebp - subl $12, %esp - movl 8(%ebp), %eax - movl %eax, -4(%ebp) - movl a, %eax - movl -4(%ebp), %ecx - subl $1, %ecx - movl %ecx, (%esp) - movl %eax, -8(%ebp) - calll f - movl -8(%ebp), %ecx - addl %eax, %ecx - movl %ecx, %eax - addl $12, %esp - popl %ebp - ret - - -- - .. code-block:: nasm - - f: - pushl %ebp - movl %esp, %ebp - subl $12, %esp - movl 8(%ebp), %eax - movl %eax, -4(%ebp) - movl -4(%ebp), %eax - subl $1, %eax - movl %eax, (%esp) - calll f - movl %eax, -8(%ebp) - movl -8(%ebp), %eax - addl a, %eax - addl $12, %esp - popl %ebp - ret - - - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - int f(int i) - { - int j=f(i-1); - return j+a; - } - - -.. class:: negative - -- - .. code-block:: nasm - - f: - pushl %ebp - movl %esp, %ebp - subl $12, %esp - movl 8(%ebp), %eax - movl %eax, -4(%ebp) - movl a, %eax - movl -4(%ebp), %ecx - movl %ecx, (%esp) - movl %eax, -8(%ebp) - calll f - movl -8(%ebp), %ecx - addl %eax, %ecx - movl %ecx, %eax - addl $12, %esp - popl %ebp - ret - - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - int f(int i) - { - return a+f(i); - } - -- - .. code-block:: nasm - - f: - pushl %ebp - movl %esp, %ebp - subl $8, %esp - movl 8(%ebp), %eax - movl %eax, -4(%ebp) - movl -4(%ebp), %eax - addl a, %eax - movl %eax, (%esp) - calll f - addl $8, %esp - popl %ebp - ret - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - int f(int i) // incorrect - { - return f(i+a); - } - -- - .. code-block:: nasm - - pushl %ebp - movl %esp, %ebp - subl $12, %esp - movl 8(%ebp), %eax - movl %eax, -4(%ebp) - movl -4(%ebp), %eax - subl $1, %eax - movl %eax, (%esp) - calll f - movl %eax, -8(%ebp) - movl a, %eax - addl $12, %esp - popl %ebp - ret - - .. class:: comment - - Ceci est la traduction de : - - .. code-block:: c - - int f(int i) - { - int j=f(i-1); - return a; - } - - -.. include:: ../../../links.rst -.. include:: ../../../man_links.rst -.. include:: ../../../incl_links.rst diff --git a/Exercices/QCM/S4/src/Makefile b/Exercices/QCM/S4/src/Makefile deleted file mode 100644 index d0cdb1837b08fcaabc2997b13501982228142f42..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S4/src/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -#################################################################### -# -# Makefile for assembler -# OB, Feb 2013 -# -#################################################################### - -CC=~/local/clang+llvm-3.2-x86_64-apple-darwin11/bin/clang - -CFLAGS=-target i386 -S -Wdisabled-optimization -O0 -fverbose-asm - -all: - @for file in *.c ; do \ - ($(CC) $(CFLAGS) $${file}; ) ; done diff --git a/Exercices/QCM/S4/src/asm1.c b/Exercices/QCM/S4/src/asm1.c deleted file mode 100644 index e29f2f931839b25b8b2c36fe76e7dc78392f9e37..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S4/src/asm1.c +++ /dev/null @@ -1,18 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int g; -int g2; -int s; - -int main() { - - g=1234; - g2=5678; - s=g; - g=g2; - g2=s; - -} - - diff --git a/Exercices/QCM/S4/src/asm2.c b/Exercices/QCM/S4/src/asm2.c deleted file mode 100644 index ceb099325880fd75e0484549c529a703c2f89a9d..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S4/src/asm2.c +++ /dev/null @@ -1,52 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int a=1; -int b=2; -int c=3; - -void f1() -{ - if(a==b) - c++; -} - -void f2() -{ - if(a>b) - c++; -} - -void f3() -{ - if(a<b) - c++; -} - -void f4() -{ - if(a!=b) - c++; -} - -void f5() -{ - if(a<=b) - c++; -} - -void f6() -{ - if(b>=a) - c++; -} - - - -int main() { - - - -} - - diff --git a/Exercices/QCM/S4/src/asm3.c b/Exercices/QCM/S4/src/asm3.c deleted file mode 100644 index 1478e0e09c08651a8704f0d85ef6ce7daaa8ddaa..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S4/src/asm3.c +++ /dev/null @@ -1,54 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int a=1; -int b=2; -int c=3; - -void f1() -{ - a=a+b; - b=b+b; - c=b-a; -} - -void f2() -{ - a=b+a; - b=b+b; - c=b-a; -} - -void f3() -{ - a=b+a; - b=b++; - c=a-b; -} - -void f4() -{ - c=b+a; - b=b++; - a=a-b; -} - -void f5() -{ - - b=b+a; - a=b++; - c=b-a; - -} - - - - -int main() { - - - -} - - diff --git a/Exercices/QCM/S4/src/asm_comp.c b/Exercices/QCM/S4/src/asm_comp.c deleted file mode 100644 index 6ee427e551777351abc16a78b01345f128138f5d..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S4/src/asm_comp.c +++ /dev/null @@ -1,58 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int a=1; -int b=2; -int c=3; - -void f1() // correct -{ - if(b<4) - a++; - -} - -void f2() // correct -{ - if((b>=4)) - {} - else - a++; -} - -void f3() // incorrect -{ - if(b<=4) - a++; - -} - -void f4() // incorrect -{ - if(b!=4) - a++; - -} - -void f5() // incorrect -{ - if(!(b<4)) - a++; - -} - -void f6() // incorrect -{ - if(b>=4) - a++; -} - - - -int main() { - - - -} - - diff --git a/Exercices/QCM/S4/src/asm_fct1.c b/Exercices/QCM/S4/src/asm_fct1.c deleted file mode 100644 index 998bb3c89e7cd8de3094421af0562d29b2b81bf0..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S4/src/asm_fct1.c +++ /dev/null @@ -1,51 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int a=1; -int b=2; -int c=3; - -int f1(int i) // correct -{ - return i+a; -} - -int f2(int i) // correct -{ - int j=a; - return j+i; - -} - -void f3(int i) // incorrect -{ - int j=i+a; - -} - -int f4() // incorrect -{ - int i; - return i+a; -} - -int f5(char c) // incorrect -{ - return c+a; - -} - -char f6(char c) // incorrect -{ - return c+a; -} - - - -int main() { - - - -} - - diff --git a/Exercices/QCM/S4/src/asm_fct2.c b/Exercices/QCM/S4/src/asm_fct2.c deleted file mode 100644 index 20c1d6d76c71438045bce32dfbea176fb1134add..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S4/src/asm_fct2.c +++ /dev/null @@ -1,51 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int a=1; -int b=2; -int c=3; - -int f1(int i) // correct -{ - return a+f1(i-1); -} - -int f2(int i) // correct -{ - int j=f2(i-1); - return j+a; - -} - -int f3(int i) // incorrect -{ - return a+f3(i); - -} - -int f4(int i) // incorrect -{ - return f4(i+a); -} - -int f5(int i) // incorrect -{ - int j=f5(i-1); - return a; -} - -char f6(char c) // incorrect -{ - return a+f6(c-1); - -} - - - -int main() { - - - -} - - diff --git a/Exercices/QCM/S4/src/asm_for.c b/Exercices/QCM/S4/src/asm_for.c deleted file mode 100644 index 694878382addb71609702076f8de7456dca70b5d..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S4/src/asm_for.c +++ /dev/null @@ -1,68 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int a=1; -int b=2; -int c=3; - -void f1() // correct -{ - for(a=0;a<c;a++) { - b=b-c; - } - -} - -void f2() // correct -{ - for(a=0;c>a;a=a+1) { - b=b-c; - } - -} - -void f3() // incorrect -{ - - for(a=a+1;c>a;a=0) { - b=b-c; - } -} - -void f4() // incorrect -{ - for(a=0;a<=c;a++) { - b=b-c; - } - -} - -void f5() // incorrect -{ - a=0; - if(a<c) { - b=b-c; - a++; - } - -} - -void f6() // incorrect -{ - for(;a<c;a++) { - a=0; - b=b-c; - } - - -} - - - -int main() { - - - -} - - diff --git a/Exercices/QCM/S4/src/asm_ifelse.c b/Exercices/QCM/S4/src/asm_ifelse.c deleted file mode 100644 index 4833fd3cd2cf0cf00bc1e1903f235fe64d78c8bc..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S4/src/asm_ifelse.c +++ /dev/null @@ -1,68 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int a=1; -int b=2; -int c=3; - -void f1() // correct -{ - if(a>=b) - a++; - else - b++; - -} - -void f2() // correct -{ - if(b<=a) - a++; - else - b++; -} - -void f3() // incorrect -{ - if(a>=b) - b++; - else - a++; - -} - -void f4() // incorrect -{ - if(b<a) - a++; - else - b++; -} - -void f5() // incorrect -{ - if(b>a) - b++; - else - a++; - -} - -void f6() // incorrect -{ - if(a>=b) { - a++; - } - b++; - -} - - - -int main() { - - - -} - - diff --git a/Exercices/QCM/S4/src/asm_max.c b/Exercices/QCM/S4/src/asm_max.c deleted file mode 100644 index 491092adaeaeebc2544fb78f40cce7b1c0e7fc30..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S4/src/asm_max.c +++ /dev/null @@ -1,52 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int a=1; -int b=2; -int c=3; - -int max(int i, int j) { //correct - if (i>j) - return i; - else - return j; -} - -int max2(int i, int j) { //correct - if (i<j) - return j; - else - return i; -} - -int max3(int i) { //incorrect - if (i<i) - return i; - else - return i; -} - -int max4(int i, int j) { //incorrect - if (i<j) - return j; - else - return j; -} - - -int max5(int i, int j) { //incorrect - if (i<j) - return i; - else - return j; -} - - - -int main() { - - - -} - - diff --git a/Exercices/QCM/S4/src/asm_sumpair.c b/Exercices/QCM/S4/src/asm_sumpair.c deleted file mode 100644 index 44ff95c24eba63110b53ec7738d7d9a2d0e81aa7..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S4/src/asm_sumpair.c +++ /dev/null @@ -1,25 +0,0 @@ -/************************************** - * sumn.c - * - * Programme d'exemple pour un calcul récursif - * de la somme des n premiers nombres impairs - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - - -///AAA -int ndiv(int n) { - if(n%2==0) - return sumn(n-1); - else - return n+sumn(n-1); -} -///BBB -int main(int argc, char *argv[]) { - g=sumn(3); - h=sumn_iter(3); - return(EXIT_SUCCESS); -} diff --git a/Exercices/QCM/S4/src/asm_while.c b/Exercices/QCM/S4/src/asm_while.c deleted file mode 100644 index aabab048cb7f539577d4b428841c12e447bdca98..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S4/src/asm_while.c +++ /dev/null @@ -1,68 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int a=1; -int b=2; -int c=3; - -void f1() // correct -{ - while(a!=c) - { - a++; - b=b+c; - } - -} - -void f2() // correct -{ - while(c!=a) - { - a++; - b=b+c; - } - -} - -void f3() // incorrect -{ - while(c>a) - { - a++; - b=b+c; - } -} - -void f4() // incorrect -{ - do - { - a++; - b=b+c; - } - while(c!=a); - -} - -void f5() // incorrect -{ - - while(c==a) - { - a++; - b=b+c; - } - -} - - - - -int main() { - - - -} - - diff --git a/Exercices/QCM/S5/Makefile b/Exercices/QCM/S5/Makefile deleted file mode 100755 index 6ba4c413e30186b366726bbe8fe76a96a4a73a7f..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -#################################################################### -# -# Makefile for SINF1252 QCM -# OB, Jan 2013 -# -#################################################################### - -MISSION=5 - -DEST=../../../web/qcm - -EXNAME=$(DEST)/Mission-$(MISSION)-qcm.html - -RST_FILES=qcm-$(MISSION).rst - -CSS=../rst-form/css/html4css1.css,../rst-form/css/rst-form.css,../rst-form/css/pygments.css - -.PHONY : qcm all - -qcm: $(EXNAME) - -$(EXNAME): $(RST_FILES) - @for i in $(RST_FILES); do\ - ( rst2html.py --stylesheet-path=$(CSS) $$i > $(EXNAME) ; ) ; done - - -all: qcm - -clean: - -rm -r $(EXNAME) diff --git a/Exercices/QCM/S5/qcm-5.rst b/Exercices/QCM/S5/qcm-5.rst deleted file mode 100644 index 417e02a9512d9f35e3ccddf169431549b99c077b..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/qcm-5.rst +++ /dev/null @@ -1,613 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. raw:: html - - <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script> - <script type="text/javascript" src="js/jquery-shuffle.js"></script> - <script type="text/javascript" src="js/rst-form.js"></script> - <script type="text/javascript" src="js/prettify.js"></script> - <script type="text/javascript">$nmbr_prop = 3</script> - - -================= -Cinquième Semaine -================= - -Cette semaine porte sur deux modules de théorie. Le premier est la fin du chapitre consacré aux bases du langage C : - - - :ref:`complementsC` - -Le second est le début du chapitre consacré aux systèmes multiprocesseurs et l'utilisation de threads en particulier : - - - :ref:`thread` - -Question 1. Pointeurs en assembleur ------------------------------------ - -Pour comprendre le fonctionnement des pointeurs en C, il est parfois utile de se ramener à la traduction en assembleur de fragments de code C. Considérons les lignes suivantes : - - .. code-block:: c - - int a=1252; - int * ptr; - - int main(int argc, const char *argv[]) { - ptr=&a; - } - -Parmi les séquences d'instructions en assembleur ci-dessous, une seule est la traduction de l'assignation de l'adresse de ``a`` au pointeur ``ptr``. Laquelle - -.. class:: positive - -- - .. code-block:: nasm - - leal a, %eax - movl %eax, ptr - -.. class:: negative - -- - .. code-block:: nasm - - movl a, %eax - movl ptr, %ecx - movl %eax, (%ecx) - - .. class:: comment - - Cette séquence d'instructions est la traduction de ``*ptr=a``. - -- - .. code-block:: nasm - - movl a, %eax - movl %eax, ptr - - .. class:: comment - - Cette séquence d'instructions est la traduction de ``ptr=(int )a;``. - -- - .. code-block:: nasm - - pushl %eax - leal (%esp), %eax - movl a, %ecx - movl %ecx, (%esp) - movl %eax, ptr - popl %eax - - .. class:: comment - - Cette séquence d'instructions est la traduction de : - - .. code-block:: c - - int b=a; - ptr=&(b); - -- - .. code-block:: nasm - - leal a, %eax - addl $4, %eax - movl %eax, ptr - - .. class:: comment - - Cette séquence d'instructions est la traduction de ``ptr=&a+1;``. - - -Question 2. Pointeurs et tableaux ---------------------------------- - -Les pointeurs peuvent être utilisés pour accéder à des tableaux. Considérons un fragment de code C utilisant un tableau d'entiers à une dimension : - -.. code-block:: c - - int a[]={2,4,3,4,8}; - int * ptr; - - printf("%d %d %d %d\n",a[0],a[1],a[2],a[a[3]]); - - -Lors de son exécution, ce programme affiche ``2 4 3 8`` sur sa sortie standard. - -Après exécution de ``ptr=&(a[0]);``, une seule des instructions ci-dessous affiche la même séquence de chiffres. Laquelle ? - -.. class:: positive - -- - .. code-block:: c - - printf("%d %d %d %d\n",*ptr,*(ptr+1),*(ptr+2),*(ptr+*(ptr+3))); - - -.. class:: negative - -- - .. code-block:: c - - printf("%d %d %d %d\n",*ptr,*ptr+1,*ptr+2,*(ptr+*(ptr+3))); - - .. class:: comment - - Cette ligne affiche ``2 3 4 8``. Sur base des règles de précédence entre les opérations, l'expression ``*ptr+1`` équivaut en fait à ``(*ptr)+1``. En cas de doute, utilisez les parenthèses. - - -- - .. code-block:: c - - printf("%d %d %d %d\n",*ptr,*(ptr++),(*ptr++),*(ptr+*(ptr++))); - - .. class:: comment - - Cette ligne affiche ``4 3 4 3`` - -- - .. code-block:: c - - printf("%d %d %d %d\n",*ptr,*(ptr+0),*(ptr+1),*ptr+*(ptr+2)); - - .. class:: comment - - Cette ligne affiche ``2 2 4 5``. ``*(ptr+0)`` est ``a[0]`` et non ``a[1]``. - -- - .. code-block:: c - - printf("%d %d %d %d\n",*ptr,*ptr+1,(*ptr+1),*(ptr+(ptr+3))); - - .. class:: comment - - Cette ligne est syntaxiquement invalide. L'expression ``ptr+(ptr+3)`` est invalide. On ne peut pas additionner deux pointeurs. - - - -Question 3. Traitement de ``argv`` ----------------------------------- - -Un programme C doit souvent pouvoir manipuler les arguments qui lui sont passés. Les variables ``argc`` et ``argv`` qui sont passées à la fonction ``main`` permettent d'accéder à ces arguments. Le fragment de programme ci-dessous affiche sur la sortie standard ses différents arguments. - -.. code-block:: c - - while(i<argc) { - printf("%d %p %s\n",i,&(argv[i]),argv[i]); - i++; - } - -Un exemple d'exécution de ce fragment de programme est présenté ci-dessous : - -.. code-block:: console - - #./a.out a b cd - 0 0x7fff5fbff788 ./a.out - 1 0x7fff5fbff790 a - 2 0x7fff5fbff798 b - 3 0x7fff5fbff7a0 cd - - -A côté de la notation ``argv[i]``, il est aussi possible d'accéder à ``argv`` en utilisant des pointeurs. Parmi les fragments de programme ci-dessous, un seul est correct et affiche le même résultat que ci-dessus. - -.. class:: positive - -- - .. code-block:: c - - char **ptr; - int i=0; - ptr=argv; - while(i<argc) { - printf("%d %p %s\n",i,&(*ptr),*ptr); - i++; - ptr++; - } - - -.. class:: negative - -- - .. code-block:: c - - char **ptr; - int i=0; - ptr=argv; - while(i<argc) { - printf("%d %p %s\n",i,&(ptr),*ptr); - i++; - ptr++; - } - - - .. class:: comment - - ``&(ptr)`` est l'adresse à laquelle le pointeur ``ptr`` est stocké. Notez que ce n'est pas l'adresse à laquelle la chaîne de caractère argument ``i`` est stockée. Ce programme affiche : - - .. code-block:: console - - 0 0x7fff5fbff738 ./a.out - 1 0x7fff5fbff738 a - 2 0x7fff5fbff738 b - 3 0x7fff5fbff738 cd - -- - .. code-block:: c - - char *ptr; - int i=0; - ptr=*argv; - while(i<argc) { - printf("%d %p %s\n",i,&(ptr),*ptr); - i++; - ptr++; - } - - .. class:: comment - - Notez dans ce code que ``ptr`` est déclaré comme ``char *``, alors que ``argv`` est un ``char **``. Si vous tenez d'exécutez ce code, il provoquera un segmentation fault. - -- - .. code-block:: c - - int i=0; - while(i<argc) { - printf("%d %p %s\n",i,&(argv+i),*(argv+i)); - i++; - } - - .. class:: comment - - La compilation de ce fragment de programme provoque un warning. L'expression ``&(argv+i)`` est invalide car ``argv`` est un pointeur (de type ``char **``) et donc ``argv+i`` est également une adresse en mémoire et l'opérateur ``&`` ne peut pas s'y appliquer. - -- - .. code-block:: c - - int i=0; - while(i<argc) { - printf("%d %p %s\n",i,&(*(argv+i)),(argv+i)); - i++; - } - - - .. class:: comment - - Dans ce fragment de code, ``argv+i`` est de type ``char **`` alors qu'il faut un ``char *`` pour passer un string à `printf(3)`_. - - - -Question 4. Pointeurs et tableaux à deux dimensions ---------------------------------------------------- - -En C, il est possible d'accéder aux données stockées dans un tableau à deux dimensions via la notation ``a[i][j]`` mais aussi en utilisant des pointeurs. Considérons le fragment de code ci-dessous : - -.. code-block:: c - - int m[3][4]= { { 1, 2, 3, 4} , - { 5, 6, 7, 8} , - { 9, 10, 11, 12} }; - - printf("%p %d %d %d\n",m, m[1][2], m[0][5], m[2][2]); - - -Un compilateur Java n'accepterait pas de compiler ce programme qui tente d'accéder à l'élément ``m[0][5]`` de la matrice, élément qui n'existe pas sur base de l'initialisation du tableau ``m``. De nombreux compilateurs C acceptent ce fragment de code sans contrainte. Lorsque le programme s'exécute il affiche : - -.. code-block:: console - - 0x7fff5fbff750 7 6 11 - -Parmi les fragments de programme ci-dessous, un seul utilisant la notation avec les pointeurs est correct et affiche la même sortie. Lequel ? - -.. class:: positive - -- - .. code-block:: c - - int *ptr; - - ptr=&(m[0][0]); - printf("%p %d %d %d\n",ptr, *(ptr+4*1+2), *(ptr+4*0+5), *(ptr+2*4+2)); - - -.. class:: negative - -- - .. code-block:: c - - int **ptr=m; - printf("%p %d %d %d\n",ptr, *(ptr+4*1+2), *(ptr+4*0+5), *(ptr+2*4+2)); - - .. class:: comment - - La déclaration ``int **ptr=m`` est invalide. - -- - .. code-block:: c - - int *ptr=m; - printf("%p %d %d %d\n",ptr, *(ptr+4*1+2), *(ptr+4*0+5), *(ptr+2*4+2)); - - - .. class:: comment - - La déclaration ``int *ptr=m;`` est invalide, ``m`` n'est pas de type ``int *``. - -Question 5. Variable ``errno`` ------------------------------- - - -En C, la variable ``errno`` est utilisée par le système pour fournir une indication sur une erreur qui s'est produite lors de l'exécution d'un appel système ou d'une fonction de la librairie. Parmi les fonctions ci-dessous, une seule ne modifie pas ``errno`` en cas d'erreur. Laquelle ? - -.. class:: positive - -- `getpid(2)`_ - - .. class:: comment - - Voir page de manuel. - -- `malloc(3)`_ - - .. class:: comment - - Notez que `malloc(3)`_ retourne ``NULL`` en cas d'erreur d'allocation. - -- `exit(2)`_ - - .. class:: comment - - Comme cette fonction ne se termine jamais, elle ne peux pas modifier ``errno``. - -.. class:: negative - -- `setenv(3)`_ - - .. class:: comment - - Voir page de manuel. - - -- `unsetenv(3)`_ - - .. class:: comment - - Voir page de manuel. - -- `pthread_join(3)`_ - - .. class:: comment - - Voir page de manuel. - - -Question 6. Utilisation de `pthread_create(3)`_ ------------------------------------------------- - -La fonction `pthread_create(3)`_ permet de créer un thread. Parmi les fragments de code ci-dessous, un seul crée correctement un thread qui appelle la fonction ``f`` en lui passant la chaîne de caractères ``s`` comme argument. Lequel ? - -.. class:: positive - -- - .. code-block:: c - - void * f( void * param) { - // incomplet - return NULL; - } - - int main (int argc, char *argv[]) { - - pthread_t t; - int err; - char *s; - err=pthread_create(&t,NULL,&(f),(void *) s); - } - -.. class:: negative - -- - .. code-block:: c - - void * f (void * param) { - // incomplet - return NULL; - } - - int main (int argc, char *argv[]) { - - pthread_t t; - int err; - char *s; - err=pthread_create(&t,NULL,&(f),(void *) &s); - } - - .. class:: comment - - - Ce fragment contient une erreur. La fonction ``f`` a la bonne signature, mais le dernier argument à `pthread_create(3)`_ doit être de type ``void *``, or ``s`` est un ``char *`` et donc ce dernier argument doit être ``(void *) s``. - -- - .. code-block:: c - - void f(void * param) { - // incomplet - return NULL; - } - - int main (int argc, char *argv[]) { - - pthread_t *t; - int err; - char *s; - err=pthread_create(t,NULL,*f,(void *) *s); - } - - .. class:: comment - - Ce fragment contient plusieurs erreurs. La fonction ``f`` n'a pas la bonne signature (d'ailleurs ``return NULL;`` pour une fonction ``void`` est incorrect). Ensuite, l'appel à `pthread_create(3)`_ doit prendre comme premier argument l'adresse vers une structure de type ``pthread_t`` qui est stockée en mémoire. Ce n'est pas le cas ici. Les troisième et quatrième arguments sont également incorrects. - -- - .. code-block:: c - - - void *f(void ** param) { - // incomplet - return NULL; - } - - int main (int argc, char *argv[]) { - - pthread_t t; - int err; - char s; - err=pthread_create(&t,NULL,&(f),(void *) s); - } - - .. class:: comment - - Dans ce fragment de code, la signature de la fonction ``f`` ainsi que l'appel à `pthread_create(3)`_ sont incorrects. - - - -Question 7. Passage d'arguments à un thread -------------------------------------------- - -Considérons un thread qui a pour objectif de convertir une fraction en un nombre en virgule flottante. Ce n'est pas une bonne utilisation de threads puisque le calcul à effectuer est très simple, mais cela nous permettra de voir comment un thread peut recevoir des arguments directement. En dehors des threads, cette fonction de conversion pourrait s'écrire : - -.. code-block:: c - - struct fraction { - int num; - int denum; - }; - - typedef struct fraction Fraction_t; - - float tofloat(Fraction_t t) { - return (float) t.num/ (float) t.denum; - } - - -Parmi les programmes ci-dessous, un seul calcule correctement la valeur attendue (le test des valeurs de retour des fonctions n'est pas présenté pour garder le code concis). Lequel ? - - -.. class:: positive - -- - .. code-block:: c - - void *mythread(void * param) { - Fraction_t *f=(Fraction_t *) param; - float *r=(float *)malloc(sizeof(float)); - *r=(float) f->num/ (float) f->denum; - return((void *) r); - } - - int main (int argc, char *argv[]) { - - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - float *r; - int err; - - err=pthread_create(&t,NULL,&mythread,&(f)); - - err=pthread_join(t,(void **) &r); - - } - -.. class:: negative - -- - .. code-block:: c - - void *mythread(void * param) { - Fraction_t f= *param; - float r; - r=(float) f.num/ (float) f.denum; - return((void *) &r); - } - - int main (int argc, char *argv[]) { - - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - float r; - int err; - - err=pthread_create(&t,NULL,&mythread,&(f)); - - err=pthread_join(t,(void **) &r); - - } - - .. class:: comment - - La fonction ``mythread`` est incorrect. L'initialisation de ``f`` ne fonctionne pas et en plus le résultat de la fonction est une variable locale (``r``) qui disparaît après son exécution. L'adresse de cette variable, même en étant castée en ``void *`` ne peut pas être retournée à la fonction ``main``. - -- - .. code-block:: c - - - void *mythread(void * param) { - Fraction_t *t=(Fraction_t *) param; - float *r=(float *)malloc(sizeof(float)); - *r=(float) t->num/ (float) t->denum; - return((void *) r); - } - - int main (int argc, char *argv[]) { - - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - float r; - int err; - - err=pthread_create(&t,NULL,&mythread,&f); - r=pthread_join(t,NULL); - - } - - .. class:: comment - - Dans cette variable, l'appel à `pthread_join(3)`_ est incorrect. - -- - .. code-block:: c - - float mythread(Fraction_t param) { - float *r=(float *)malloc(sizeof(float)); - *r=(float) param->num/ (float) param->denum; - return(r); - } - - int main (int argc, char *argv[]) { - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - printf("%f \n",tofloat(f)); - float *r; - int err; - - err=pthread_create(&t,NULL,&mythread,&(f)); - - err=pthread_join(t,(void *) &r); - } - - .. class:: comment - - Cette variante contient deux erreurs. La première est le prototype de la fonction ``mythread``. Celle-ci doit obligatoirement être de type ``void * fct(void * param)``, il n'est pas possible d'utiliser un autre prototype. Ensuite, l'appel à `pthread_join(3)`_ est incorrect puisque le deuxième argument de `pthread_join(3)`_ doit être de type ``void **`` et non ``void *``. - - -.. include:: ../../../links.rst -.. include:: ../../../man_links.rst -.. include:: ../../../incl_links.rst diff --git a/Exercices/QCM/S5/src/Makefile b/Exercices/QCM/S5/src/Makefile deleted file mode 100644 index dc0d5d140a75e10d2440f3c898eefdfd1a3cf1d4..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/src/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -#################################################################### -# -# Makefile for assembler -# OB, Feb 2013 -# -#################################################################### - -CC=~/local/clang+llvm-3.2-x86_64-apple-darwin11/bin/clang - -CFLAGS=-target i386 -S -Wdisabled-optimization -O0 -fverbose-asm - -all: - @for file in *.c ; do \ - ($(CC) $(CFLAGS) $${file}; ) ; done - @for file in *.c ; do \ - ($(CC) $${file}; ) ; done diff --git a/Exercices/QCM/S5/src/pthread_create.c b/Exercices/QCM/S5/src/pthread_create.c deleted file mode 100644 index 5edcc3c6cf12f9d5daeda0bee47628d608edd627..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/src/pthread_create.c +++ /dev/null @@ -1,63 +0,0 @@ -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourne %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} -// correct -void *f(void * param) { - // incomplet - return NULL; -} - -// incorrect -void *f1(void * param) { - // incomplet - return NULL; -} -// incorrect -void *f2(void param) { - // incomplet - return NULL; -} -// incorrect -void f3(void * param) { - // incomplet - return NULL; -} -// incorrect -void *f4(void ** param) { - // incomplet - return NULL; -} - - -int main (int argc, char *argv[]) { - - pthread_t t; - int err; - char *s; - char s1; - // correct - err=pthread_create(&t,NULL,&(f),(void *) s); - // incorrect - err=pthread_create(&t,NULL,&(f1),(void *) &(s)); - err=pthread_create(t,NULL,f2,s); - err=pthread_create(*t,NULL,*f3,(void *) *s); - err=pthread_create(&t,NULL,&(f),s1); - if(err!=0) - error(err,"pthread_create"); - - err=pthread_join(t,(void **) &r); - if(err!=0) - error(err,"pthread_join"); - - printf("%f \n",(float) (*r)); - - return(EXIT_SUCCESS); -} diff --git a/Exercices/QCM/S5/src/ptr1.c b/Exercices/QCM/S5/src/ptr1.c deleted file mode 100644 index f0c4a8372f81014106054c703c392720b25f5d54..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/src/ptr1.c +++ /dev/null @@ -1,46 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int a=1; -int * ptr; -int b=2; -int c=3; - -void f1() // correct -{ - ptr=&a; - -} - -void f3() // incorrect -{ - *ptr=a; - -} - -void f4() // incorrect -{ - ptr=(int) a; -} - -void f5() // incorrect -{ - int b=a; - ptr=&(b); - -} - -void f6() // incorrect -{ - ptr=&a+1; -} - - - -int main() { - - - -} - - diff --git a/Exercices/QCM/S5/src/ptr2.c b/Exercices/QCM/S5/src/ptr2.c deleted file mode 100644 index c6cc5c0073e2cc3e7bdfb8dbeb78ca11789e3cae..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/src/ptr2.c +++ /dev/null @@ -1,36 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int a[]={2,4,3,4,8}; -int * ptr; -int b; - -int main() { - int c; - - ptr=&(a[0]); - - f0: // correct - printf("%d %d %d %d\n",a[0],a[1],a[2],a[a[3]]); - - f1: // correct - printf("%d %d %d %d\n",*ptr,*(ptr+1),*(ptr+2),*(ptr+*(ptr+3))); - - f2: // incorrect - printf("%d %d %d %d\n",*ptr,*ptr+1,*ptr+2,*(ptr+*(ptr+3))); - - f3: // incorrect - printf("%d %d %d %d\n",*ptr,*(ptr++),(*ptr++),*(ptr+*(ptr++))); - - f4: // incorrect - printf("%d %d %d %d\n",*ptr,*(ptr+0),*(ptr+1),*ptr+*(ptr+2)); - - - f5: // incorrect - printf("%d %d %d %d\n",*ptr,*ptr+1,(*ptr+1),*(ptr+*(ptr+3))); - - - -} - - diff --git a/Exercices/QCM/S5/src/ptr3.c b/Exercices/QCM/S5/src/ptr3.c deleted file mode 100644 index 3e608e83d51b51f8a426f1f4d9c5ff0c0b581fc3..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/src/ptr3.c +++ /dev/null @@ -1,74 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int main() { - int c; - - int a[3][4]={ {0, 1, 2, 3} , - {4, 5, 6, 7} , - {8, 9, 10, 11} }; - - - int *ptr; - ptr=&(a[0][0]); - - int (*p_ptr)[4]; - p_ptr=a; - - /* - int a2[][]= { {0, 1} , - {2, 3, 4} , - {5, 6, 7 , 8} }; - */ - - - int* a1[3]; - int l0[]={0, 1}; - int l1[]={2, 3, 4}; - int l2[]={5, 6, 7, 9}; - a1[0]=l0; - a1[1]=l1; - a1[2]=l2; - - /* - int *a2=(int *) malloc(9*sizeof(int)); - int val=0; - for(int i=0;i<3;i++) { - for(int j=0;j<3+j++) { - *(a2+ - - int* a1[3]; - int l0[]={0, 1, 2}; - int l1[]={3, 4, 5}; - int l2[]={6, 7, 8}; - a1[0]=&(l0[0]); - a1[1]=&(l1[0]); - a1[2]=&(l2[0]); - */ - - - f0: // correct - printf("%d %d %d \n", a[0][2], a[2][1], a[1][3]); - - f1: // correct - printf("%d %d %d \n", *(ptr+2), *(ptr+2*4+1), *(*(p_ptr+1)+3)); - - f2: // incorrect - printf("%d %d %d \n", *(ptr+2), *(ptr+2*4+1), *(*(p_ptr+4*1)+3)); - - f3: // incorrect - printf("%d %d %d \n", *(ptr+2), *(ptr+2*3+1), *(*(p_ptr+3*1)+3)); - - - f4: // incorrect - compile pas - printf("%d %d %p \n", *ptr+2, *(ptr+2*4+1), *((p_ptr+1)+3)); - - - f5: // incorrect - printf("%d %d %d \n", *(ptr+2), *(ptr+2*4+1), *(*(p_ptr+1+3))); - - - -} - - diff --git a/Exercices/QCM/S5/src/ptr4.c b/Exercices/QCM/S5/src/ptr4.c deleted file mode 100644 index d0ad1f1ac8cd77ab0e07f2a15d9ee428548c4d6b..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/src/ptr4.c +++ /dev/null @@ -1,78 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char **argv) { - - int i=0; - - f0: // correct - while(i<argc) { - printf("%d %p %s\n",i,&(argv[i]),argv[i]); - i++; - } - - - i=0; - char **ptr3; - ptr3=argv; - while(i<argc) { - printf("%d %p %s\n",i,&(*ptr3),*ptr3); - i++; - ptr3++; - } - - i=0; - char **ptr; - ptr=argv; - while(i<argc) { - printf("%d %p %s\n",i,&(ptr),*ptr); - i++; - ptr++; - } - - - - // provoque un segmentation fault - /* - i=0; - char *ptr2; - ptr2=*argv; - while(i<argc) { - printf("%d %p %s\n",i,&(ptr2),*ptr2); - i++; - ptr2++; - } - */ - - /* ptr4.c:50:27: error: address expression must be an lvalue or a function - designator - printf("%d %p %s\n",i,&(argv+i),*(argv+i)); - - - i=0; - while(i<argc) { - printf("%d %p %s\n",i,&(argv+i),*(argv+i)); - i++; - } - - */ - /* -ptr4.c:61:40: warning: format specifies type 'char *' but the argument has type - 'char **' [-Wformat] - printf("%d %p %s\n",i,&(*(argv+i)),(argv+i)); - ~~ ^~~~~~~~ - - i=0; - while(i<argc) { - printf("%d %p %s\n",i,&(*(argv+i)),(argv+i)); - i++; - } - - */ - - - - -} - - diff --git a/Exercices/QCM/S5/src/ptr5.c b/Exercices/QCM/S5/src/ptr5.c deleted file mode 100644 index 615fc212141e8b5724bc92560abf178844a1fa9e..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/src/ptr5.c +++ /dev/null @@ -1,61 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char **argv) { - - int m[3][4]= { { 1, 2, 3, 4} , - { 5, 6, 7, 8} , - { 9, 10, 11, 12} }; - - printf("%p %d %d %d\n",m, m[1][2], m[0][5], m[2][2]); - - int *ptr; - - ptr=&(m[0][0]); - printf("%p %d %d %d\n",ptr, *(ptr+4*1+2), *(ptr+4*0+5), *(ptr+2*4+2)); - - /* invalide - int **ptr=m; - printf("%p %d %d %d\n",ptr, *(ptr+4*1+2), *(ptr+4*0+5), *(ptr+2*4+2)); - */ - - /* invalide - int *ptr1=m; - printf("%p %d %d %d\n",ptr1, *(ptr1+4*1+2), *(ptr1+4*0+5), *(ptr1+2*4+2)); - */ - - - /* - -ptr5.c:28:26: warning: format specifies type 'void *' but the argument has type - 'int' [-Wformat] - printf("%p %d %d %d\n",*ptr, ptr+4*1+2, ptr+4*0+5, ptr+2*4+2); - ~~ ^~~~ - %d -ptr5.c:28:32: warning: format specifies type 'int' but the argument has type - 'int *' [-Wformat] - printf("%p %d %d %d\n",*ptr, ptr+4*1+2, ptr+4*0+5, ptr+2*4+2); - ~~ ^~~~~~~~~ -ptr5.c:28:43: warning: format specifies type 'int' but the argument has type - 'int *' [-Wformat] - printf("%p %d %d %d\n",*ptr, ptr+4*1+2, ptr+4*0+5, ptr+2*4+2); - ~~ ^~~~~~~~~ -ptr5.c:28:54: warning: format specifies type 'int' but the argument has type - 'int *' [-Wformat] - printf("%p %d %d %d\n",*ptr, ptr+4*1+2, ptr+4*0+5, ptr+2*4+2); - ~~ ^~~~~~~~~ - - ptr=&(m[0][0]); - printf("%p %d %d %d\n",*ptr, ptr+4*1+2, ptr+4*0+5, ptr+2*4+2); - */ - - /* - ptr=&(m); - printf("%p %d %d %d\n",&ptr, *ptr+4*1+2, *ptr+4*0+5, *ptr+2*4+2); - */ - - - -} - - diff --git a/Exercices/QCM/S5/src/thread1.c b/Exercices/QCM/S5/src/thread1.c deleted file mode 100644 index d2c85d84d65cf5481111e03188f3b9b639ee286a..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/src/thread1.c +++ /dev/null @@ -1,68 +0,0 @@ -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -struct Array { - int length; - int *tab; -}; - -typedef struct Array Array_t; - - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourne %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - - -void *thread_min(void * param) { - Array_t *a=(Array_t *) param; - int *r=(int *)malloc(sizeof(int)); - *r=a->tab[0]; - for(int i=1;i<a->length;i++) { - if(a->tab[i]<*r) - *r=a->tab[i]; - } - - return((void *) r); -} - -void *thread_max(void * param) { - Array_t *a=(Array_t *) param; - int *r=(int *)malloc(sizeof(int)); - *r=a->tab[0]; - for(int i=1;i<a->length;i++) { - if(a->tab[i]>*r) - *r=a->tab[i]; - } - - return((void *) r); -} - -int main (int argc, char *argv[]) { - - int tab[]={12, 4, 3, 7, 8 , 9 , 10}; - Array_t array = {.length=7, .tab=tab}; - pthread_t first; - pthread_t second; - int *r_min; - int *r_max; - - int err; - int min; - int max; - err=pthread_create(&first,NULL,&thread_min,&(array)); - if(err!=0) - error(err,"pthread_create"); - - err=pthread_join(first,(void **) &r_min); - if(err!=0) - error(err,"pthread_join"); - - printf("min:%ld \n",(long) (*r_min)); - - return(EXIT_SUCCESS); -} diff --git a/Exercices/QCM/S5/src/thread_create.c b/Exercices/QCM/S5/src/thread_create.c deleted file mode 100644 index 1f747f1afe4bdc5f8b9d16fe910bfdb00bfc3fa6..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/src/thread_create.c +++ /dev/null @@ -1,54 +0,0 @@ -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -struct fraction { - int num; - int denum; -}; - -typedef struct fraction Fraction_t; - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourne %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -float tofloat(Fraction_t t) { - return (float) t.num/ (float) t.denum; - -} - - -void *mythread(void * param) { - Fraction_t f=(Fraction_t ) param; - float r; - r=(float) f->num/ (float) f->denum; - return((void *) r); -} - -int main (int argc, char *argv[]) { - - - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - printf("%f \n",tofloat(f)); - float *r; - int err; - - err=pthread_create(&t,NULL,&mythread,&(f)); - if(err!=0) - error(err,"pthread_create"); - - err=pthread_join(t,(void **) &r); - if(err!=0) - error(err,"pthread_join"); - - printf("%f \n",(float) (*r)); - - return(EXIT_SUCCESS); -} diff --git a/Exercices/QCM/S5/src/thread_create2.c b/Exercices/QCM/S5/src/thread_create2.c deleted file mode 100644 index b6ff19081dc28a1b4c6151e572fe18bb49a1e16e..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/src/thread_create2.c +++ /dev/null @@ -1,54 +0,0 @@ -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -struct fraction { - int num; - int denum; -}; - -typedef struct fraction Fraction_t; - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourne %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -float tofloat(Fraction_t t) { - return (float) t.num/ (float) t.denum; - -} - - -void *mythread(void * param) { - Fraction_t *f=(Fraction_t *) param; - float *r=(float *)malloc(sizeof(float)); - *r=(float) f->num/ (float) f->denum; - return((void *) r); -} - -int main (int argc, char *argv[]) { - - - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - printf("%f \n",tofloat(f)); - float *r; - int err; - - err=pthread_create(&t,NULL,&mythread,&(f)); - if(err!=0) - error(err,"pthread_create"); - - err=pthread_join(t,(void **) &r); - if(err!=0) - error(err,"pthread_join"); - - printf("%f \n",(float) (*r)); - - return(EXIT_SUCCESS); -} diff --git a/Exercices/QCM/S5/src/thread_create3.c b/Exercices/QCM/S5/src/thread_create3.c deleted file mode 100644 index ba9cb48743ec693ef9a752a46caf87577ebb003d..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/src/thread_create3.c +++ /dev/null @@ -1,54 +0,0 @@ -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -struct fraction { - int num; - int denum; -}; - -typedef struct fraction Fraction_t; - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourne %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -float tofloat(Fraction_t t) { - return (float) t.num/ (float) t.denum; - -} - - -void *mythread(void * param) { - Fraction_t f= *param; - float r; - r=(float) f.num/ (float) f.denum; - return((void *) &r); -} - -int main (int argc, char *argv[]) { - - - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - printf("%f \n",tofloat(f)); - float *r; - int err; - - err=pthread_create(&t,NULL,&mythread,&(f)); - if(err!=0) - error(err,"pthread_create"); - - err=pthread_join(t,(void **) &r); - if(err!=0) - error(err,"pthread_join"); - - printf("%f \n",(float) (*r)); - - return(EXIT_SUCCESS); -} diff --git a/Exercices/QCM/S5/src/thread_create4.c b/Exercices/QCM/S5/src/thread_create4.c deleted file mode 100644 index eeb38998e85ee60173d3e637504938a2fd6a110b..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/src/thread_create4.c +++ /dev/null @@ -1,55 +0,0 @@ -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -struct fraction { - int num; - int denum; -}; - -typedef struct fraction Fraction_t; - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourne %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -float tofloat(Fraction_t t) { - return (float) t.num/ (float) t.denum; - -} - - -void *mythread(void * param) { - Fraction_t *t=(Fraction_t *) param; - float *r=(float *)malloc(sizeof(float)); - *r=(float) t->num/ (float) t->denum; - return((void *) r); -} - -int main (int argc, char *argv[]) { - - - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - printf("%f \n",tofloat(f)); - float *r; - int err; - - err=pthread_create(&t,NULL,&mythread,&f); - if(err!=0) - error(err,"pthread_create"); - - r=pthread_join(t,NULL); - - if(err!=0) - error(err,"pthread_join"); - - printf("%f \n",(float) (*r)); - - return(EXIT_SUCCESS); -} diff --git a/Exercices/QCM/S5/src/thread_create5.c b/Exercices/QCM/S5/src/thread_create5.c deleted file mode 100644 index 5e617db17e72193e93dfc257814b8f47ecd8e1a1..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/src/thread_create5.c +++ /dev/null @@ -1,53 +0,0 @@ -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -struct fraction { - int num; - int denum; -}; - -typedef struct fraction Fraction_t; - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourne %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -float tofloat(Fraction_t t) { - return (float) t.num/ (float) t.denum; - -} - - -float mythread(Fraction_t param) { - float *r=(float *)malloc(sizeof(float)); - *r=(float) param->num/ (float) param->denum; - return(r); -} - -int main (int argc, char *argv[]) { - - - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - printf("%f \n",tofloat(f)); - float *r; - int err; - - err=pthread_create(&t,NULL,&mythread,&(f)); - if(err!=0) - error(err,"pthread_create"); - - err=pthread_join(t,(void *) &r); - if(err!=0) - error(err,"pthread_join"); - - printf("%f \n",(float) (*r)); - - return(EXIT_SUCCESS); -} diff --git a/Exercices/QCM/S5/src/thread_createok.c b/Exercices/QCM/S5/src/thread_createok.c deleted file mode 100644 index b6ff19081dc28a1b4c6151e572fe18bb49a1e16e..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S5/src/thread_createok.c +++ /dev/null @@ -1,54 +0,0 @@ -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -struct fraction { - int num; - int denum; -}; - -typedef struct fraction Fraction_t; - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourne %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -float tofloat(Fraction_t t) { - return (float) t.num/ (float) t.denum; - -} - - -void *mythread(void * param) { - Fraction_t *f=(Fraction_t *) param; - float *r=(float *)malloc(sizeof(float)); - *r=(float) f->num/ (float) f->denum; - return((void *) r); -} - -int main (int argc, char *argv[]) { - - - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - printf("%f \n",tofloat(f)); - float *r; - int err; - - err=pthread_create(&t,NULL,&mythread,&(f)); - if(err!=0) - error(err,"pthread_create"); - - err=pthread_join(t,(void **) &r); - if(err!=0) - error(err,"pthread_join"); - - printf("%f \n",(float) (*r)); - - return(EXIT_SUCCESS); -} diff --git a/Exercices/QCM/S6/Makefile b/Exercices/QCM/S6/Makefile deleted file mode 100755 index 927fa5b1280bc94fedde37ee2771dacdf46adfe8..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S6/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -#################################################################### -# -# Makefile for SINF1252 QCM -# OB, Jan 2013 -# -#################################################################### - -MISSION=6 - -DEST=../../../web/qcm - -EXNAME=$(DEST)/Mission-$(MISSION)-qcm.html - -RST_FILES=qcm-$(MISSION).rst - -CSS=../rst-form/css/html4css1.css,../rst-form/css/rst-form.css,../rst-form/css/pygments.css - -.PHONY : qcm all - -qcm: $(EXNAME) - -$(EXNAME): $(RST_FILES) - @for i in $(RST_FILES); do\ - ( rst2html.py --stylesheet-path=$(CSS) $$i > $(EXNAME) ; ) ; done - - -all: qcm - -clean: - -rm -r $(EXNAME) diff --git a/Exercices/QCM/S6/qcm-6.rst b/Exercices/QCM/S6/qcm-6.rst deleted file mode 100644 index 3448586adeb982dc838972bed3f2c4141a0ebe5e..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S6/qcm-6.rst +++ /dev/null @@ -1,501 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. raw:: html - - <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script> - <script type="text/javascript" src="js/jquery-shuffle.js"></script> - <script type="text/javascript" src="js/rst-form.js"></script> - <script type="text/javascript" src="js/prettify.js"></script> - <script type="text/javascript">$nmbr_prop = 3</script> - - -=============== -Sixième Semaine -=============== - -Cette semaine porte sur la communication et la synchronisation entre threads. Plus précisément, la matière est décrite dans les deux sections suivantes : - - -.. - :ref:`complementsC` - -- `Communication entre threads <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/Threads/threads2.html>`_ -- `Coordination entre threads <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/Threads/threads2.html#coordination-entre-threads>`_ - -.. - :ref:`thread` - -Question 1. Algorithme de Peterson ----------------------------------- - -L'algorithme de Peterson peut s'écrire de différentes façons. Pour bien comprendre son fonctionnement, il est utile de réfléchir à d'autres formulations que celle utilisées dans le syllabus. Parmi les fragments de code ci-dessous, un seul implémente correctement l'algorithme de Peterson. Lequel ? - - -.. class:: positive - -- - .. code-block:: console - - /* initialisation */ - bool in1 = false; - bool in2 = false; - int last = 1; - // thread 1 - while (true) { - in1 = true; - last = 1; - while ( in2 && (last==1)) {}; - section_critique(); - in1=false; - // ... - } - // thread2 - while (true) { - in2 = true; - last = 2; - while ( in1 && (last==2)) {}; - section_critique(); - in2=false; - // ... - } - -- - .. code-block:: console - - /* initialisation */ - bool in1 = false; - bool in2 = false; - int last = 2; - // thread 1 - while (true) { - in1 = true; - last = 1; - while ( in2 && (last==1)) {}; - section_critique(); - in1=false; - // ... - } - // thread2 - while (true) { - in2 = true; - last = 2; - while ( in1 && (last==2)) {}; - section_critique(); - in2=false; - // ... - } - -.. class:: negative - -- - .. code-block:: console - - // initialisation - bool in1 = false; - bool in2 = false; - int last = 1; - // thread 1 - while (true) { - in1 = true; - last = 1; - while ( in1 && (last==1)) {}; - section_critique(); - in1=false; - // ... - } - // thread2 - while (true) { - in2 = true; - last = 2; - while ( in2 && (last==2)) {}; - section_critique(); - in2=false; - // ... - } - - .. class:: comment - - Cette solution ne fonctionne pas. Si un des deux threads est seul, il n'entrera jamais en section critique. - -- - .. code-block:: console - - // initialisation - bool in1 = false; - bool in2 = false; - int last = 2; - // thread 1 - while (true) { - in1 = true; - last = 1; - while ( in2 && (last==2)) {}; - section_critique(); - in1=false; - // ... - } - // thread2 - while (true) { - in2 = true; - last = 2; - while ( in1 && (last==1)) {}; - section_critique(); - in2=false; - // ... - } - - .. class:: comment - - Cette solution ne fonctionne pas. Il est possible que le thread 1 rentre en section critique puis le thread 2 met ``last`` à 2 et peut également y entrer sans que thread 1 n'en soit sorti. - -- - .. code-block:: console - - // initialisation - bool in1 = false; - bool in2 = false; - int last = 1; - // thread 1 - while (true) { - last = 1; - in1 = true; - while ( in2 && (last==1)) {}; - section_critique(); - in1=false; - // ... - } - // thread2 - while (true) { - last = 2; - in2 = true; - while ( in1 && (last==2)) {}; - section_critique(); - in2=false; - // ... - } - - .. class:: comment - - Cette solution ne fonctionne pas. Il y a un risque de violation de section critique. Si le thread 1 fait ``last=1;`` puis est interrompu avant de faire ``in1=true;``. Le thread 2 exécute alors ``last=2;`` suivi de ``in2=true;``. A cet instant, ``in2==false`` et le thread 2 rentre en section critique puisque ``in1==false``. Le thread 1 se réveille et exécute ``in1=true;``. Il peut ensuite immédiatement entre en section critique puisque ``last`` vaut ``2`` à cet instant. - -Question 2. Initialisation de mutex ------------------------------------ - -Avant de pouvoir utiliser un mutex POSIX, il est nécessaire de déclarer la structure correspondante et initialiser le mutex. Parmi les fragments de code ci-dessous, lequel est celui qui déclare et initialise correctement un mutex ? - -.. class:: positive - -- - .. code-block:: console - - pthread_mutex_t mutex; - pthread_mutexattr_t attr; - - err= pthread_mutexattr_init(&attr); - if(err!=0) - error(err,"pthread_mutexattr_init"); - - err=pthread_mutex_init( &mutex, &attr); - if(err!=0) - error(err,"pthread_mutex_init"); - - .. class:: comment - - Notez que dans ce cas, le mutex est initialisé avec les attributs par défaut. - - -- - .. code-block:: console - - pthread_mutex_t mutex; - - err=pthread_mutex_init( &mutex, NULL); - if(err!=0) - error(err,"pthread_mutex_init"); - - .. class:: comment - - Notez que dans ce cas, le mutex est initialisé avec les attributs par défaut. - -.. class:: negative - -- - .. code-block:: console - - pthread_mutex_t mutex; - pthread_mutexattr_t attr; - - err= pthread_mutexattr_init(attr); - if(err!=0) - error(err,"pthread_mutexattr_init"); - - err=pthread_mutex_init(mutex, attr); - if(err!=0) - error(err,"pthread_mutex_init"); - - .. class:: comment - - Tant `pthread_mutexattr_init(3posix)`_ que `pthread_mutex_init(3posix)`_ prennent comme arguments un *pointeur* vers une structure de type ``pthread_mutex_t``. Ces deux fonctions modifient le contenu de cette structure et doivent donc en recevoir l'adresse comme argument. - - - -- - .. code-block:: console - - pthread_mutex_t mutex; - pthread_mutexattr_t attr; - - err= pthread_mutexattr_init(&attr); - if(err!=0) - error(err,"pthread_mutexattr_init"); - - err=pthread_mutex_init(&mutex, attr); - if(err!=0) - error(err,"pthread_mutex_init"); - - .. class:: comment - - Tant `pthread_mutexattr_init(3posix)`_ que `pthread_mutex_init(3posix)`_ prennent comme arguments un *pointeur* vers une structure de type ``pthread_mutex_t``. Ces deux fonctions modifient le contenu de cette structure et doivent donc en recevoir l'adresse comme argument. - - -- - .. code-block:: console - - pthread_mutex_t *mutex; - pthread_mutexattr_t *attr; - - err= pthread_mutexattr_init(attr); - if(err!=0) - error(err,"pthread_attr_init"); - - err=pthread_mutex_init(mutex, attr); - if(err!=0) - error(err,"pthread_mutex_init"); - - .. class:: comment - - Tant `pthread_mutexattr_init(3posix)`_ que `pthread_mutex_init(3posix)`_ prennent comme arguments un *pointeur* vers une structure de type ``pthread_mutex_t``. La mémoire permettant de stocker ces deux structures doit avoir été réservée en utilisant `malloc(3)`_ avant de faire appel à ces deux fonctions. - - - -Question 3. Utilisation de `pthread_mutex_lock(3posix)`_ et `pthread_mutex_unlock(3posix)`_ -------------------------------------------------------------------------------------------- - -Un programme utilisant plusieurs threads doit mettre à jour une variable globale partagée entre tous les threads. Pour cela, le développeur écrit une fonction ``update`` qui prend comme arguments la variable à mettre à jour et le mutex qui y est associé. Parmi les extraits ci-dessous, lequel permet de mettre à jour la variable sans risque de contention entre les threads qui y accèdent ? - -.. class:: positive - -- - .. code-block:: console - - void update(int * val, pthread_mutex_t * mutex) { - - err=pthread_mutex_lock(mutex); - if(err!=0) - error(err,"pthread_mutex_lock"); - - // mise à jour de la variable globale - - err=pthread_mutex_unlock(mutex); - if(err!=0) - error(err,"pthread_mutex_unlock"); - - } - - -.. class:: negative - -- - .. code-block:: console - - void update(int * val, pthread_mutex_t * mutex) { - - err=pthread_mutex_unlock(mutex); - if(err!=0) - error(err,"pthread_mutex_unlock"); - - // mise à jour de la variable globale - - err=pthread_mutex_lock(mutex); - if(err!=0) - error(err,"pthread_mutex_lock"); - - } - - .. class:: comment - - Ce code est incorrect. Un mutex s'utilise en faisant d'abord ``pthread_mutex_lock`` et ensuite ``pthread_mutex_unlock``. - -- - .. code-block:: console - - void update(int val, pthread_mutex_t mutex) { - - err=pthread_mutex_lock(mutex); - if(err!=0) - error(err,"pthread_mutex_lock"); - - // mise à jour de la variable globale - - err=pthread_mutex_unlock(mutex); - if(err!=0) - error(err,"pthread_mutex_unlock"); - - } - - .. class:: comment - - L'utilisation de cette fonction implique que la structure ``pthread_mutex_t`` doit être copiée sur le stack avant de pouvoir être utilisée par la fonction. Cette solution ne peut fonctionner car la structure de données qui contient toute l'information relative à un mutex et placée à un endroit donné en mémoire et ne peut pas être copiée. - - - -- - .. code-block:: console - - void update(int * val, pthread_mutex_t mutex) { - - err=pthread_mutex_lock(&mutex); - if(err!=0) - error(err,"pthread_mutex_lock"); - - // mise à jour de la variable globale - - err=pthread_mutex_unlock(&mutex); - if(err!=0) - error(err,"pthread_mutex_unlock"); - - } - - .. class:: comment - - L'utilisation de cette fonction implique que la structure ``pthread_mutex_t`` doit être copiée sur le stack avant de pouvoir être utilisée par la fonction. Cette solution ne peut fonctionner car la structure de données qui contient toute l'information relative à un mutex et placée à un endroit donné en mémoire et ne peut pas être copiée. - - - -Question 4. Utilisation de plusieurs mutex ------------------------------------------- - -Dans certains programmes, il est nécessaire de définir plusieurs mutex qui sont utilisés par différents threads pour gérer l'accès à des variables partagées. Considérons un programme qui utilise trois variables globales et est découpé en plusieurs threads. - -.. code-block:: console - - long a=5; // variable globale partagée - long b=7; // variable globale partagée - long c=9; // variable globale partagée - - pthread_mutex_t x; // variable globale associée à a - pthread_mutex_t y; // variable globale associée à b - pthread_mutex_t z; // variable globale associée à c - - - void update(int * val1, int * val2, pthread_mutex_t * mutex1, pthread_mutex_t * mutex2) { - - err=pthread_mutex_lock(mutex1); - if(err!=0) - error(err,"pthread_mutex_lock"); - err=pthread_mutex_lock(mutex2); - if(err!=0) - error(err,"pthread_mutex_lock"); - - // mise à jour val1 - // mise à jour val2 - - err=pthread_mutex_unlock(mutex1); - if(err!=0) - error(err,"pthread_mutex_unlock"); - - err=pthread_mutex_unlock(mutex2); - if(err!=0) - error(err,"pthread_mutex_unlock"); - - } - -Ce programme utilise plusieurs threads qui modifient les variables ``a``, ``b`` et ``c``. Parmi les fragments de code ci-dessous qui utilisent plusieurs threads, un seul est correct. Lequel ? - -.. class:: positive - -- - .. code-block:: console - - // thread A - - update(&a,&b,&x,&y); - update(&a,&c,&x,&z); - - // thread B - - update(&b,&c,&y,&z); - update(&a,&c,&x,&z); - - -- - .. code-block:: console - - // thread A - - update(&a,&b,&x,&y); - update(&b,&c,&y,&z); - - // thread B - - update(&b,&c,&y,&z); - update(&a,&c,&x,&z); - - -.. class:: negative - -- - .. code-block:: console - - // thread A - - update(&a,&b,&x,&y); - update(&c,&a,&z,&x); - - // thread B - - update(&b,&c,&y,&z); - update(&a,&c,&x,&z); - - .. class:: comment - - Lorsqu'un thread utilise plusieurs ressources protégées par un mutex, il est important que les accès à ces mutex se fassent chaque fois dans le même ordre. Dans cet exemple, il faut toujours accéder à ``x`` puis à ``y`` puis à ``z`` (ou un autre ordre). Accéder à ``z`` puis à ``x`` dans le thread A et à ``x`` puis à ``z`` dans le thread B est une source de deadlocks potentiels. - - -- - .. code-block:: console - - // thread A - - update(&a,&b,&x,&y); - update(&a,&c,&x,&z); - - // thread B - - update(&b,&c,&y,&z); - update(&c,&a,&z,&x); - - .. class:: comment - - Lorsqu'un thread utilise plusieurs ressources protégées par un mutex, il est important que les accès à ces mutex se fassent chaque fois dans le même ordre. Dans cet exemple, il faut toujours accéder à ``x`` puis à ``y`` puis à ``z`` (ou un autre ordre). Accéder à ``z`` puis à ``x`` dans le thread B et à ``x`` puis à ``z`` dans le thread A est une source de deadlocks potentiels. - -- - .. code-block:: console - - // thread A - - update(&a,&b,&x,&y); - update(&a,&b,&x,&y); - - // thread B - - update(&b,&a,&y,&x); - update(&a,&c,&x,&z); - - .. class:: comment - - Lorsqu'un thread utilise plusieurs ressources protégées par un mutex, il est important que les accès à ces mutex se fassent chaque fois dans le même ordre. Dans cet exemple, il faut toujours accéder à ``x`` puis à ``y`` puis à ``z`` (ou un autre ordre). Accéder à ``a`` puis à ``y`` dans le thread A et à ``y`` puis à ``x`` dans le thread B est une source de deadlocks potentiels. - - -.. include:: ../../../links.rst -.. include:: ../../../man_links.rst -.. include:: ../../../incl_links.rst diff --git a/Exercices/QCM/S6/src/pthread-mutex.c b/Exercices/QCM/S6/src/pthread-mutex.c deleted file mode 100644 index 2a925f669147e2813c785171c3c08f946dab3fe1..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S6/src/pthread-mutex.c +++ /dev/null @@ -1,135 +0,0 @@ -/************************************** - * pthread-mutex.c - * - * Programme d'exemple de pthread avec - * utilisation de mutex pour éviter une - * violation de section critique - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -///AAA -#include <pthread.h> -#define NTHREADS 4 - -long a=5; -long b=7; -long c=9; - -pthread_mutex_t x; -pthread_mutex_t y; -pthread_mutex_t z; - - -void update(int * val, pthread_mutex_t * mutex) { - - err=pthread_mutex_lock(mutex); - if(err!=0) - error(err,"pthread_mutex_lock"); - *val=(*val)+1; - err=pthread_mutex_unlock(mutex); - if(err!=0) - error(err,"pthread_mutex_unlock"); - return NULL; -} - -void update2(int * val1, int * val2, pthread_mutex_t * mutex1, pthread_mutex_t * mutex2) { - - err=pthread_mutex_lock(mutex1); - if(err!=0) - error(err,"pthread_mutex_lock"); - err=pthread_mutex_lock(mutex2); - if(err!=0) - error(err,"pthread_mutex_lock"); - - *val1=(*val2)+1; - *val2=(*val1)+1; - - err=pthread_mutex_unlock(mutex1); - if(err!=0) - error(err,"pthread_mutex_unlock"); - - err=pthread_mutex_unlock(mutex2); - if(err!=0) - error(err,"pthread_mutex_unlock"); - -} - - -void update3(int * val1, int * val2, int * val3, pthread_mutex_t * mutex1, pthread_mutex_t * mutex2, pthrad_mutex_t * mutex3) { - - err=pthread_mutex_lock(mutex1); - if(err!=0) - error(err,"pthread_mutex_lock"); - err=pthread_mutex_lock(mutex2); - if(err!=0) - error(err,"pthread_mutex_lock"); - - *val1=(*val2)+1; - *val2=(*val1)+1; - - err=pthread_mutex_unlock(mutex1); - if(err!=0) - error(err,"pthread_mutex_unlock"); - - err=pthread_mutex_unlock(mutex2); - if(err!=0) - error(err,"pthread_mutex_unlock"); - -} - - -void *func(void * param) { - int err; - for(int j=0;j<1000000;j++) { - err=pthread_mutex_lock(&mutex_global); - if(err!=0) - error(err,"pthread_mutex_lock"); - global=increment(global); - err=pthread_mutex_unlock(&mutex_global); - if(err!=0) - error(err,"pthread_mutex_unlock"); - } - return(NULL); -} - -int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - - err=pthread_mutex_init( &mutex_global, NULL); - if(err!=0) - error(err,"pthread_mutex_init"); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&func,NULL); - if(err!=0) - error(err,"pthread_create"); - } - for(int i=0; i<1000000000;i++) { /*...*/ } - - for(int i=NTHREADS-1;i>=0;i--) { - err=pthread_join(thread[i],NULL); - if(err!=0) - error(err,"pthread_join"); - } - - err=pthread_mutex_destroy(&mutex_global); - if(err!=0) - error(err,"pthread_mutex_destroy"); - - printf("global: %ld\n",global); - - return(EXIT_SUCCESS); -} diff --git a/Exercices/QCM/S7/Makefile b/Exercices/QCM/S7/Makefile deleted file mode 100755 index 54ca3477f946acc1f5d631df24308320b7df3fe4..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S7/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -#################################################################### -# -# Makefile for SINF1252 QCM -# OB, Jan 2013 -# -#################################################################### - -MISSION=7 - -DEST=../../../web/qcm - -EXNAME=$(DEST)/Mission-$(MISSION)-qcm.html - -RST_FILES=qcm-$(MISSION).rst - -CSS=../rst-form/css/html4css1.css,../rst-form/css/rst-form.css,../rst-form/css/pygments.css - -.PHONY : qcm all - -qcm: $(EXNAME) - -$(EXNAME): $(RST_FILES) - @for i in $(RST_FILES); do\ - ( rst2html.py --stylesheet-path=$(CSS) $$i > $(EXNAME) ; ) ; done - - -all: qcm - -clean: - -rm -r $(EXNAME) diff --git a/Exercices/QCM/S7/qcm-7.rst b/Exercices/QCM/S7/qcm-7.rst deleted file mode 100644 index fca3b49985ebc412fe9584a5e79204a0806c1257..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S7/qcm-7.rst +++ /dev/null @@ -1,424 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. raw:: html - - <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script> - <script type="text/javascript" src="js/jquery-shuffle.js"></script> - <script type="text/javascript" src="js/rst-form.js"></script> - <script type="text/javascript" src="js/prettify.js"></script> - <script type="text/javascript">$nmbr_prop = 4</script> - - -================ -Septième semaine -================ - - -Question 1. Utilisation des sémaphores --------------------------------------- - -Avant d'être utilisé, un sémaphore doit être déclaré et initialisé. Après son utilisation, il doit être détruit. Parmi les séquences d'instructions ci-dessous, une seule initialise correctement un sémaphore à la valeur 1. Laquelle ? - -.. class:: positive - -- - .. code-block:: console - - sem_t semaphore; - - sem_init(&semaphore, 0,1); - - // ... - - sem_destroy(&semaphore); - - -- - .. code-block:: console - - sem_t *semaphore; - semaphore=(sem_t *)malloc(sizeof(struct sem_t)); - if (semaphore==NULL) - error("malloc"); - - sem_init(semaphore, 0,1); - - // ... - - sem_destroy(semaphore); - - -.. class:: negative - -- - .. code-block:: console - - sem_t semaphore; - - sem_init(semaphore, 1,0); - - // ... - - sem_destroy(semaphore); - - .. class:: comment - - `sem_init(3)`_ et `sem_destroy(3)`_ prennent comme premier argument un pointeur vers une structure ``sem_t``. `sem_init(3)`_ prend comme troisième argument la valeur initiale du sémaphore. - -- - .. code-block:: console - - sem_t semaphore; - - sem_init(&semaphore, 1,0); - - // ... - - sem_destroy(&semaphore); - - .. class:: comment - - `sem_init(3)`_ prend comme troisième argument la valeur initiale du sémaphore. - -- - .. code-block:: console - - sem_t *semaphore; - semaphore=(sem_t *)malloc(sizeof(struct sem_t)); - if (semaphore==NULL) - error("malloc"); - - sem_init(semaphore, 1, 0); - - // ... - - sem_destroy(semaphore); - - .. class:: comment - - `sem_init(3)`_ prend comme troisième argument la valeur initiale du sémaphore. - - -- - .. code-block:: console - - sem_t *semaphore; - semaphore=(sem_t *)malloc(sizeof(struct sem_t)); - if (semaphore==NULL) - error("malloc"); - - sem_init(semaphore, 1, 0); - - // ... - - sem_destroy(&semaphore); - - .. class:: comment - - `sem_init(3)`_ prend comme troisième argument la valeur initiale du sémaphore. `sem_destroy(3)`_ prend comme premier argument un pointeur vers une structure ``sem_t``. - - - -Question 2. Exclusion mutuelle ------------------------------- - -Les sémaphores peuvent être utilisés tout comme les mutex pour résoudre des problèmes d'exclusion mutuelle. Parmi les extraits de programmes ci-dessous, une seule est une solution correcte au problème de l'exclusion mutuelle en utilisant des sémaphores. Laquelle ? - -.. class:: positive - -- - .. code-block:: console - - - static sem_t semaphore; - long global=0; - - int increment(int i) { - // ... - } - - void *inc(void * param) { - for(int j=0;j<1000000;j++) { - sem_wait(&semaphore); - global=increment(global); - sem_post(&semaphore); - } - } - - int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - - sem_init(&semaphore, 0,1); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&inc,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - // reste non fourni - } -- - .. code-block:: console - - - sem_t * semaphore; - long global=0; - - int increment(int i) { - // ... - } - - void *inc(void * param) { - for(int j=0;j<1000000;j++) { - sem_wait(semaphore); - global=increment(global); - sem_post(semaphore); - } - } - - int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - semaphore=(sem_t *)malloc(sizeof(sem_t)) - if(semaphore==NULL) - error("malloc"); - - sem_init(semaphore, 0,1); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&inc,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - // reste non fourni - } - -.. class:: negative - -- - .. code-block:: console - - - static sem_t semaphore; - long global=0; - - int increment(int i) { - // ... - } - - void *inc(void * param) { - for(int j=0;j<1000000;j++) { - sem_wait(&semaphore); - global=increment(global); - sem_post(&semaphore); - } - } - - int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - - sem_init(&semaphore, 0,0); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&inc,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - // reste non fourni - } - - .. class:: comment - - Pour résoudre un problème d'exclusion mutuelle, il faut initialiser le sémaphore à ``1`` avec `sem_init(3)`_ et non à ``0`` comme dans cet exemple. - -- - .. code-block:: console - - - static sem_t semaphore; - long global=0; - - int increment(int i) { - // ... - } - - void *inc(void * param) { - for(int j=0;j<1000000;j++) { - sem_post(&semaphore); - global=increment(global); - sem_wait(&semaphore); - } - } - - int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - - sem_init(&semaphore, 0,0); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&inc,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - // reste non fourni - } - - .. class:: comment - - Pour résoudre un problème d'exclusion mutuelle, il faut initialiser le sémaphore à ``1`` avec `sem_init(3)`_ et non à ``0`` comme dans cet exemple. En outre, l'accès à la section critique doit être précédée par un appel à `sem_wait(3)`_ et suivie par un appel à `sem_post(3)`_ et non l'inverse comme dans cet exemple. - -- - .. code-block:: console - - - sem_t * semaphore; - long global=0; - - int increment(int i) { - // ... - } - - void *inc(void * param) { - for(int j=0;j<1000000;j++) { - sem_wait(semaphore); - global=increment(global); - sem_post(semaphore); - } - } - - int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - semaphore=(sem_t *)malloc(sizeof(sem_t)) - if(semaphore==NULL) - error("malloc"); - - sem_init(semaphore, 0,0); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&inc,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - // reste non fourni - } - - .. class:: comment - - Pour résoudre un problème d'exclusion mutuelle, il faut initialiser le sémaphore à ``1`` avec `sem_init(3)`_ et non à ``0`` comme dans cet exemple. - -- - .. code-block:: console - - - sem_t * semaphore; - long global=0; - - int increment(int i) { - // ... - } - - void *inc(void * param) { - for(int j=0;j<1000000;j++) { - sem_post(semaphore); - global=increment(global); - sem_wait(semaphore); - } - } - - int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - semaphore=(sem_t *)malloc(sizeof(sem_t)) - if(semaphore==NULL) - error("malloc"); - - sem_init(semaphore, 0,0); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&inc,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - // reste non fourni - } - - .. class:: comment - - Pour résoudre un problème d'exclusion mutuelle, il faut initialiser le sémaphore à ``1`` avec `sem_init(3)`_ et non à ``0`` comme dans cet exemple. En outre, l'accès à la section critique doit être précédée par un appel à `sem_wait(3)`_ et suivie par un appel à `sem_post(3)`_ et non l'inverse comme dans cet exemple. - - - -Question 3. Fonctions 'thread-safe' ------------------------------------ - -La plupart des fonctions de la librairie standard sont des fonctions thread-safe, c'est-à -dire des fonctions que l'on peut utiliser dans plusieurs threads distincts sans risquer de problèmes d'accès concurrent. Cependant, certaines fonctions, souvent parmi les plus anciennes, ne sont pas thread-safe. Parmi les fonctions ci-dessous, une seule est thread-safe. Laquelle ? - -.. class:: positive - -- `gettimeofday(2)`_ - - .. class:: comment - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - -- `strsep(3)`_ - - .. class:: comment - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - -.. class:: negative - -- `getenv(3)`_ - - .. class:: comment - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - -- `getopt(3)`_ - - .. class:: comment - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - -- `asctime(3)`_ - - .. class:: comment - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - -- `strtok(3)`_ - - .. class:: comment - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - -- `strerror(3)`_ - - .. class:: comment - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - -- `getopt(3)`_ - - .. class:: comment - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - - - -.. include:: ../../../links.rst -.. include:: ../../../man_links.rst -.. include:: ../../../incl_links.rst diff --git a/Exercices/QCM/S7/src/pthread-mutex-perf.c b/Exercices/QCM/S7/src/pthread-mutex-perf.c deleted file mode 100644 index 05f3448d35f69e3ddd3c74927d433f6ec406a52f..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S7/src/pthread-mutex-perf.c +++ /dev/null @@ -1,131 +0,0 @@ -/************************************** - * pthread-mutex.c - * - * Programme d'exemple de pthread avec - * utilisation de mutex pour éviter une - * violation de section critique - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <sys/time.h> - -/* Return t2-t1 in microseconds */ -long timeval_diff(struct timeval *t2, struct timeval *t1) -{ - long diff = (t2->tv_usec + 1000000 * t2->tv_sec) - (t1->tv_usec + 1000000 * t1->tv_sec); - return (diff); -} - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -void usage(char *arg) { - printf("Usage : %s percent nthreads\n\n",arg); - printf(" percent: 0-100 pourcentage de temps en section critique\n"); - printf(" nthreads : nombre de threads à lancer\n"); -} -///AAA -#define LOOP 40000 -#define LOOP_CRITIQUE 40000 -#define N 4 - -int percent; // pourcentage de temps en section critique -int nthreads; // nombre de threads -pthread_mutex_t mutex; - -void critique() { - long j=0; - for(int i=0;i<(LOOP_CRITIQUE*percent)/100;i++) { - j+=i; - // ... - } -} - -void noncritique() { - int j=0; - for(int i=0;i<(LOOP_CRITIQUE*(100-percent))/100;i++) { - j-=i; - // ... - } -} - - -void *func(void * param) { - for(int j=0;j<LOOP/nthreads;j++) { - pthread_mutex_lock(&mutex); - critique(); - pthread_mutex_unlock(&mutex); - noncritique(); - } - return(NULL); -} - -int main (int argc, char *argv[]) { - int err; - struct timeval tvStart, tvEnd; - long mesures[N]; - long sum=0; - - if(argc!=3) { - usage(argv[0]); - return(EXIT_FAILURE); - } - - char *endptr; - percent=strtol(argv[1],&endptr,10); - if(percent<1 || percent >100) { - usage(argv[0]); - return(EXIT_FAILURE); - } - nthreads=strtol(argv[2],&endptr,10); - - if(nthreads<0) { - usage(argv[0]); - return(EXIT_FAILURE); - } - pthread_t thread[nthreads]; - - err=pthread_mutex_init( &mutex, NULL); - if(err!=0) - error(err,"pthread_mutex_init"); - - for (int j=0;j<N;j++) { - - err=gettimeofday(&tvStart, NULL); - if(err!=0) - exit(EXIT_FAILURE); - - for(int i=0;i<nthreads;i++) { - err=pthread_create(&(thread[i]),NULL,&func,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - for(int i=nthreads-1;i>=0;i--) { - err=pthread_join(thread[i],NULL); - if(err!=0) - error(err,"pthread_join"); - } - err=gettimeofday(&tvEnd, NULL); - if(err!=0) - exit(EXIT_FAILURE); - - mesures[j]=timeval_diff(&tvEnd, &tvStart); - sum+=mesures[j]; - - } - printf("%d, %d, %ld\n",nthreads,percent,sum/N); - - err=pthread_mutex_destroy(&mutex); - if(err!=0) - error(err,"pthread_destroy"); - - return(EXIT_SUCCESS); -} diff --git a/Exercices/QCM/S7/src/pthread-sem.c b/Exercices/QCM/S7/src/pthread-sem.c deleted file mode 100644 index 322b80207dd0803d27ab71c792325ddd30eebe4f..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S7/src/pthread-sem.c +++ /dev/null @@ -1,61 +0,0 @@ -/************************************** - * pthread-semt.c - * - * Programme d'exemple de sémaphores - * - **************************************/ - -#include <pthread.h> -#include <semaphore.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -#define NTHREADS 4 - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -static sem_t semaphore; -long global=0; - -int increment(int i) { - return i+1; -} - -void *inc(void * param) { - for(int j=0;j<1000000;j++) { - sem_wait(&semaphore); - global=increment(global); - sem_post(&semaphore); - } - pthread_exit(NULL); -} - -int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - - sem_init(&semaphore, 0,1); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&inc,NULL); - if(err!=0) { - error(err,"pthread_create"); - } - } - - for(int i=0;i<NTHREADS;i++) { - err=pthread_join(thread[i],NULL); - if(err!=0) { - error(err,"pthread_join"); - } - } - sem_destroy(&semaphore); - printf("global: %ld\n",global); - - return(EXIT_SUCCESS); -} diff --git a/Exercices/QCM/S8/Makefile b/Exercices/QCM/S8/Makefile deleted file mode 100755 index e350e0846be7e3614feb14b7641f3d2e8bea0204..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S8/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -#################################################################### -# -# Makefile for SINF1252 QCM -# OB, Jan 2013 -# -#################################################################### - -MISSION=8 - -DEST=../../../web/qcm - -EXNAME=$(DEST)/Mission-$(MISSION)-qcm.html - -RST_FILES=qcm-$(MISSION).rst - -CSS=../rst-form/css/html4css1.css,../rst-form/css/rst-form.css,../rst-form/css/pygments.css - -.PHONY : qcm all - -qcm: $(EXNAME) - -$(EXNAME): $(RST_FILES) - @for i in $(RST_FILES); do\ - ( rst2html.py --stylesheet-path=$(CSS) $$i > $(EXNAME) ; ) ; done - - -all: qcm - -clean: - -rm -r $(EXNAME) diff --git a/Exercices/QCM/S8/qcm-8.rst b/Exercices/QCM/S8/qcm-8.rst deleted file mode 100644 index 36078ea62c2f90764f440e21bb6aab4a4f7355a2..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S8/qcm-8.rst +++ /dev/null @@ -1,455 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. raw:: html - - <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script> - <script type="text/javascript" src="js/jquery-shuffle.js"></script> - <script type="text/javascript" src="js/rst-form.js"></script> - <Script type="text/javascript" src="js/prettify.js"></script> - <script type="text/javascript">$nmbr_prop = 4</script> - - -================ -Huitième semaine -================ - -La matière couverte cette semaine couvre les processus. Elle est décrite dans les sections suivantes des notes : - - - `Les processus <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/Threads/processus.html>`_ - -Question 1. `fork(2)`_ ------------------------ - -L'appel système `fork(2)`_ permet de créer une copie du processus courant. Un étudiant a écrit le fragment de code ci-dessous se trouvant dans la fonction ``main``: - -.. code-block:: c - - int n=... - for(int i=0; i<n ; i++) { - printf("i=%d\n",i); - pid_t pid; - pid=fork(); - if (pid==-1) { - perror("fork"); - exit(EXIT_FAILURE); - } - else { - if(pid!=0) { - printf("Running in %d\n",pid); - } - } - } - return(EXIT_SUCCESS); - -Lors de l'exécution de ce programme, combien de processus sont créés en fonction de la valeur de ``n`` ? - -.. class:: positive - -- Lorsque ``n`` est initialisé à ``2``, quatre processus sont créés. - - .. class:: comment - - Le premier processus démarre son exécution. Il exécute `fork(2)`_. Un nouveau processus est donc créé. Ces deux processus exécutent à leur tour `fork(2)`_ et deux processus supplémentaires sont donc créés. - -- Lorsque ``n`` est initialisé à ``3``, huit processus sont créés. - - .. class:: comment - - Le premier processus démarre son exécution. Il exécute `fork(2)`_. Un nouveau processus est donc créé. Ces deux processus exécutent à leur tour `fork(2)`_ et deux processus supplémentaires sont donc créés. Chacun de ces quatre processus exécute à son tour `fork(2)`_ et il y a donc huit processus au total. - -.. class:: negative - -- Lorsque ``n`` est initialisé à ``2``, deux processus sont créés. - - .. class:: comment - - Le premier processus démarre son exécution. Il exécute `fork(2)`_. Un nouveau processus est donc créé. Chacun de ces deux processus poursuit son exécution et la valeur de ``i`` est incrémentée. - -- Lorsque ``n`` est initialisé à ``2``, trois processus sont créés. - - .. class:: comment - - Le premier processus démarre son exécution. Il exécute `fork(2)`_. Un nouveau processus est donc créé. Chacun de ces deux processus poursuit son exécution et la valeur de ``i`` est incrémentée. - - -- Lorsque ``n`` est initialisé à ``3``, trois processus sont créés. - - .. class:: comment - - Le premier processus démarre son exécution. Il exécute `fork(2)`_. Un nouveau processus est donc créé. Chacun de ces deux processus poursuit son exécution et la valeur de ``i`` est incrémentée. - -- Lorsque ``n`` est initialisé à ``3``, quatre processus sont créés. - - .. class:: comment - - Le premier processus démarre son exécution. Il exécute `fork(2)`_. Un nouveau processus est donc créé. Chacun de ces deux processus poursuit son exécution et la valeur de ``i`` est incrémentée. - -Question 2. `execve(2)`_ ------------------------- - -Parmi les extraits de programme ci-dessous, lequel est un appel correct à `execve(2)`_ pour lancer le programme ``/bin/echo`` avec comme arguments ``-n`` et ``SINF1252`` ? - -.. class:: positive - -- - .. code-block:: c - - char *arguments[]={"echo", "-n", "SINF1252", NULL}; - char *environnement[]={"LANG=fr",NULL}; - int err=execve("/bin/echo", arguments, environnement); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - - -- - .. code-block:: c - - - char prog[]="echo"; - char param1[]="-n"; - char param2[]="SINF1252"; - char *arguments[4]; - arguments[0]=prog; - arguments[1]=param1; - arguments[2]=param2; - arguments[3]=NULL; - char *environnement[]={"LANG=fr", NULL}; - int err=execve("/bin/echo", arguments, environnement); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - - -.. class:: negative - -- - .. code-block:: c - - char arguments[]={"echo", "-n", "SINF1252", NULL}; - char environnement[]={"LANG=fr",NULL}; - int err=execve("/bin/echo", arguments, environnement); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - - - .. class:: comment - - Les deuxième et troisième arguments à `execve(2)`_ doivent être de type ``char *arg[]``. - -- - .. code-block:: c - - - char prog[]="echo"; - char param1[]="-n"; - char param2[]="SINF1252"; - char *arguments[4]; - arguments[0]=prog; - arguments[1]=param1; - arguments[2]=param2; - arguments[3]=NULL; - char *environnement[]={"LANG=fr"}; - int err=execve("/bin/echo", arguments, environnement); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - - .. class:: comment - - Les deuxième et troisième arguments à `execve(2)`_ doivent être de type ``char *arg[]``. - -- - .. code-block:: c - - - char prog[]="echo"; - char param1[]="-n"; - char param2[]="SINF1252"; - char *arguments[3]; - arguments[0]=prog; - arguments[1]=param1; - arguments[2]=param2; - char *environnement[]={"LANG=fr"}; - int err=execve("/bin/echo", arguments, environnement); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - - .. class:: comment - - Le dernier élément des tableaux de pointeurs ``argv` et ``environnement`` doivent obligatoirement contenir ``NULL``. Sans cela, il n'est pas possible de déterminer le nombre d'éléments dans ces tableaux. - -- - .. code-block:: c - - char *arguments[]={"echo", "-n", "SINF1252"}; - char *environnement[]={"LANG=fr"}; - int err=execve("/bin/echo", arguments, environnement); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - - .. class:: comment - - Le dernier élément des tableaux de pointeurs ``argv` et ``environnement`` doivent obligatoirement contenir ``NULL``. Sans cela, il n'est pas possible de déterminer le nombre d'éléments dans ces tableaux. - - -Question 3. `execve(2)`_ ------------------------- - -L'appel système `execve(2)`_ permet d'exécuter un programme en remplaçant le programme en cours d'exécution par celui se trouvant sur disque dont le nom est spécifié. Un étudiant a écrit le programme ci-dessous pour tester `execve(2)`_ : - -.. code-block:: c - - #include <stdio.h> - #include <stdlib.h> - #include <unistd.h> - - extern char **environ; - - int main (int argc, char *argv[]) { - - int n=... - int i=0; - for(i=0;i<n;i++) { - sleep(1); - printf("%d\n",i); - int err=execve(argv[0], argv, environ); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - } - return(EXIT_SUCCESS); - } - -.. class:: positive - -- Lorsque ``n`` est initialisé à ``3``, le programme ne s'arrête jamais et affiche : - - .. code-block:: console - - 0 - 0 - 0 - ... - - .. class:: comment - - Lors de l'exécution de `execve(2)`_, le programme est remplacé par lui-même puisque ``argv[0]`` contient toujours le nom de l'exécutable qui est en train d'être exécuté. Ce programme redémarre son exécution au début de la fonction ``main``... - - -- Lorsque ``n`` est initialisé à ``2``, le programme ne s'arrête jamais et affiche : - - .. code-block:: console - - 0 - 0 - 0 - ... - - - .. class:: comment - - Lors de l'exécution de `execve(2)`_, le programme est remplacé par lui-même puisque ``argv[0]`` contient toujours le nom de l'exécutable qui est en train d'être exécuté. Ce programme redémarre son exécution au début de la fonction ``main``... - - - -.. class:: negative - -- Lorsque ``n`` est initialisé à ``3``, le programme affiche : - - .. code-block:: console - - 0 - 1 - 2 - - - .. class:: comment - - Lors de l'exécution de `execve(2)`_, le programme est remplacé par lui-même puisque ``argv[0]`` contient toujours le nom de l'exécutable qui est en train d'être exécuté. Ce programme redémarre son exécution au début de la fonction ``main``... - -- Lorsque ``n`` est initialisé à ``2``, le programme affiche : - - .. code-block:: console - - 0 - 1 - - - .. class:: comment - - Lors de l'exécution de `execve(2)`_, le programme est remplacé par lui-même puisque ``argv[0]`` contient toujours le nom de l'exécutable qui est en train d'être exécuté. Ce programme redémarre son exécution au début de la fonction ``main``... - -- Lorsque ``n`` est initialisé à ``2``, l'appel à `execve(2)`_ est erroné et le programme s'arrête. - - .. class:: comment - - L'appel à `execve(2)`_ est tout à fait correct, même si il n'est pas recommandé d'utiliser `execve(2)`_ de cette façon... - - -- Lorsque ``n`` est initialisé à ``3``, l'appel à `execve(2)`_ est erroné et le programme s'arrête. - - .. class:: comment - - L'appel à `execve(2)`_ est tout à fait correct, même si il n'est pas recommandé d'utiliser `execve(2)`_ de cette façon... - - - -Question 4. Utilisation de `waitpid(2)`_ ----------------------------------------- - -L'appel système `waitpid(2)`_ permet à un processus d'attendre les valeurs de retour de ses processus fils. Un étudiant a écrit un programme qui lance de nombreux processus et veut faire une boucle qui permet de récupérer tous les processus fils qu'il a créé. Parmi les fragments de code ci-dessous, un seul est correct. Lequel ? - - -.. class:: positive - - -- - .. code-block:: c - - - int fils; - int done=false; - while(!done) { - int status; - fils=waitpid(0,&status,0); - if( (fils==-1) && (errno==ECHILD) ) - done=true; - } - -- - .. code-block:: c - - - int fils; - int done=false; - while(!done) { - int status; - if( (waitpid(0,&status,0)==-1) && (errno==ECHILD) ) - done=true; - } - - - -.. class:: negative - -- - .. code-block:: c - - - int fils; - int done=false; - int status; - while(waitpid(0,status,0)!=0) { - if( (fils==-1) && (errno==ECHILD) ) - done=true; - } - - - .. class:: comment - - Le second argument de `waitpid(2)`_ est un pointeur vers un entier et non un entier. - -- - .. code-block:: c - - - int fils; - int done=false; - while(!done) { - int status; - fils=waitpid(getpid(),&status,0); - if( (fils==-1) && (errno==ECHILD) ) - done=true; - } - - .. class:: comment - - Lorsque le premier argument de `waitpid(2)`_ est un entier positif, il s'agit de l'identifiant du processus pour lequel `waitpid(2)`_ attend. Dans ce cas, `getpid(2)`_ retourne l'identifiant du processus qui existe `waitpid(2)`_ et un processus ne peut pas être un fils de lui-même. - -Question 5. Récupération du résultat d'un processus avec `waitpid(2)`_ ----------------------------------------------------------------------- - -Un étudiant souhaite récupérer le résultat du processus ``pid`` qu'il a créé en faisant `fork(2)`_ et l'afficher sur ``stdout``. Parmi les fragments de programmes ci-dessous, un seul est correct. Lequel ? - -.. class:: positive - -- - .. code-block:: c - - int status; - int p=waitpid(pid,&status,0); - if(p==-1) { - perror("wait"); - exit(EXIT_FAILURE); - } - if(WIFEXITED(status)) { - printf("Le processus a retourne %d\n",WEXITSTATUS(status)); - } - - -.. class:: negative - -- - .. code-block:: c - - int status; - int p=waitpid(pid,status,0); - if(p==-1) { - perror("wait"); - exit(EXIT_FAILURE); - } - printf("Le processus a retourne %d\n",WEXITSTATUS(status)); - - .. class:: comment - - L'appel système `waitpid(2)`_ prend comme second argument un pointeur vers un ``int`` et non un `ìnt``. - - -- - .. code-block:: c - - int status; - int p=waitpid(pid,&status,0); - if(p==-1) { - perror("wait"); - exit(EXIT_FAILURE); - } - printf("Le processus a retourne %d\n",p); - - .. class:: comment - - La valeur de retour de `waitpid(2)`_ indique si l'appel système s'est exécuté correctement ou non. Pour récupérer le statut du processus fils ``pid``, il faut utiliser la macro ``WEXITSTATUS``. - - -- - .. code-block:: c - - int *status; - int p=waitpid(pid,status,0); - if(p==-1) { - perror("wait"); - exit(EXIT_FAILURE); - } - printf("Le processus a retourne %d\n",p); - - .. class:: comment - - La valeur de retour de `waitpid(2)`_ indique si l'appel système s'est exécuté correctement ou non. Pour récupérer le statut du processus fils ``pid``, il faut utiliser la macro ``WEXITSTATUS``. Le pointeur ``int * status`` doit pointer vers une zone mémoire allouée par malloc. Ici, il pointe vers ``NULL``. - - -.. include:: ../../../links.rst -.. include:: ../../../man_links.rst -.. include:: ../../../incl_links.rst diff --git a/Exercices/QCM/S8/src/execbomb.c b/Exercices/QCM/S8/src/execbomb.c deleted file mode 100644 index 828bac5c087b06e1bd94d964f97276cc16cadd1d..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S8/src/execbomb.c +++ /dev/null @@ -1,29 +0,0 @@ -/************************************** - * execbomb.c - * - * Programme qui ne se termine jamais - * - *************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -extern char **environ; - -int main (int argc, char *argv[]) { - - int n=2; - int i=0; - for(i=0;i<n;i++) { - sleep(1); - printf("%d\n",i); - int err=execve(argv[0], argv, environ); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - } - return(EXIT_SUCCESS); -} - diff --git a/Exercices/QCM/S8/src/execswap.c b/Exercices/QCM/S8/src/execswap.c deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/Exercices/QCM/S8/src/execve.c b/Exercices/QCM/S8/src/execve.c deleted file mode 100644 index 52b29d3cfa7c690e5055672f9d01d0459a655dcc..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S8/src/execve.c +++ /dev/null @@ -1,50 +0,0 @@ -/************************************** - * execbomb.c - * - * Programme qui ne se termine jamais - * - *************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -void f1() { - /* ok - char *arguments[]={"echo", "-n", "SINF1252", NULL}; - char *environnement[]={"LANG=fr",NULL}; - int err=execve("/bin/echo", arguments, environnement); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - - */ - - /* ok - char prog[]="echo"; - char param1[]="-n"; - char param2[]="SINF1252"; - char *arguments[4]; - arguments[0]=prog; - arguments[1]=param1; - arguments[2]=param2; - arguments[3]=NULL; - char *environnement[]={"LANG=fr"}; - int err=execve("/bin/echo", arguments, environnement); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - */ - -} - - -extern char **environ; - -int main (int argc, char *argv[]) { - - f1(); -} - diff --git a/Exercices/QCM/S8/src/fork-wait.c b/Exercices/QCM/S8/src/fork-wait.c deleted file mode 100644 index b18df42fed1fa831723b796f8a55e873030b1ba0..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S8/src/fork-wait.c +++ /dev/null @@ -1 +0,0 @@ -List directory (brief): ~/Documents/Cours/SINF1252/SystemesInformatiques/Exercices/QCM/S8/src/ diff --git a/Exercices/QCM/S8/src/fork-wait2.c b/Exercices/QCM/S8/src/fork-wait2.c deleted file mode 100644 index 9fcb9baf0d7bd09f7eebcafee291d0a4717d3515..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S8/src/fork-wait2.c +++ /dev/null @@ -1,41 +0,0 @@ -/************************************** - * fork-wait.c - * - * Programme d'exemple d'utilisation de - * wait - * - *************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/wait.h> -#include <sys/types.h> -#include <errno.h> -#include <stdbool.h> - -int main (int argc, char *argv[]) { - - pid_t pid; - - for(int i=0;i<2;i++) { - pid=fork(); - if (pid==-1) { - perror("fork"); - exit(EXIT_FAILURE); - } - if (pid==0) { - sleep(8); - return(42); - } - } - - int fils; - int done=false; - while(!done) { - int status; - fils=waitpid(0,&status,0); - if( (fils==-1) && (errno==ECHILD) ) - done=true; - } -} diff --git a/Exercices/QCM/S8/src/nfork.c b/Exercices/QCM/S8/src/nfork.c deleted file mode 100644 index 085a0ddc03a6e0a20e60e4ea055ddb06038dece8..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S8/src/nfork.c +++ /dev/null @@ -1,33 +0,0 @@ -/************************************** - * nfork.c - * - * Programme lançant plusieurs copies - * de lui même - * - *************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - - -int main (int argc, char *argv[]) { - - int n=2; - for(int i=0; i<n ; i++) { - printf("i=%d\n",i); - pid_t pid; - pid=fork(); - if (pid==-1) { - perror("fork"); - exit(EXIT_FAILURE); - } - else { - if(pid!=0) { - printf("Running in %d\n",pid); - } - } - } - return(EXIT_SUCCESS); -} - diff --git a/Exercices/QCM/S8/src/waitpid.c b/Exercices/QCM/S8/src/waitpid.c deleted file mode 100644 index 92eb83e2a551b8f469525718048ab97bb1a8eea6..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S8/src/waitpid.c +++ /dev/null @@ -1,21 +0,0 @@ -/************************************** - * nfork.c - * - * Programme lançant plusieurs copies - * de lui même - * - *************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> - -int main (int argc, char *argv[]) { - - int status; - int err=waitpid(getpid(),&status,0); - printf("%s\n",strerror(errno)); -} - diff --git a/Exercices/QCM/S9/Makefile b/Exercices/QCM/S9/Makefile deleted file mode 100755 index f1117bf587f65854491b872a71187bf74004b874..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S9/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -#################################################################### -# -# Makefile for SINF1252 QCM -# OB, Jan 2013 -# -#################################################################### - -MISSION=9 - -EXNAME=../../../_static/Mission-$(MISSION)-qcm.html - -RST_FILES=qcm-$(MISSION).rst - -CSS=../rst-form/css/html4css1.css,../rst-form/css/rst-form.css,../rst-form/css/pygments.css - -.PHONY : qcm all - -qcm: $(EXNAME) - -$(EXNAME): $(RST_FILES) - @for i in $(RST_FILES); do\ - ( rst2html.py --stylesheet-path=$(CSS) $$i > $(EXNAME) ; ) ; done - - -all: qcm - -clean: - -rm -r $(EXNAME) diff --git a/Exercices/QCM/S9/qcm-9.rst b/Exercices/QCM/S9/qcm-9.rst deleted file mode 100644 index 1bc476b57b7886e83f7dcf584977d04bd4a9cfa6..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S9/qcm-9.rst +++ /dev/null @@ -1,505 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. raw:: html - - <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script> - <script type="text/javascript" src="js/jquery-shuffle.js"></script> - <script type="text/javascript" src="js/rst-form.js"></script> - <script type="text/javascript" src="js/prettify.js"></script> - <script type="text/javascript">$nmbr_prop = 4</script> - - -================ -Neuvième semaine -================ - - -La matière couverte cette semaine porte sur le système de fichiers et sa manipulation par les processus. - -Question 1. Accès aux fichiers ------------------------------- - -Les bits de permissions permettent de contrôler l'accès aux fichiers. Considérons le répertoire ci-dessous : - -.. code-block:: console - - -rw-r--r-- 1 obo obo 0 23 mar 21:57 a - -r-xr-x--x 1 obo obo 0 23 mar 21:57 b - -rw------- 1 obo obo 0 23 mar 21:57 c - -rw------x 1 obo obo 0 23 mar 21:57 d - --w-----w- 1 obo obo 0 23 mar 21:57 e - - -Un seul des groupes d'affirmations ci-dessous est vrai. Lequel ? - -.. class:: positive - -- - - l'utilisateur ``obo`` peut lire le fichier ``c``, exécuter le fichier ``b`` et modifier le contenu du fichier ``d`` - - -- - - l'utilisateur ``obo`` peut lire le fichier ``a``, exécuter le fichier ``b`` et modifier le contenu du fichier ``c`` - - -.. class:: negative - -- - - l'utilisateur ``obo`` peut lire le fichier ``e``, exécuter le fichier ``b`` et modifier le contenu du fichier ``e`` - - .. class:: comment - - Le fichier ``e`` n'est pas lisible par cet utilisateur. - -- - - l'utilisateur ``obo`` peut lire le fichier ``c``, exécuter le fichier ``d`` et modifier le contenu du fichier ``b`` - - .. class:: comment - - Le fichier ``b`` n'est pas modifiable par cet utilisateur. - -- - - l'utilisateur ``obo`` peut lire le fichier ``c``, exécuter le fichier ``a`` et modifier le contenu du fichier ``d`` - - .. class:: comment - - Le fichier ``a`` n'est pas exécutable par cet utilisateur. - - -Question 2. Fichiers et répertoires ------------------------------------ - -Les permissions associées aux répertoires ont un rôle un peu différent de celles qui sont associées aux fichiers. Considérons le répertoire ci-dessous qui contient 4 sous-répertoires. - -.. code-block:: console - - drw------- 2 obo obo 68 23 mar 22:25 a - dr-x------ 2 obo obo 68 23 mar 22:25 b - d-wx------ 3 obo obo 102 23 mar 22:27 c - drwx------ 3 obo obo 102 23 mar 22:26 d - -Chacun de ces répertoires contient un fichier qui a comme nom ``f``. La commande `touch(1)`_ peut être utilisée pour créer un fichier vide. Ainsi, dans ce répertoire, la commande ``touch f`` va créer le fichier ``f`` - -.. code-block:: console - - ls -l f - -rw-r--r-- 1 obo obo 0 23 mar 22:30 f - -Dans le répertoire ci-dessus, une seule séquence de commandes fonctionne sans erreur. Laquelle ? - -.. class:: positive - -- - .. code-block:: console - - ls -l d - touch c/x - cd b - -- - .. code-block:: console - - ls -l b - cat c/f - cd d - - -.. class:: negative - -- - .. code-block:: console - - ls -l c - touch d/x - cd a - - .. class:: comment - - Il n'est pas possible d'aller dans le répertoire ``a``. En outre, le contenu du répertoire ``c`` ne peut pas être lu avec `ls(1)`_ - -- - .. code-block:: console - - ls -l c - touch a/x - cd c - - .. class:: comment - - Il n'est pas possible de créer un fichier dans le répertoire ``a``. - -- - .. code-block:: console - - ls -l b - touch b/x - cd b - - .. class:: comment - - Il n'est pas possible de créer un fichier dans le répertoire ``b``. - - - -Question 3. Permissions sur les fichiers ----------------------------------------- - -La page de manuel de `chmod(1posix)`_ décrit en détails les permissions relatives aux fichiers et répertoires. Ces permissions peuvent être représentées sous une forme numérique ou textuelle. Parmi les affirmations suivantes, relatives à des permissions pour des `fichiers`, un seul groupe est vrai. Lequel ? - - -.. class:: positive - -- - - Le fichier ayant ``00467`` comme permissions est exécutable par n'importe quel utilisateur - - Le fichier ayant ``00777`` comme permissions est lisible par son propriétaire - - Le fichier ayant ``00600`` ne peut être lu que par son propriétaire - -- - - Le fichier ayant ``00647`` comme permissions est exécutable par n'importe quel utilisateur - - Le fichier ayant ``00700`` comme permissions est lisible par son propriétaire - - Le fichier ayant ``00421`` comme permissions ne peut être lu que par son propriétaire - -.. class:: negative - -- - - Le fichier ayant ``00476`` comme permissions est exécutable par n'importe quel utilisateur - - Le fichier ayant ``00747`` comme permissions est lisible par son propriétaire - - Le fichier ayant ``00601`` comme permissions ne peut être lu que par son propriétaire - - .. class:: comment - - Le fichier ayant ``00476`` comme permissions ne peut être exécuté que par un membre du groupe correspondant à ce fichier. - -- - - Le fichier ayant ``00677`` comme permissions est exécutable par n'importe quel utilisateur - - Le fichier ayant ``00017`` comme permissions est lisible par son propriétaire - - Le fichier ayant ``00400`` comme permissions ne peut être lu que par son propriétaire - - .. class:: comment - - Le fichier ayant ``00017`` comme permissions n'est pas lisible par son propriétaire - - -- - - Le fichier ayant ``00755`` comme permissions est exécutable par n'importe quel utilisateur - - Le fichier ayant ``00417`` comme permissions est lisible par son propriétaire - - Le fichier ayant ``00222`` comme permissions ne peut être lu que par son propriétaire - - .. class:: comment - - Le fichier ayant ``00222`` comme permissions n'est pas lisible par son propriétaire - - -- - - Le fichier ayant ``00666`` comme permissions est exécutable par n'importe quel utilisateur - - Le fichier ayant ``00400`` comme permissions est modificale par son propriétaire - - Le fichier ayant ``00400`` comme permissions ne peut être lu que par son propriétaire - - .. class:: comment - - Le fichier ayant ``00666`` comme permissions n'est pas exécutable - - - -Question 4. Permissions sur les fichiers ----------------------------------------- - -Les bits de permissions associés à un fichiers sont généralement représentés sous forme textuelle lorsque la commande `ls(1)`_ affiche le contenu d'un répertoire. Considérons le répertoire ci-dessous : - - .. code-block:: console - - -rw-r--r-- 1 obo obo 0 23 mar 21:57 a - -rwxr-x--x 1 obo obo 0 23 mar 21:57 b - -rw------- 1 obo obo 0 23 mar 21:57 c - -rw------x 1 obo obo 0 23 mar 21:57 d - --w-r--rw- 1 obo obo 0 23 mar 21:57 e - - -Parmi les commandes suivantes, un seul groupe permet d'obtenir les mêmes permissions que ci-dessous. Lequel ? - -.. class:: positive - -- - .. code-block:: console - - chmod 644 a - chmod 751 b - chmod 600 c - chmod 601 d - chmod 246 e - -.. class:: negative - - -- - .. code-block:: console - - chmod 446 a - chmod 157 b - chmod 006 c - chmod 106 d - chmod 642 e - - .. class:: comment - - Relisez la page de manuel de `chmod(1)`_ - -- - .. code-block:: console - - chmod 444 a - chmod 751 b - chmod 600 c - chmod 604 d - chmod 123 e - - .. class:: comment - - Relisez la page de manuel de `chmod(1)`_ - -- - .. code-block:: console - - chmod 322 a - chmod 364 b - chmod 300 c - chmod 301 d - chmod 123 e - - .. class:: comment - - Relisez la page de manuel de `chmod(1)`_ - - -Question 5. Système de fichiers -------------------------------- - - -Le système de fichiers Unix utilise des `inode` pour stocker les meta-données relatives à un fichier/répertoire. Parmi les groupes d'affirmations suivants, un seul est correct. Lequel ? - -.. class:: positive - -- - - deux fichiers se trouvant dans des répertoires différents sur le même disque peuvent avoir le même `inode` - - le champ ``nlinks`` est toujours positif - - un accès au fichier modifie le ``atime`` associé à ce fichier - - -.. class:: negative - -- - - deux fichiers ont toujours des `inode` différents - - l'`inode` contient le nom du fichier - - une écriture dans un fichier modifie le ``mtime`` associé à ce fichier - - .. class:: comment - - Les deux premières affirmations sont fausses. - - -- - - un fichier et un répertoire se trouvant sur le même disque peuvent avoir le même `inode` - - une lecture dans un fichier modifie le ``mtime`` associé à ce fichier - - l'`inode` contient le nom du fichier - - .. class:: comment - - Toutes les affirmations sont fausses. - - -- - - une copie d'un fichier incrémente la valeur du champ ``nlinks`` de son `inode` - - une lecture dans un fichier modifie le ``atime`` associé à ce fichier - - il n'y a jamais deux fichiers qui ont le même `inode` - - .. class:: comment - - La première et la troisième affirmation sont fausses. - -Question 6. Manipulation des répertoires ----------------------------------------- - -Les répertoires sont des fichiers spéciaux. Pour les utiliser, il faut faire appel aux fonctions `opendir(3)`_, `readdir(3)`_ et `closedir(3)`_. Parmi les séquences d'instructions ci-dessous, laquelle permet de compter le nombre de fichiers se trouvant dans le répertoire courant ? - -.. code-block:: c - - /* - * name!=NULL - * retourne le nombre de fichiers dans le répertoire name - * et -1 en cas d'erreur - */ - -.. class:: positive - -- - .. code-block:: c - - int nfiles(char * name) { - - DIR *dirp; - struct dirent *dp; - dp=malloc(sizeof(struct dirent)); - if(dp==NULL) { - return -1; - } - dirp = opendir(name); - if(dirp==NULL) { - return -1; - } - int count=0; - while ((dp = readdir(dirp)) != NULL) { - if (dp->d_type==DT_REG) { - count++; - } - } - int err = closedir(dirp); - if(err<0) { - return -1; - } - return(count); - } - - -- - -.. class:: negative - -- - .. code-block:: c - - int nfiles(char * name) { - - DIR *dirp; - struct dirent *dp; - dirp = opendir(name); - if(dirp==NULL) { - return -1; - } - int count=0; - while (readdir(dirp) != NULL) { - count++; - } - int err = closedir(dirp); - if(err<0) { - return -1; - } - return(count); - } - - .. class:: comment - - Ce code compte toutes les entrées dans le répertoire et pas seulement le fichiers. - -- - .. code-block:: c - - int nfiles2(char * name) { - - DIR dirp; - struct dirent dp; - dirp = opendir(name); - if(dirp==-1) { - return -1; - } - int count=0; - while ((dp = readdir(dirp)) != -1) { - count++; - } - - int err = closedir(dirp); - if(err<0) { - return -1; - } - return(count); - } - - .. class:: comment - - Ce code est erroné. `opendir(3)`_ retourne un pointeur et `readdir(3)`_ également. - -- - .. code-block:: c - - int nfiles(char * name) { - - DIR dirp; - struct dirent dp; - dirp = opendir(name); - int count=0; - while ((dp = readdir(dirp)) != NULL) { - if (dp->d_type==DT_REG) { - count++; - } - } - int err = closedir(dirp); - if(err<0) { - return -1; - } - return(count); - } - - .. class:: comment - - Ce code est erroné. `opendir(3)`_ retourne un pointeur et `readdir(3)`_ également. - - - - -Question 7. Liens symboliques ------------------------------ - -Considérons un répertoire dans lequel les commandes suivantes sont exécutées : - -.. code-block:: console - - touch a - cp a b - ln a c - ln b d - echo "test" > c - ln -s d e - echo essai > e - -Après exécution de ces commandes, un seul des groupes d'affirmations suivant est correct. Lequel ? - -.. class:: positive - -- - - les fichiers ``a`` et ``c`` ont le même `inode` - - les fichiers ``b`` et ``d`` ont la même taille - - l'`inode` correspondant au fichier ``d`` indique qu'il y a deux liens vers lui - - -- - - les fichiers ``d`` et ``e`` ont des `inode` différents - - les fichiers ``a`` et ``c`` ont la même taille - - l'`inode` correspondant au fichier ``b`` indique qu'il y a deux liens vers lui - - -.. class:: negative - -- - - les fichiers ``a`` et ``c`` ont des `inodes` différents - - les fichiers ``e`` et ``d`` ont la même taille - - l'`inode` correspondant au fichier ``d`` indique qu'il y a trois liens vers lui - -- - - les fichiers ``a`` et ``d`` ont des `inode` différents - - les fichiers ``b`` et ``d`` ont la même taille - - l'`inode` correspondant au fichier ``b`` indique qu'il y a trois liens vers lui - - .. class:: comment - - Il y a deux liens (hard) vers le fichier ``b``. Le fichier ``e`` est un lien symbolique vers ce fichier et non un lien `hard`. - -- - - les fichiers ``b``, ``d`` et ``e`` ont le même `inode` - - les fichiers ``a`` et ``c`` ont la même taille - - l'`inode` correspondant au fichier ``a`` indique qu'il y a deux liens vers lui - - -.. include:: ../../../links.rst -.. include:: ../../../man_links.rst -.. include:: ../../../incl_links.rst diff --git a/Exercices/QCM/S9/src/readdir.c b/Exercices/QCM/S9/src/readdir.c deleted file mode 100644 index ce16a4de6f37211d933c820e990a49c1449fa108..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S9/src/readdir.c +++ /dev/null @@ -1,89 +0,0 @@ -/************************************** - * readdir.c - * - * Programme d'exemple d'utilisation de - * répertoires - * - *************************************/ -///AAA -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <dirent.h> - -void exit_on_error(char *s) { - perror(s); - exit(EXIT_FAILURE); -} - -/* - * name!=NULL - * retourne le nombre de fichiers dans le répertoire name - * et -1 en cas d'erreur - */ - -int nfiles(char * name) { - - DIR *dirp; - struct dirent *dp; - dirp=malloc(sizeof(DIR)); - if(dirp==NULL) { - return(-1); - } - dp=malloc(sizeof(struct dirent)); - if(dp==NULL) { - return -1; - } - dirp = opendir(name); - if(dirp==NULL) { - return -1; - } - int count=0; - while ((dp = readdir(dirp)) != NULL) { - if (dp->d_type==DT_REG) { - count++; - } - } - int err = closedir(dirp); - if(err<0) { - return -1; - } - return(count); -} - - -int main (int argc, char *argv[]) { - - - - - DIR *dirp; - struct dirent *dp; - dirp=malloc(sizeof(DIR)); - if(dirp==NULL) { - exit_on_error("malloc"); - } - dp=malloc(sizeof(struct dirent)); - if(dp==NULL) { - exit_on_error("malloc"); - } - char name[]="."; - dirp = opendir(name); - if(dirp==NULL) { - exit_on_error("opendir"); - } - int count=0; - while ((dp = readdir(dirp)) != NULL) { - if (dp->d_type==DT_REG) { - count++; - } - } - printf ("%d fichiers - int err = closedir(dirp); - if(err<0) { - exit_on_error("closedir"); - } - - -} -///BBB diff --git a/Exercices/QCM/S9/src/readdir2.c b/Exercices/QCM/S9/src/readdir2.c deleted file mode 100644 index 4b1ba58bd0bccae57ed861c60a7310e6df4ca707..0000000000000000000000000000000000000000 --- a/Exercices/QCM/S9/src/readdir2.c +++ /dev/null @@ -1,76 +0,0 @@ -/************************************** - * readdir.c - * - * Programme d'exemple d'utilisation de - * répertoires - * - *************************************/ -///AAA -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <dirent.h> - -void exit_on_error(char *s) { - perror(s); - exit(EXIT_FAILURE); -} - -/* - * name!=NULL - * retourne le nombre de fichiers dans le répertoire name - * et -1 en cas d'erreur - */ - -int nfiles(char * name) { - - DIR *dirp; - struct dirent *dp; - dirp = opendir(name); - if(dirp==NULL) { - return -1; - } - int count=0; - while ((dp = readdir(dirp)) != NULL) { - if (dp->d_type==DT_REG) { - count++; - } - } - int err = closedir(dirp); - if(err<0) { - return -1; - } - return(count); -} - -/* -int nfiles2(char * name) { - - DIR dirp; - struct dirent dp; - dirp = opendir(name); - if(dirp==-1) { - return -1; - } - int count=0; - while ((dp = readdir(dirp)) != -1) { - if (dp->d_type==DT_REG) { - count++; - } - } - int err = closedir(dirp); - if(err<0) { - return -1; - } - return(count); -} -*/ - -int main (int argc, char *argv[]) { - - - - printf("%d \n",nfiles(".")); - -} -///BBB diff --git a/Exercices/QCM/qcm.rst.old b/Exercices/QCM/qcm.rst.old deleted file mode 100644 index 102313cdb3ce756dc5ffbd9c41d6a79162e8c5d1..0000000000000000000000000000000000000000 --- a/Exercices/QCM/qcm.rst.old +++ /dev/null @@ -1,45 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. raw:: html - - <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script> - <script type="text/javascript" src="js/jquery-shuffle.js"></script> - <script type="text/javascript" src="js/rst-form.js"></script> - <script type="text/javascript" src="js/prettify.js"></script> - <script type="text/javascript">$nmbr_prop = 4</script> - - -=================== -Semaine -=================== - -Question ---------- - -Considérons le programme C ci-dessous qui permet de manipuler les arguments passés en ligne de commande. - - .. code-block:: c - - #include <stdlio.h> - #include <stdlib.h> - int main(int argc, const char *argv[]) - { - int a = atoi(argv[1]); - printf("%d\n", a); - } - -Parmi les groupes d'affirmations ci-dessous, un seul ne contient que des affirmations qui sont toutes vraies. Lequel ? - - -.. class:: positive - - - -.. class:: negative - - .. class:: comment - - - diff --git a/Exercices/QCM/rst-form/css/html4css1.css b/Exercices/QCM/rst-form/css/html4css1.css deleted file mode 100644 index 816050614440183b34221665aa105dbd1a92fe7a..0000000000000000000000000000000000000000 --- a/Exercices/QCM/rst-form/css/html4css1.css +++ /dev/null @@ -1,303 +0,0 @@ -/* -:Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 7056 2011-06-17 10:50:48Z milde $ -:Copyright: This stylesheet has been placed in the public domain. - -Default cascading style sheet for the HTML output of Docutils. - -See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to -customize this style sheet. -*/ - -/* used to remove borders from tables and images */ -.borderless, table.borderless td, table.borderless th { - border: 0 } - -table.borderless td, table.borderless th { - /* Override padding for "table.docutils td" with "! important". - The right padding separates the table cells. */ - padding: 0 0.5em 0 0 ! important } - -.first { - /* Override more specific margin styles with "! important". */ - margin-top: 0 ! important } - -.last, .with-subtitle { - margin-bottom: 0 ! important } - -.hidden { - display: none } - -a.toc-backref { - text-decoration: none ; - color: black } - -blockquote.epigraph { - margin: 2em 5em ; } - -dl.docutils dd { - margin-bottom: 0.5em } - -object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] { - overflow: hidden; -} - -/* Uncomment (and remove this text!) to get bold-faced definition list terms -dl.docutils dt { - font-weight: bold } -*/ - -div.abstract { - margin: 2em 5em } - -div.abstract p.topic-title { - font-weight: bold ; - text-align: center } - -div.admonition, div.attention, div.caution, div.danger, div.error, -div.hint, div.important, div.note, div.tip, div.warning { - margin: 2em ; - border: medium outset ; - padding: 1em } - -div.admonition p.admonition-title, div.hint p.admonition-title, -div.important p.admonition-title, div.note p.admonition-title, -div.tip p.admonition-title { - font-weight: bold ; - font-family: sans-serif } - -div.attention p.admonition-title, div.caution p.admonition-title, -div.danger p.admonition-title, div.error p.admonition-title, -div.warning p.admonition-title { - color: red ; - font-weight: bold ; - font-family: sans-serif } - -/* Uncomment (and remove this text!) to get reduced vertical space in - compound paragraphs. -div.compound .compound-first, div.compound .compound-middle { - margin-bottom: 0.5em } - -div.compound .compound-last, div.compound .compound-middle { - margin-top: 0.5em } -*/ - -div.dedication { - margin: 2em 5em ; - text-align: center ; - font-style: italic } - -div.dedication p.topic-title { - font-weight: bold ; - font-style: normal } - -div.figure { - margin-left: 2em ; - margin-right: 2em } - -div.footer, div.header { - clear: both; - font-size: smaller } - -div.line-block { - display: block ; - margin-top: 1em ; - margin-bottom: 1em } - -div.line-block div.line-block { - margin-top: 0 ; - margin-bottom: 0 ; - margin-left: 1.5em } - -div.sidebar { - margin: 0 0 0.5em 1em ; - border: medium outset ; - padding: 1em ; - background-color: #ffffee ; - width: 40% ; - float: right ; - clear: right } - -div.sidebar p.rubric { - font-family: sans-serif ; - font-size: medium } - -div.system-messages { - margin: 5em } - -div.system-messages h1 { - color: red } - -div.system-message { - border: medium outset ; - padding: 1em } - -div.system-message p.system-message-title { - color: red ; - font-weight: bold } - -div.topic { - margin: 2em } - -h1.section-subtitle, h2.section-subtitle, h3.section-subtitle, -h4.section-subtitle, h5.section-subtitle, h6.section-subtitle { - margin-top: 0.4em } - -h1.title { - text-align: center } - -h2.subtitle { - text-align: center } - -hr.docutils { - width: 75% } - -img.align-left, .figure.align-left, object.align-left { - clear: left ; - float: left ; - margin-right: 1em } - -img.align-right, .figure.align-right, object.align-right { - clear: right ; - float: right ; - margin-left: 1em } - -img.align-center, .figure.align-center, object.align-center { - display: block; - margin-left: auto; - margin-right: auto; -} - -.align-left { - text-align: left } - -.align-center { - clear: both ; - text-align: center } - -.align-right { - text-align: right } - -/* reset inner alignment in figures */ -div.align-right { - text-align: inherit } - -/* div.align-center * { */ -/* text-align: left } */ - -ol.simple, ul.simple { - margin-bottom: 1em } - -ol.arabic { - list-style: decimal } - -ol.loweralpha { - list-style: lower-alpha } - -ol.upperalpha { - list-style: upper-alpha } - -ol.lowerroman { - list-style: lower-roman } - -ol.upperroman { - list-style: upper-roman } - -p.attribution { - text-align: right ; - margin-left: 50% } - -p.caption { - font-style: italic } - -p.credits { - font-style: italic ; - font-size: smaller } - -p.label { - white-space: nowrap } - -p.rubric { - font-weight: bold ; - font-size: larger ; - color: maroon ; - text-align: center } - -p.sidebar-title { - font-family: sans-serif ; - font-weight: bold ; - font-size: larger } - -p.sidebar-subtitle { - font-family: sans-serif ; - font-weight: bold } - -p.topic-title { - font-weight: bold } - -pre.address { - margin-bottom: 0 ; - margin-top: 0 ; - font: inherit } - -pre.literal-block, pre.doctest-block, pre.math { - margin-left: 2em ; - margin-right: 2em } - -span.classifier { - font-family: sans-serif ; - font-style: oblique } - -span.classifier-delimiter { - font-family: sans-serif ; - font-weight: bold } - -span.interpreted { - font-family: sans-serif } - -span.option { - white-space: nowrap } - -span.pre { - white-space: pre } - -span.problematic { - color: red } - -span.section-subtitle { - /* font-size relative to parent (h1..h6 element) */ - font-size: 80% } - -table.citation { - border-left: solid 1px gray; - margin-left: 1px } - -table.docinfo { - margin: 2em 4em } - -table.docutils { - margin-top: 0.5em ; - margin-bottom: 0.5em } - -table.footnote { - border-left: solid 1px black; - margin-left: 1px } - -table.docutils td, table.docutils th, -table.docinfo td, table.docinfo th { - padding-left: 0.5em ; - padding-right: 0.5em ; - vertical-align: top } - -table.docutils th.field-name, table.docinfo th.docinfo-name { - font-weight: bold ; - text-align: left ; - white-space: nowrap ; - padding-left: 0 } - -h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, -h4 tt.docutils, h5 tt.docutils, h6 tt.docutils { - font-size: 100% } - -ul.auto-toc { - list-style-type: none } diff --git a/Exercices/QCM/rst-form/css/prettify.css b/Exercices/QCM/rst-form/css/prettify.css deleted file mode 100644 index d44b3a2282ad31ed23a605f6b392b09324c64724..0000000000000000000000000000000000000000 --- a/Exercices/QCM/rst-form/css/prettify.css +++ /dev/null @@ -1 +0,0 @@ -.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} \ No newline at end of file diff --git a/Exercices/QCM/rst-form/css/pygments.css b/Exercices/QCM/rst-form/css/pygments.css deleted file mode 100644 index 2c5a906f3c3bc0309158f0362456cc8d546e9c61..0000000000000000000000000000000000000000 --- a/Exercices/QCM/rst-form/css/pygments.css +++ /dev/null @@ -1,62 +0,0 @@ -.highlight .hll { background-color: #ffffcc } -.highlight { background: #f8f8f8; } -.highlight .c { color: #408080; font-style: italic } /* Comment */ -.highlight .err { border: 1px solid #FF0000 } /* Error */ -.highlight .k { color: #008000; font-weight: bold } /* Keyword */ -.highlight .o { color: #666666 } /* Operator */ -.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */ -.highlight .cp { color: #BC7A00 } /* Comment.Preproc */ -.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */ -.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */ -.highlight .gd { color: #A00000 } /* Generic.Deleted */ -.highlight .ge { font-style: italic } /* Generic.Emph */ -.highlight .gr { color: #FF0000 } /* Generic.Error */ -.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ -.highlight .gi { color: #00A000 } /* Generic.Inserted */ -.highlight .go { color: #808080 } /* Generic.Output */ -.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ -.highlight .gs { font-weight: bold } /* Generic.Strong */ -.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ -.highlight .gt { color: #0040D0 } /* Generic.Traceback */ -.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ -.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ -.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ -.highlight .kp { color: #008000 } /* Keyword.Pseudo */ -.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ -.highlight .kt { color: #B00040 } /* Keyword.Type */ -.highlight .m { color: #666666 } /* Literal.Number */ -.highlight .s { color: #BA2121 } /* Literal.String */ -.highlight .na { color: #7D9029 } /* Name.Attribute */ -.highlight .nb { color: #008000 } /* Name.Builtin */ -.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ -.highlight .no { color: #880000 } /* Name.Constant */ -.highlight .nd { color: #AA22FF } /* Name.Decorator */ -.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ -.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ -.highlight .nf { color: #0000FF } /* Name.Function */ -.highlight .nl { color: #A0A000 } /* Name.Label */ -.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ -.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ -.highlight .nv { color: #19177C } /* Name.Variable */ -.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ -.highlight .w { color: #bbbbbb } /* Text.Whitespace */ -.highlight .mf { color: #666666 } /* Literal.Number.Float */ -.highlight .mh { color: #666666 } /* Literal.Number.Hex */ -.highlight .mi { color: #666666 } /* Literal.Number.Integer */ -.highlight .mo { color: #666666 } /* Literal.Number.Oct */ -.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ -.highlight .sc { color: #BA2121 } /* Literal.String.Char */ -.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ -.highlight .s2 { color: #BA2121 } /* Literal.String.Double */ -.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ -.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ -.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ -.highlight .sx { color: #008000 } /* Literal.String.Other */ -.highlight .sr { color: #BB6688 } /* Literal.String.Regex */ -.highlight .s1 { color: #BA2121 } /* Literal.String.Single */ -.highlight .ss { color: #19177C } /* Literal.String.Symbol */ -.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ -.highlight .vc { color: #19177C } /* Name.Variable.Class */ -.highlight .vg { color: #19177C } /* Name.Variable.Global */ -.highlight .vi { color: #19177C } /* Name.Variable.Instance */ -.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ diff --git a/Exercices/QCM/rst-form/css/rst-form.css b/Exercices/QCM/rst-form/css/rst-form.css deleted file mode 100644 index cd4202550ceaac90fc8e0efb69ae6fda671a71a9..0000000000000000000000000000000000000000 --- a/Exercices/QCM/rst-form/css/rst-form.css +++ /dev/null @@ -1,62 +0,0 @@ -/* -:Author: 3.14r -:Contact: 3@14r.com -:Copyright: This stylesheet has been placed in the public domain. - -Stylesheet for use with Docutils. - -*/ - -/* @import url(html4css1.css); */ - - -/* Your customizations go here. For example: */ - -body { - padding: 2% 5% 0 5%; -} - -h1, h2, h3 { - background-color: #2c5aa0; - padding: 3px 0 3px 40px; - color: white; - border-radius: 10px 0 0 10px; - -moz-border-radius: 10px 0 0 10px; - -webkit-border-radius: 10px 0 0 10px; - font-size: 150%; -} -h1.title { - text-align: left; -} - -div.section { - margin-top: 35px; - margin-bottom: 10px; -} - -.checker>h1, div.section>h1 { - font-size: 100%; -} - -li p.first { - display: inline; -} - -li>img.checkmark { - margin-left: -50px; -} - -ul { - list-style-type: none; -} - -input[type=radio] { - margin-right: 15px; - vertical-align: center; -} - -.result { - display: inline; - margin-left: 30px; - font-weight: bold; -} diff --git a/Exercices/QCM/rst-form/images/correct.png b/Exercices/QCM/rst-form/images/correct.png deleted file mode 100644 index 7f6e8675d08f0744d3839536a2d6004ce92e90f3..0000000000000000000000000000000000000000 Binary files a/Exercices/QCM/rst-form/images/correct.png and /dev/null differ diff --git a/Exercices/QCM/rst-form/images/false.png b/Exercices/QCM/rst-form/images/false.png deleted file mode 100644 index c2ea1ab74e1a161151754adf7d2055e5e1b0c897..0000000000000000000000000000000000000000 Binary files a/Exercices/QCM/rst-form/images/false.png and /dev/null differ diff --git a/Exercices/QCM/rst-form/js/jquery-1.7.2.min.js b/Exercices/QCM/rst-form/js/jquery-1.7.2.min.js deleted file mode 100644 index 16ad06c5acaad09ee4d6e9d7c428506db028aeeb..0000000000000000000000000000000000000000 --- a/Exercices/QCM/rst-form/js/jquery-1.7.2.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v1.7.2 jquery.com | jquery.org/license */ -(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'><div style='"+t+"0;display:block;overflow:hidden;'></div></div>"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table><tr><td style='"+t+"0;display:none'></td><td>t</td></tr></table>",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'></div>",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function( -a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.result}},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f -.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file diff --git a/Exercices/QCM/rst-form/js/jquery-shuffle-another.js b/Exercices/QCM/rst-form/js/jquery-shuffle-another.js deleted file mode 100644 index 4d816f28028084769c09209780a33a4524dfe2aa..0000000000000000000000000000000000000000 --- a/Exercices/QCM/rst-form/js/jquery-shuffle-another.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * jQuery Shuffle (http://mktgdept.com/jquery-shuffle) - * A jQuery plugin for shuffling a set of elements - * - * v0.0.1 - 13 November 2009 - * - * Copyright (c) 2009 Chad Smith (http://twitter.com/chadsmith) - * Dual licensed under the MIT and GPL licenses. - * http://www.opensource.org/licenses/mit-license.php - * http://www.opensource.org/licenses/gpl-license.php - * - * Shuffle elements using: $(selector).shuffle() or $.shuffle(selector) - * - **/ -(function(d){d.fn.shuffle=function(c){c=[];return this.each(function(){c.push(d(this).clone(true))}).each(function(a,b){d(b).replaceWith(c[a=Math.floor(Math.random()*c.length)]);c.splice(a,1)})};d.shuffle=function(a){return d(a).shuffle()}})(jQuery); \ No newline at end of file diff --git a/Exercices/QCM/rst-form/js/jquery-shuffle.js b/Exercices/QCM/rst-form/js/jquery-shuffle.js deleted file mode 100644 index ec707c0f18255ca14e00cc9564a5f0e8225cf5a0..0000000000000000000000000000000000000000 --- a/Exercices/QCM/rst-form/js/jquery-shuffle.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * jQuery shuffle - * - * Copyright (c) 2008 Ca-Phun Ung <caphun at yelotofu dot com> - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * http://yelotofu.com/labs/jquery/snippets/shuffle/ - * - * Shuffles an array or the children of a element container. - * This uses the Fisher-Yates shuffle algorithm <http://jsfromhell.com/array/shuffle [v1.0]> - */ - -(function($){ - - $.fn.shuffle = function() { - return this.each(function(){ - var items = $(this).children().clone(true); - return (items.length) ? $(this).html($.shuffle(items)) : this; - }); - } - - $.shuffle = function(arr) { - for(var j, x, i = arr.length; i; j = parseInt(Math.random() * i), x = arr[--i], arr[i] = arr[j], arr[j] = x); - return arr; - } - -})(jQuery); diff --git a/Exercices/QCM/rst-form/js/prettify.js b/Exercices/QCM/rst-form/js/prettify.js deleted file mode 100644 index eef5ad7e6a07676b3919146d583d1c190bf1e163..0000000000000000000000000000000000000000 --- a/Exercices/QCM/rst-form/js/prettify.js +++ /dev/null @@ -1,28 +0,0 @@ -var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; -(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= -[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c< -f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&& -(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r= -{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length, -t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b=== -"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), -l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, -q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, -q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, -"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), -a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} -for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value", -m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m= -a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue= -j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], -"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], -H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], -J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ -I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), -["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", -/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), -["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", -hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b= -!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m, -250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit", -PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})(); diff --git a/Exercices/QCM/rst-form/js/random_selector.js b/Exercices/QCM/rst-form/js/random_selector.js deleted file mode 100644 index cad1d8fd986515cee564c27ce954cedbe67fcee6..0000000000000000000000000000000000000000 --- a/Exercices/QCM/rst-form/js/random_selector.js +++ /dev/null @@ -1,25 +0,0 @@ -/* Code from http://blog.mastykarz.nl/jquery-random-filter/ */ - -jQuery.jQueryRandom = 0; -jQuery.extend(jQuery.expr[":"], -{ - random: function(a, i, m, r) { - if (i == 0) { - jQuery.jQueryRandom = Math.floor(Math.random() * r.length); - }; - return i == jQuery.jQueryRandom; - } -}); -/* - * <ul> - * <li>First</li> - * <li>Second</li> - * <li>Third</li> - * </ul> - * <script type="text/javascript"> - * $().ready(function() { - * alert($("li:random").text()); - * }); - * </script> - * - */ diff --git a/Exercices/QCM/rst-form/js/rst-form.js b/Exercices/QCM/rst-form/js/rst-form.js deleted file mode 100644 index 7e6e8d801da5afea094256c9e71d7256008d9a7c..0000000000000000000000000000000000000000 --- a/Exercices/QCM/rst-form/js/rst-form.js +++ /dev/null @@ -1,43 +0,0 @@ - -$(function() { - if (typeof $nmbr_prop == 'undefined') { - $nmbr_prop = Infinity; - } - $('.comment').not('.preproc').hide(); - $('ul.positive').before('<ul class="proposals"></ul>'); - $('ul.positive').each(function(index) { - $(this).shuffle().children('li').first() - .prependTo($(this).parent().children('ul.proposals')) - .attr('class', 'correct'); - }); - $('ul.negative').each(function(index) { - $(this).shuffle(); - $(this).children('li').slice(0, $nmbr_prop-1).each(function(index) { - $(this) - .prependTo($(this).parent().parent().children('ul.proposals')) - .attr('class', 'false'); - }); - }); - $('ul.proposals').each(function(index) { - $(this).shuffle(); - $('<input type="radio" name="' + $(this).parent().attr('id') + '">').prependTo($(this).children('li')); - }); - $('ul.positive').hide(); - $('ul.negative').hide(); - $('body').append('<div id="checker" class="checker"><h1>Vérifiez vos réponses</h1><input type="submit" value="Vérifier" id="verifier"></div>'); - $('#verifier').click(function () { - $('.comment').not('.preproc').hide(); - $('.checkmark').remove(); - $('.result').remove(); - $('li.false input:checked').parent().prepend('<img class="checkmark" src="images/false.png" style="display: none;"></img>'); - $('li.correct input:checked').parent().prepend('<img class="checkmark" src="images/correct.png" style="display: none;"></img>'); - $('.checkmark').show(); - $('input:checked').parent().children('.comment').show('slow'); - $('#checker').append('<div class="result">Votre score est de ' + - $('li.correct input:checked').length + '/' + - $('ul.proposals').length + '</div>'); - }); - $('pre.literal-block').addClass('prettyprint'); - prettyPrint(); -}); - diff --git a/Exercices/QCM/rst-form/readme.txt b/Exercices/QCM/rst-form/readme.txt deleted file mode 100644 index 7ad79b214edb0f083fa705c767a6fec7bf351bb9..0000000000000000000000000000000000000000 --- a/Exercices/QCM/rst-form/readme.txt +++ /dev/null @@ -1,5 +0,0 @@ -Pour compiler -------------- - -:: - rst2html --stylesheet css/rst-form.css --link-stylesheet test.rst > test.html diff --git a/Exercices/QCM/rst-form/test.rst b/Exercices/QCM/rst-form/test.rst deleted file mode 100644 index e201f57394c3deff01b87b6b525e1b668608e02a..0000000000000000000000000000000000000000 --- a/Exercices/QCM/rst-form/test.rst +++ /dev/null @@ -1,112 +0,0 @@ - -.. raw:: html - - <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script> - <script type="text/javascript" src="js/jquery-shuffle.js"></script> - <script type="text/javascript" src="js/rst-form.js"></script> - <script type="text/javascript">$nmbr_prop = 4</script> - -================= -Questionnaire RST -================= - -Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor -incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis -nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. -Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu -fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in -culpa qui officia deserunt mollit anim id est laborum. - -Question 1. 'Dérivées de polynomes' -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Lorsque l'on dérive le polynome :math:`x^4+3 \times x^2 +5 \times x+12`, on -obtient notamment le terme : - -.. class:: positive - -- :math:`4 \times x^3` -- :math:`5` -- :math:`6 \times x` - -.. class:: negative - -- :math:`4 \times x^2` - - .. class:: comment - - La dérivée de :math:`a \times x^n` est :math:`a \times n \times x^{n-1}` -- :math:`5 \times x` - - .. class:: comment - - La dérivée de :math:`a \times x^n` est :math:`a \times n \times x^{n-1}` -- :math:`12` - - .. class:: comment - - La dérivée d'un entier est :math:`0` - -Question 2. 'Dérivées de polynomes' -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Lorsque l'on dérive le polynome :math:`x^4+3 \times x^2 +5 \times x+12`, on -obtient notamment le terme : - -.. class:: positive - -- :math:`4 \times x^3` -- :math:`5` -- :math:`6 \times x` - -.. class:: negative - -- :math:`4 \times x^2` - - .. class:: comment - - La dérivée de :math:`a \times x^n` est :math:`a \times n \times x^{n-1}` -- :math:`5 \times x` - - .. class:: comment - - La dérivée de :math:`a \times x^n` est :math:`a \times n \times x^{n-1}` -- :math:`12` - - .. class:: comment - - La dérivée d'un entier est :math:`0` - - -Question 3. 'Dérivées de polynomes' -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Lorsque l'on dérive le polynome :math:`x^4+3 \times x^2 +5 \times x+12`, on -obtient notamment le terme : - -.. class:: positive - -- :math:`4 \times x^3` -- :math:`5` -- :math:`6 \times x` - -.. class:: negative - -- :math:`4 \times x^2` - - .. class:: comment - - La dérivée de :math:`a \times x^n` est :math:`a \times n \times x^{n-1}` -- :math:`5 \times x` - - .. class:: comment - - La dérivée de :math:`a \times x^n` est :math:`a \times n \times x^{n-1}` -- :math:`12` - - .. class:: comment - - La dérivée d'un entier est :math:`0` - - - diff --git a/Exercices/_static b/Exercices/_static deleted file mode 120000 index 7a2b653646f86d98f976df94c66c017b5d24ecbe..0000000000000000000000000000000000000000 --- a/Exercices/_static +++ /dev/null @@ -1 +0,0 @@ -../_static \ No newline at end of file diff --git a/Exercices/_templates/layout.html b/Exercices/_templates/layout.html deleted file mode 100644 index 289d380b194cd2d21db58b2ded4f2d65a369985c..0000000000000000000000000000000000000000 --- a/Exercices/_templates/layout.html +++ /dev/null @@ -1,4 +0,0 @@ -{% extends "!layout.html" %} -{% block extrahead %} -{% endblock %} - diff --git a/Exercices/benchmark.rst.old b/Exercices/benchmark.rst.old deleted file mode 100644 index 762a91db09f535c4a1fbeeca1a291d0131926587..0000000000000000000000000000000000000000 --- a/Exercices/benchmark.rst.old +++ /dev/null @@ -1,39 +0,0 @@ -.. -*- coding: utf-8 -*- - -Evaluation des performances des appels systèmes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Pour le troisième projet, vous devrez choisir un appel système, analyser la façon dont il doit être utilisé, sur base de sa page de manuel et de livres de référence et ensuite en évaluer ses performances. Pour cette évaluation de performances, vous devrez modifier le programme de benchmark développé par Benoît Legat, Nicolas Demol et Maxime Houtain : - - https://github.com/blegat/benchmark.git - -Pour s'exécuter, ce programme nécessite une version récente de `gnuplot <http://www.gnuplot.info>`_ , un programme permettant d'afficher des données de façon graphique. Téléchargez les sources de ce programme et installez-le en faisant : - -.. code:: console - - - wget http://sourceforge.net/projects/gnuplot/files/gnuplot/4.6.5/gnuplot-4.6.5.tar.gz - tar xzvf gnuplot-4.6.5.tar.gz - cd gnuplot-4.6.5 - ./configure - make - -Le programme gnuplot est maintenant compilé et prêt à être utilisé. Le programme exécutable est dans le répertoire gnuplot-4.6.5/src/gnuplot - -Chargez le programme de benchmark et compilez-le comme suit : - -.. code:: console - - git clone https://github.com/blegat/benchmark.git - cd benchmark - PATH=~/src/gnuplot-4.6.5/src:${PATH} ./bootstrap.sh - make - -La troisième commande permet de forcer l'utilisation de la version récente de gnuplot que vous avez installé à la place de la version par défaut du système qui n'est pas supportée par l'outil de benchmark. Une fois le benchmark compilé, vous pouvez l'exécuter et tester les benchmarks fournis. Commencez par ceux qui se trouvent dans les répertoires suivants : - - - ``tab`` - - ``thread`` - - ``amdahl`` - - ``types`` - -Pour exécuter un benchmark, lancez simplement ``make show`` dans le répertoire du benchmark. Il exécutera alors le benchmark et produira un fichier HTML contenant les résultats obtenus ainsi que des fichiers au format .csv avec les valeurs mesurées. Essayez d'interpréter les résultats obtenus. Pouvez-vous justifier l'évolution des performances que vous observez ? diff --git a/Exercices/bib.rst b/Exercices/bib.rst deleted file mode 100644 index 97c0a1ecffdddba2bf2e35d116e34cfebec76ae5..0000000000000000000000000000000000000000 --- a/Exercices/bib.rst +++ /dev/null @@ -1,15 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -************* -Bibliographie -************* - - -.. [Downey2008] Downey, A., `The Little Book of Semaphores`, Second Edition, Green Tea Press, 2008, - -.. [IA32] intel, `Intel® 64 and IA-32 Architectures : Software Developer’s Manual`, Combined Volumes: 1, 2A, 2B, 2C, 3A, 3B and 3C, December 2011, http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf - -.. [Kerrisk2010] Kerrisk, M., `The Linux Programming Interface`, No Starch Press, 2010, http://my.safaribooksonline.com/book/programming/linux/9781593272203 - diff --git a/Exercices/conf.py b/Exercices/conf.py deleted file mode 100644 index 75f693559c306b19894e1e6f08b8d135e0d8c85c..0000000000000000000000000000000000000000 --- a/Exercices/conf.py +++ /dev/null @@ -1,320 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SINF1252 documentation build configuration file, created by -# sphinx-quickstart on Tue Jan 3 16:17:09 2012. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' -sys.path.append(os.path.abspath('mcq')) -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.todo', 'sphinx.ext.ifconfig', 'sphinx.ext.mathjax', 'sphinx.ext.intersphinx','mcq' ] - - -# mcq - -mcq_nb_prop=3 -mcq_upload_url='http://inginious.info.ucl.ac.be' -mcq_inginious_url='http://inginious.info.ucl.ac.be/cnp3' - -# ucomment -#sys.path.append(os.path.abspath(os.getcwd())) -#extensions.append('ucomment-extension') -#html_translator_class = 'ucomment-extension.ucomment_html_translator' - -# Point to your Django application, which contains all -# the other settings required. -#ucomment = {} -#ucomment['django_application_path'] = '/home/cpaasch/sinf1252/ucommentsite/ucommentapp' - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -source_encoding = 'utf-8' -#source_encoding = 'latin1' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'SINF1252 : Exercices ' -copyright = u'2012-2014, O. Bonaventure, G. Detal, C. Paasch' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '2014' -# The full version, including alpha/beta/rc tags. -release = '2014' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -language = 'fr' - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['_build', '.#*', '*/.#*', 'QCM/*' ] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -rst_epilog = """ -.. include:: /../Theorie/links.rst -.. include:: /../Theorie/man_links.rst -.. include:: /../Theorie/incl_links.rst -""" - -# Intersphinx -intersphinx_mapping = {'theorie': ('https://sites.uclouvain.be/SystInfo/notes/Theorie/html/', None), 'outils': ('https://sites.uclouvain.be/SystInfo/notes/Outils/html/', None), 'exercices': ('https://sites.uclouvain.be/SystInfo/notes/Exercices/html/', None)} - - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'haiku' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -html_title = u'Systèmes informatiques' - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static', 'mcq/static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'SINF1252doc' - - -# -- Options for LaTeX output -------------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -'papersize': 'a4paper', - -# The font size ('10pt', '11pt' or '12pt'). -'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'SINF1252.tex', u'SINF1252', - u'O. Bonaventure, G. Detal, C. Paasch', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'sinf1252', u'SINF1252', - [u'O. Bonaventure, G. Detal, C. Paasch'], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------------ - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'SINF1252', u'SINF1252', - u'O. Bonaventure, G. Detal, C. Paasch', 'SINF1252', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - - -# -- Options for Epub output --------------------------------------------------- - -# Bibliographic Dublin Core info. -epub_title = u'SINF1252' -epub_author = u'O. Bonaventure, G. Detal, C. Paasch' -epub_publisher = u'O. Bonaventure, G. Detal, C. Paasch' -epub_copyright = u'2013, O. Bonaventure, G. Detal, C. Paasch' - -# The language of the text. It defaults to the language option -# or en if the language is not set. -#epub_language = '' - -# The scheme of the identifier. Typical schemes are ISBN or URL. -#epub_scheme = '' - -# The unique identifier of the text. This can be a ISBN number -# or the project homepage. -#epub_identifier = '' - -# A unique identification for the text. -#epub_uid = '' - -# A tuple containing the cover image and cover page html template filenames. -#epub_cover = () - -# HTML files that should be inserted before the pages created by sphinx. -# The format is a list of tuples containing the path and title. -#epub_pre_files = [] - -# HTML files shat should be inserted after the pages created by sphinx. -# The format is a list of tuples containing the path and title. -#epub_post_files = [] - -# A list of files that should not be packed into the epub file. -#epub_exclude_files = [] - -# The depth of the table of contents in toc.ncx. -#epub_tocdepth = 3 - -# Allow duplicate toc entries. -#epub_tocdup = True - -#try: -# open('.staff','r') -# tags.add('staff') -# print "Build as staff member" -#except: -# print "Build as student" diff --git a/Exercices/index.rst b/Exercices/index.rst deleted file mode 100644 index 4b73b277c04f51a2495cddb5136aa7a2acc1939f..0000000000000000000000000000000000000000 --- a/Exercices/index.rst +++ /dev/null @@ -1,27 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012-2014 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -################################## -Systèmes informatiques : Exercices -################################## - - -.. only:: html - - Ce site web contient les exercices du cours `SINF1252 <http://www.uclouvain.be/cours-2015-LSINF1252.html>`_ donné aux `étudiants en informatique <http://www.uclouvain.be/info.html>`_ à l'`Université catholique de Louvain <http://www.uclouvain.be>`_ (UCL). Les étudiants sont invités à ajouter leur commentaires en soumettant des patches via https://github.com/obonaventure/SystemesInformatiques - -********* -Exercices -********* - -.. toctree:: - :maxdepth: 2 - - intro - bib - -.. Projets/P1/projet-1 -.. Projets/P2/enonce -.. Projets/P3/enonce diff --git a/Exercices/intro.rst b/Exercices/intro.rst deleted file mode 100644 index e641d513d5404320cf1a1b582c11b89526d38b61..0000000000000000000000000000000000000000 --- a/Exercices/intro.rst +++ /dev/null @@ -1,220 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Introduction -============ - -Cette section comprend deux types d'exercices afin de permettre aux étudiants de mieux ancrer leur compréhension des bases des systèmes informatiques. Les premiers sont des questionnaires à choix multiples. Pour chaque module de cours, entre 5 et 10 questions à choix multiples seront proposées. Elles permettront à chaque étudiant(e) de valider sa compréhension de la matière. Ensuite, les étudiants seront invités à écrire de petits programmes, généralement en langage C. Ces programmes sont l'occasion de mettre en pratique les compétences acquises chaque semaine. La plupart des programmes ont un rôle formatif, ils permettront de guider la discussion avec les tuteurs durant les séances tutorées. Enfin, deux projets de groupe seront proposés aux étudiants. Leur évaluation contribuera à la cote finale. - - -Première semaine ----------------- - -La matière couverte cette semaine correspond à l'`introduction aux systèmes informatiques <https://sites.uclouvain.be/SystInfo/notes/Theorie/html/intro.html>`_ et au `langage C <https://sites.uclouvain.be/SystInfo/notes/Theorie/html/C/intro-C.html>`_ . Le volet pratique est important et les sections relatives au `shell <https://sites.uclouvain.be/SystInfo/notes/Outils/html/shell.html>`_ et aux `processus <https://sites.uclouvain.be/SystInfo/notes/Outils/html/processus.html>`_ de la section dédiée aux `autres outils <https://sites.uclouvain.be/SystInfo/notes/Outils/html>`_ devraient vous être utiles. - - -.. toctree:: - :maxdepth: 2 - - mcq-ex/qcm-1 - Programmes/prog-1 - - -Deuxième semaine ----------------- - -La matière couverte cette semaine correspond à la section relative aux `types de données <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/C/datatypes.html#les-expressions-de-manipulation-de-bits>`_ (jusque et y compris la section relative aux `expressions de manipulation de bits <http://sites.uclouvain.be/SystInfo/notes/Theorie/C/datatypes/#les-expressions-de-manipulation-de-bits>`_) - -.. toctree:: - :maxdepth: 2 - - mcq-ex/qcm-2 - Programmes/prog-2 - - -Troisième semaine ------------------ - -La matière couverte cette semaine correspond aux sections relative à l'`organisation de la mémoire <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/C/malloc.html#organisation-de-la-memoire>`_ Vous commencez à développer des programmes complets, le debugger `gdb <https://sites.uclouvain.be/SystInfo/notes/Outils/html/gdb.html>`_ pourrait vous aider. Il est décrit dans la section `gdb <https://sites.uclouvain.be/SystInfo/notes/Outils/html/gdb.html>`_ - -.. toctree:: - :maxdepth: 2 - - mcq-ex/qcm-3 - Programmes/prog-3 - - -Quatrième semaine ------------------ - -Durant les dernières semaines, vous avez appris les bases de l'écriture de fonctions en C. L'objectif de cette semaine est de vous amener à être capable d'écrire des programmes comprenant plusieurs fonctions. -La matière couverte cette semaine correspond aux sections : - - - :ref:`theorie:ordinateurs` - - :ref:`theorie:complementsC` - -En outre, vous devrez aussi lire les sections de la partie Outils qui sont relatives à - -- :ref:`outils:make` -- :ref:`outils:ref_cunit` - - -.. toctree:: - :maxdepth: 2 - - mcq-ex/qcm-4 - Programmes/prog-4 - - -Cinquième semaine ------------------ - - -La matière de cette semaine porte sur l'utilisation du système de fichiers et les ``pipe``. Elle est décrite dans les sections : - - - :ref:`theorie:utilisateurs` - - :ref:`theorie:fichiers` - - :ref:`theorie:pipe` - - -.. toctree:: - :maxdepth: 2 - - mcq-ex/qcm-9 - Programmes/prog-5 - - -Sixième semaine ---------------- - -La matière couverte cette semaine correspond aux sections : - - - - :ref:`theorie:threads` (sauf la section `Utilisation d'instruction atomique`) - - :ref:`theorie:comthreads` (jusqu'à la section `Le problème des philosophes`) - -.. toctree:: - :maxdepth: 2 - - mcq-ex/qcm-6 - Programmes/prog-6 - - -Septième semaine ----------------- - -La matière de cette semaine porte sur l'utilisation des mutex et des sémaphores et quelques compléments sur les threads. Elle est décrite dans la section : - - - :ref:`theorie:comthreads` (à partir de la section `Le problème des philosophes`) - - :ref:`theorie:coordinationthreads` - -En outre, vous devrez aussi lire les sections de la partie Outils qui sont relatives à - -- :ref:`outils:valgrind-ref` -- :ref:`outils:gdb-ref` - -.. toctree:: - :maxdepth: 2 - - mcq-ex/qcm-7 - Programmes/prog-7 - -Huitième semaine ----------------- - -La matière de cette semaine porte sur le fonctionnement des processus. Elle est décrite dans la section : - - - :ref:`theorie:processus` - -.. toctree:: - :maxdepth: 2 - - mcq-ex/qcm-8 - Programmes/prog-8 - - - -Neuvième semaine ----------------- - -La matière de cette semaine porte sur les pipes, la mémoire virtuelle et les fichiers mappés en mémoire : - - - :ref:`theorie:pipe` - - :ref:`theorie:vmem` - - :ref:`theorie:fctvmem` - - :ref:`theorie:stockage` - - :ref:`theorie:remplacement` - - :ref:`theorie:mmap` - - -.. only:: html - - `QCM11 <http://sites.uclouvain.be/SystInfo/qcm/Mission-11-qcm.html>`_ - - -Séance tutorée -^^^^^^^^^^^^^^ - -.. toctree:: - :maxdepth: 2 - - Programmes/prog-11 - - -Dixième semaine ---------------- - -La matière de cette semaine porte sur les utilisations avancées de la mémoire virtuelle, les sméaphores nommés et le partage de fichiers : - - - :ref:`theorie:shmem` - - :ref:`theorie:forkmem` - - :ref:`theorie:vmstat` - - :ref:`theorie:execvmem` - - :ref:`theorie:semname` - - :ref:`theorie:fileshare` - -Séance tutorée -^^^^^^^^^^^^^^ - -.. toctree:: - :maxdepth: 2 - - Programmes/prog-12 - -Onzième semaine ---------------- - -La matière de cette semaine porte sur l'utilisation du processeur intel 32 bits en langage assembleur - - - `Organisation des ordinateurs <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/Assembleur/memory.html>`_ - - `Etude de cas : IA32 <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/Assembleur/memory.html#etude-de-cas-architecture-ia32>`_ - - -Séance tutorée -^^^^^^^^^^^^^^ - -.. toctree:: - :maxdepth: 2 - - mcq-ex/qcm-4-asm - Programmes/prog-4-asm - - -Douzième semaine ----------------- - -La matière de cette semaine porte sur les signaux, les sémaphores nommés et le partage de fichiers : - - - :ref:`theorie:signaux` - - -Séance tutorée -^^^^^^^^^^^^^^ - -.. toctree:: - :maxdepth: 2 - - mcq-ex/qcm-10 - Programmes/prog-10 - diff --git a/Exercices/mcq-ex/qcm-1.rst b/Exercices/mcq-ex/qcm-1.rst deleted file mode 100644 index 9cec8736f6daffe68a5dc5afb7ae29b67b187668..0000000000000000000000000000000000000000 --- a/Exercices/mcq-ex/qcm-1.rst +++ /dev/null @@ -1,301 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -Questions à choix multiples -=========================== -:task_id: sinf1252-1 - -Ces questions ont pour objectif de vous permettre de tester vous-même votre compréhension de la matière couverte par cette mission de mise en route. Elles supposent que vous avez lu le premier chapitre du syllabus contenant l'introduction à Unix et au langage C. - - -Question 1. Commande `man(1)`_ ------------------------------- - -.. question:: man - :nb_prop: 3 - :nb_pos: 1 - - La commande `man(1)`_ permet de lire les pages de manuel d'un système Unix. Elle est particulièrement utile pour vérifier les arguments à donner à un programme en ligne de commande ou pour savoir comment utiliser certaines fonctions de la librairie standard ou appels systèmes. Comment faut-il appeler la commande `man(1)`_ pour lister toutes les pages de manuel dont le résumé contient le mot ''intro'' ? - - .. positive:: - - .. code-block:: console - - man -k intro - - .. negative:: - - .. code-block:: console - - man intro - - .. comment:: - - Cette commande permet d'obtenir la page dénommée ``intro`` mais uniquement dans la première section du manuel. Elle ne liste pas toutes les pages dont le résumé contient le mot clé ``intro``. - - .. negative:: - - .. code-block:: console - - man -k *intro* - - .. comment:: - - Par défaut, lorsque vous passez un argument tel que ``*intro*`` en ligne de commande, le shell va tenter de remplacer ``*intro*`` par tous les noms de fichiers du répertoire courant qui contiennent l'expression régulière qui commence par n'importe quelle suite de caractères, contient ``intro`` et se termine par n'importe quelle suite de caractères. Si le répertoire dans lequel vous exécutez cette commande contient les fichiers ``intro.txt`` et ``intro.dat``, ``man`` recevra ces deux noms de fichiers comme arguments. - - -Question 2. Commande `ls(1)`_ ------------------------------ - -.. question:: ls - :nb_prop: 3 - :nb_pos: 1 - - La commande `ls(1)`_ permet de lister le contenu d'un répertoire. Elle supporte de nombreux paramètres. Parmi les groupes d'affirmation suivants, un seul est valide, lequel ? - - .. positive:: - - - Dans un répertoire, la commande ``ls -a`` sans argument permet d'afficher la liste de tous les fichiers et répertoires présents - - La commande ``ls -r`` permet de lister les répertoires présents dans le répertoire courant en inversant l'ordre - - La commande ``ls -l`` permet d'obtenir la liste détaillée du contenu du répertoire courant avec toutes les informations relatives à chaque fichier et répertoire non cachés - - .. comment:: Réponse correcte. - - .. positive:: - - - Dans un répertoire, la commande ``ls -a`` sans argument permet d'afficher la liste de tous les fichiers et répertoires présents - - La commande ``ls -R`` permet de lister de façon récursive le contenu du répertoire courant et de ses sous-répertoires - - La commande ``ls -l`` permet d'obtenir la liste détaillée du contenu du répertoire courant avec toutes les informations relatives à chaque fichier et répertoire non cachés - - .. comment:: Réponse correcte. - - .. negative:: - - - Dans un répertoire, la commande ``ls *`` permet d'afficher la liste de tous les fichiers et répertoires présents - - La commande ``ls -f`` permet de lister le contenu du répertoire courant sans trier les fichiers par nom - - La commande ``ls -l`` permet d'obtenir la liste détaillée du contenu du répertoire courant avec toutes les informations relatives à chaque fichier et répertoire - - .. comment:: Relisez la page de manuel de `ls(1)`_. Sous Unix, le shell va remplacer ``*`` par l'ensemble des fichiers présents dans le répertoire courant - - .. negative:: - - - Dans un répertoire, l'appel à `ls(1)`_ sans argument permet d'afficher la liste de tous les fichiers et répertoires présents - - La commande ``ls -r`` permet de lister de façon récursive le contenu du répertoire courant et de ses sous-répertoires - - La commande ``ls -l`` permet d'obtenir la liste détaillée du contenu du répertoire courant avec toutes les informations relatives à chaque fichier et répertoire - - .. comment:: Relisez la page de manuel de `ls(1)`_. Sous Unix, l'appel à `ls(1)`_ sans argument dans le shell affichera l'ensemble des fichiers présents dans le répertoire courant - - - -Question 3. Premier programme en langage C ------------------------------------------- - -.. question:: hello - :nb_prop: 3 - :nb_pos: 1 - - - Depuis la publication du livre de référence [KernighanRitchie1998], le premier programme écrit en langage C affiche à l'écran la chaîne de caractères "Hello, world". Parmi les codes source ci-dessous, un seul est entièrement correct. Lequel ? - - - .. positive:: - - .. code-block:: c - - #include <stdio.h> - int main(int argc, const char *argv[]) { - printf("Hello, world\n"); - } - - .. comment:: Réponse correcte. - - .. positive:: - - .. code-block:: c - - #include <stdio.h> - int main(int argc, const char *argv[]) { - printf("Hello,"); - printf(" world\n"); - } - - .. comment:: Réponse correcte. - - .. negative:: - - .. code-block:: c - - #include <stdio.h> - void main(int argc, const char *argv[]) { - printf("Hello, world\n"); - } - - .. comment:: En C, contrairement à Java, la fonction ``main`` retourne une valeur de type ``int``. - - .. negative:: - - .. code-block:: c - - int main(int argc, const char *argv[]) { - printf("Hello, world\n"); - } - - - .. comment:: La fonction `printf(3)`_ utilisée par ce programme fait partie de la librairie standard de gestion des I/O. Pour l'utiliser, il faut inclure le header `stdio.h`_. Même si certains compilateurs pouvaient l'inclure par défaut, il est préférable de spécifier ce header explicitement. - - .. negative:: - - .. code-block:: c - - #include <stdlib.h> - int main() { - printf("Hello, world\n"); - } - - - .. comment:: En C, la signature de la fonction ``main`` est ``int main(int argc, const char *argv[])`` même si certains compilateurs peuvent être tolérants. `printf(3)`_ est défini via `stdio.h`_ et non `stdlib.h`_. - - .. negative:: - - .. code-block:: c - - #include <stdlib.h> - void main() - printf("Hello, world\n"); - } - - - .. comment:: En C, la signature de la fonction ``main`` est ``int main(int argc, const char *argv[])`` même si certains compilateurs peuvent être tolérants. `printf(3)`_ est défini via `stdio.h`_ et non `stdlib.h`_. - - -Question 4. Deuxième programme en langage C --------------------------------------------- - -.. question:: 2ndprog - :nb_prop: 3 - :nb_pos: 1 - - Votre deuxième programme en langage C doit afficher à l'écran la chaîne de caractères `SINF1252`. Lequel parmi les programmes ci-dessous affiche-t-il correctement cette chaîne de caractères ? - - .. positive:: - - .. code-block:: c - - #include <stdio.h> - int main(int argc, const char *argv[]) { - int a = 1252; - printf("SINF%d\n", a); - } - - .. comment:: En C, la fonction `printf(3)`_ prend un nombre variable d'arguments. Le premier est toujours une spécification de formatage qui indique la chaîne de caractères à afficher. Les autres arguments sont des identifiants de variables dont les valeurs seront utilisées pour construire la chaîne de caractères à afficher. Le deuxième argument remplace le premier format `%d`, le troisième argument le deuxième format, etc. La page de manuel de `printf(3)`_ fournit de nombreux détails sur le fonctionnement de cette fonction qui accepte de nombreux paramètres. - - .. positive:: - - .. code-block:: c - - #include <stdio.h> - int main(int argc, const char *argv[]) { - int a = 1252; - printf("SINF"); - printf("%d\n", a); - } - - .. comment:: En C, la fonction `printf(3)`_ prend un nombre variable d'arguments. Le premier est toujours une spécification de formatage qui indique la chaîne de caractères à afficher. Les autres arguments sont des identifiants de variables dont les valeurs seront utilisées pour construire la chaîne de caractères à afficher. Le deuxième argument remplace le premier format `%d`, le troisième argument le deuxième format, etc. La page de manuel de `printf(3)`_ fournit de nombreux détails sur le fonctionnement de cette fonction qui accepte de nombreux paramètres. - - .. negative:: - - .. code-block:: none - - #include <stdio.h> - int main(int argc, const char *argv[]) { - int a = 1252; - printf("SINF%a\n", a); - } - - .. comment:: Dans la fonction `printf(3)`_, ``%a`` est utilisé lorsque l'on veut placer dans une chaîne de caractères un nombre réel en notation hexadécimale. Dans ce cas, ``a`` étant un entier, il aurait fallu utiliser ``%d``. - - .. negative:: - - .. code-block:: none - - #include <stdio.h> - int main(int argc, const char *argv[]) { - int a = 1252; - printf(SINF); - printf(%d\n, a); - } - - .. comment:: En C, une chaîne de caractères (ou un descripteur de format pour `printf(3)`_ qui est aussi une chaîne de caractères) commence et se termine par le caractère ``"``. - - .. negative:: - - .. code-block:: c - - #include <stdio.h> - int main(int argc, const char *argv[]) { - int a = 1252; - printf("SINF$a\n", a); - } - - .. comment:: Dans la fonction `printf(3)`_ en C, et contrairement à d'autres langages, le caractère ``$`` ne joue pas de rôle particulier. Le programme ci-dessus affichera donc simplement ``SINF$a`` à l'écran. - - -Question 5. Arguments passés à un programme C ------------------------------------------------ - - -.. question:: args - :nb_prop: 3 - :nb_pos: 1 - - Considérons le programme C ci-dessous qui permet de manipuler les arguments passés en ligne de commande. - - .. code-block:: c - - - #include <stdio.h> - #include <stdlib.h> - int main(int argc, const char *argv[]) - { - int a = atoi(argv[1]); - printf("%d\n", a); - } - - - Parmi les groupes d'affirmations ci-dessous, un seul ne contient que des affirmations qui sont toutes vraies. Lequel ? - - - .. positive:: - - - Lors de l'exécution de la fonction ``main``, ``argc`` est initialisé au nombre d'arguments passés au programme (y compris le nom de l'exécutable lui-même). - - Lors de l'exécution de la fonction ``main``, le tableau ``argv[]`` contient dans ``argv[0]`` le nom du programme, dans ``argv[1]`` le premier argument, etc. - - La fonction ``atoi`` permet de convertir une chaîne de caractères en l'entier équivalent. - - .. comment:: Réponse correcte. - - .. negative:: - - - - Lors de l'exécution de la fonction ``main``, ``argc`` est initialisé à zéro. - - Lors de l'exécution de la fonction ``main``, le tableau ``argv[]`` contient dans ``argv[0]`` le premier argument, dans ``argv[1]`` le second argument, etc. - - La fonction ``atoi`` calcule la taille de son argument. - - .. comment:: Les trois affirmations sont fausses. ``argc`` sera toujours initialisé à un vu que le nom du programme est toujours passé en argument. Le premier élément du tableau ``argv[]``, ``argv[0]``, est le nom du programme qui est exécuté. Enfin, la fonction ``atoi`` permet de convertir une chaîne de caractères en l'entier équivalent. - - .. negative:: - - - Lors de l'exécution de la fonction ``main``, ``argc`` est le nombre maximum d'arguments que l'on peut lui passer. - - Lors de l'exécution de la fonction ``main``, le tableau ``argv[]`` contient dans ``argv[0]`` le premier argument, dans ``argv[1]`` le second argument, etc. - - La fonction ``atoi`` doit prendre comme argument une chaîne de caractères qui ne contient que des chiffres. - - .. comment:: Les deux premières affirmations sont fausses. ``argc`` contient le nombre d'arguments passés effectivement au programme. Le premier élément du tableau ``argv[]``, ``argv[0]``, est le nom du programme qui est exécuté. - - .. negative:: - - - Lors de l'exécution de la fonction ``main``, le tableau ``argv[]`` contient dans ``argv[0]`` le premier argument, dans ``argv[1]`` le second argument, etc. - - La fonction ``atoi`` permet de convertir une chaîne de caractères en l'entier équivalent. - - .. comment:: Le premier élément du tableau ``argv[]``, ``argv[0]``, est le nom du programme qui est exécuté. - diff --git a/Exercices/mcq-ex/qcm-10.rst b/Exercices/mcq-ex/qcm-10.rst deleted file mode 100644 index 77d6ecfd31ccc6a59b051c2fe9454027ba950592..0000000000000000000000000000000000000000 --- a/Exercices/mcq-ex/qcm-10.rst +++ /dev/null @@ -1,228 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. sectionauthor:: Gregory Vander Schueren <gregory.vanderschueren@student.uclouvain.be> - -Questions à choix multiples -=========================== - -:task_id: sinf1252-10 - -Question 1. Signaux synchrones et asynchrones ---------------------------------------------- - -Un signal est dit synchrone lorsqu'il est causé par l'exécution d'une instruction du processus. Un signal est dit asynchrone s'il n'a pas été causé directement par l'exécution d'un instruction du processus. - -.. question:: signal_sync_async - :nb_prop: 4 - :nb_pos: 2 - - Parmi les affirmations suivantes, lesquelles sont correctes ? - - .. positive:: - - - Le signal SIGFPE est synchrone. - - .. positive:: - - - Le signal SIGSEGV est synchrone. - - .. positive:: - - - Le signal SIGALRM est asynchrone. - - .. negative:: - - - Le signal SIGCHLD est synchrone. - - .. comment:: Ce signal indique qu'un processus fils s'est arrêté ou a fini son exécution. Il résulte d'une cause externe au programme. - - .. negative:: - - - Le signal SIGINT est synchrone. - - .. comment:: Ce signal est envoyé par le shell lorsque l'utlisateur tape Ctrl-C pendant l'exécution d'un programme. Il résulte d'une cause externe au programme. - - .. negative:: - - - Le signal SIGTERM est synchrone. - - .. comment:: Ce signal est le signal utilisé par défaut par la commande kill pour demander la fin d'un processus. Il résulte d'une cause externe au programme. - - .. negative:: - - - Le signal SIGBUS est synchrone. - - .. comment:: Ce signal correspond à une erreur matérielle. Il résulte d'une cause externe au programme. - - - -Question 2. Signaux pour arrêter un processus ---------------------------------------------- - - - -.. question:: signal_stop_process - :nb_prop: 4 - :nb_pos: 2 - - Trois signaux permettent d'arrêter un processus: SIGTERM, SIGINT et SIGKILL. Parmi les affirmations suivantes, lesquelles sont correctes ? - - .. positive:: - - - Envoyer un signal SIGKILL à un processus le termine toujours immédiatement. - - .. positive:: - - - Lorsque l'on tappe Ctrl-C dans le shell pendant l'exécution d'un programme, un signal SIGINT est envoyé au processus en cours d'exécution. - - .. positive:: - - - Envoyer un signal SIGTERM ou SIGINT est préférable à SIGKILL car le processus peut prévoir une routine de traitement de signal pour se terminer proprement. - - .. negative:: - - - Envoyer un signal SIGTERM à un processus le termine toujours immédiatement. - - .. comment:: Par défaut, la réception de ce signal provoque la terminaison du processus. Néanmoins, le processus peut prévoir une routine de traitement pour ce type de signal ou choisir d'ignorer ce type de signal. - - .. negative:: - - - Lorsque l'on tappe Ctrl-C dans le shell pendant l'exécution d'un programme, un signal SIGTERM est envoyé au processus en cours d'exécution. - - .. comment:: C'est un signal SIGINT qui est envoyé au processus en cours d'exécution. - - .. negative:: - - - Envoyer un signal SIGTERM ou SIGKILL est préférable à SIGTERM car le processus peut prévoir une routine de traitement de signal pour se terminer proprement. - - .. comment:: Un processus ne peut pas prévoir de routine de traitement pour SIGKILL ni choisir d'ignorer ce type de signal. - -Question 3. Routines de traitement de signal --------------------------------------------- - -Un étudiant a décidé d'implémenter un programme simulant une bombe à retardement qui détonne 1h après son intialisation. Pour accélérer le décompte, l'étudiant a enregistré un handler pour le signal SIGUSR1 qui divise par 2 le temps restant à décompter. - -.. code-block:: c - - #include <stdio.h> - #include <stdlib.h> - #include <signal.h> - #include <unistd.h> - - int counter = 3600; - - void counter_boost(int signum) { - counter=counter/2; - printf("Boost!\n"); - } - - int main () { - if (signal(SIGUSR1,counter_boost)==SIG_ERR) { - perror("signal"); - exit(EXIT_FAILURE); - } - - while(counter>0) { - counter--; - printf("%d seconds left\n", counter); - sleep(1); - } - - printf("BOOM!"); - return(EXIT_SUCCESS); - } - - - -.. question:: signal_handlers - :nb_prop: 3 - :nb_pos: 1 - - Ce programme, bien qu'en apparence fonctionnel, contient plusieurs erreurs de programmation. Parmi les affirmations suivantes, laquelle est correcte ? - - .. positive:: - - - Il y a un risque que la variable counter soit accédée en même temps par le processus et la routine de traitement de signal. Il est nécessaire de la déclarer sig_atomic_t pour résoudre ce problème. - - .. comment:: Avec sig_atomic_t, le compilateur garantit que tous les accès à la variable se feront de façon atomique. - - - .. positive:: - - - La fonction `printf(3)`_ n'est pas réentrante et ne doit pas être utilisée dans une routine de traitement de signal. - - .. comment:: La fonction `printf(3)`_ modifie des données globales (le buffer attaché au stream). Cette dernière est documentée comme non réentrante et ne doit donc pas être utilisée dans une routine de traitement de signal. - - - .. negative:: - - - Il y a un risque que la variable counter soit accédée en même temps par le processus et la routine de traitement de signal. Il est nécessaire de protéger cette variable par un mutex. - - .. comment:: Cette solution peut causer un deadlock. La routine de traitement de signal est asynchrone et peut être appelée à tout moment. Si le mutex est déjà utilisé à ce moment là , la routine de traitement de signal restera bloquée sur l'appel `pthread_mutex_lock(3posix)`_. - - - .. negative:: - - - Il y a un risque que la variable counter soit accédée en même temps par le processus et la routine de traitement de signal. Il est nécessaire de la déclarer volatile pour résoudre ce problème. - - .. comment:: Il est toujours possible que le processus exécute l'instruction de chargement de la valeur de la variable puis qu'un signal lui soit délivré. Lorsque le processus revient à son flux d'éxécution normal, la valeur de la variable a changé mais elle n'est pas rechargée depuis la mémoire. - - - .. negative:: - - - Il est interdit de modifier une variable globale (telle que counter) dans une routine de traitement de signal. - - .. comment:: La modification de variables globales dans une routine de traitement de signal est autorisée. Il est néanmoins nécessaire de prendre certaines précautions et la déclarer avec sig_atomic_t pour garantir que tous les accès à la variable se feront de façon atomique. - - - -Question 4. Implémentation des signaux sous Unix ------------------------------------------------- - -Deux stratégies existent pour implémenter les signaux sous Unix: maintenir une queue de tous les signaux destinés à un processus donné ou représenter l'ensemble des signaux qu'un processus peut recevoir sous la forme de drapeaux binaires (un par signal). Linux utilise la seconde stratégie. - -.. question:: signal_implementation_strategies - :nb_prop: 4 - :nb_pos: 1 - - Parmi les affirmations suivantes, lesquelles sont correctes ? - - .. positive:: - - - La solution sous forme de queue sans limite de taille permet de s'assurer que tout signal envoyé au processus est reçu par le processus. - - .. positive:: - - - La solution sous forme de drapeaux binaires ne nécessite qu'un seul bit de mémoire par signal mais n'est pas forcément meilleure que la solution utilisant une queue. - - .. comment:: C'est une question de compromis. La solution sous forme de drapeaux binaires est plus économe en mémoire mais n'est pas fiable. - - .. negative:: - - - La solution utilisant une queue permet de s'assurer que tout signal envoyé au processus est reçu par le processus. Elle est donc meilleure que la solution sous forme de drapeaux binaires. - - .. comment:: C'est une question de compromis. La solution utilisant une queue peut devenir très gourmande en mémoire s'il n'y a pas de limite sur la taille de la queue. - - - .. negative:: - - - Une solution intermédiaire utilisant 10 drapeaux par type de signal permettrait d'être à la fois fiable et économe en mémoire. - - .. comment:: Elle permettrait d'être fiable seulement pour les 10 premiers signaux de même type reçus. - - - .. negative:: - - - La solution utilisant des drapeaux binaires permet de s'assurer que tout signal envoyé au processus est reçu par le processus. - - .. comment:: Si le signal est envoyé 2 fois au processus avant l'exécution de la prochaine routine de traitement de signal, le drapeau sera mis à vrai et la routine de traitement de signal ne sera appelée qu'une seule fois. - - - .. negative:: - - - Avec la solution utilisant des drapeaux binaires, seul les signaux envoyés plusieurs fois avant l'exécution routine de traitement de signal seront perdus. - - .. comment:: Si un autre signal arrive durant l'exécution de la routine de traitement de signal, celui-ci sera perdu car bloqué par le système d'exploitation pour empêcher l'interruption de la routine de traitement du précédent signal. - - diff --git a/Exercices/mcq-ex/qcm-2.rst b/Exercices/mcq-ex/qcm-2.rst deleted file mode 100644 index a09a717c40ef0c4c32542b7258951de8a1abb283..0000000000000000000000000000000000000000 --- a/Exercices/mcq-ex/qcm-2.rst +++ /dev/null @@ -1,820 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - - - -Questions à choix multiples -=========================== - -:task_id: sinf1252-2 - -La matière couverte cette semaine la section relative aux `types de données <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/C/datatypes.html>`_ (jusque et y compris la section relative aux `expressions de manipulation de bits <http://sinf1252.info.ucl.ac.be/Theorie/C/datatypes/#les-expressions-de-manipulation-de-bits>`_ - - -Question 1. Conversion de types -------------------------------- - -En C tout comme dans des langages comme Java, il est possible de convertir des nombres d'un type primitif vers un autre. Cependant, alors que le compilateur Java vérifie si la conversion est sans risque, le compilateur C ne fait aucune vérification et suppose que si le programmeur a effectué une conversion explicite entre types, il a pris ses précautions. Sur une architecture où les types de données sont stockés comme suit : - -.. code-block:: c - - // char 1 octet(s) - // unsigned char 1 octet(s) - // short 2 octet(s) - // unsigned short 2 octet(s) - // int 4 octet(s) - // unsigned int 4 octet(s) - - - int i; - short s; - long l; - char c; - unsigned int ui; - unsigned char uc; - unsigned long ul; - unsigned short us; - - -.. question:: conversiontypes - :nb_prop: 3 - :nb_pos: 1 - - Un seul des fragments de code ci-dessous contient des conversions de type qui sont sans risque. Lequel ? - - .. positive:: - - .. code-block:: c - - i=(int ) s; - s=(short) uc; - l=(long )i; - - .. positive:: - - .. code-block:: c - - ui=(unsigned int) us; - s=(short) c; - ul=(unsigned long )ui; - - - .. negative:: - - .. code-block:: c - - ui=(unsigned int ) s; - us=(unsigned short) uc; - l=(long )i; - - .. comment:: Si ``s`` est négatif, la conversion en ``unsigned int`` risque de poser problème. - - - .. negative:: - - .. code-block:: c - - i=(int ) us; - us=(unsigned short) i; - l=(long )c; - - .. comment:: La conversion d'un ``int`` en un ``unsigned short`` risque de poser problème. - - .. negative:: - - .. code-block:: c - - ui=(int) s; - s=(short) c; - ul=(unsigned long )ui; - - .. comment:: La première conversion risque de poser des problèmes. - - -Question 2. Notation hexadécimale ---------------------------------- - -.. question:: hexa - :nb_prop: 3 - :nb_pos: 1 - - Parmi les affirmations suivantes relatives aux nombres en représentation hexadécimale, une seule est vraie. Laquelle ? - - .. positive:: - - La représentation hexadécimale du nombre entier positif ``27`` est ``1B`` - - .. positive:: - - La représentation hexadécimale du nombre entier positif ``67`` est ``43`` - - .. negative:: - - La représentation hexadécimale du nombre entier positif ``67`` est ``34`` - - .. comment:: :math:`3*16+4` ne vaut pas ``67`` - - .. negative:: - - La représentation hexadécimale du nombre entier positif ``27`` est ``B1`` - - .. comment:: :math:`11*16+1` ne vaut pas ``27`` - - .. negative:: La représentation hexadécimale du nombre entier positif ``62`` est ``B1`` - - .. comment:: :math:`11*16+1` ne vaut pas ``62`` - - .. negative:: - - La représentation hexadécimale du nombre entier positif ``128`` est ``FF`` - - .. comment:: :math:`15*16+15` ne vaut pas ``128`` - - -Question 3. Notation binaire ----------------------------- - -.. question:: binaire - :nb_prop: 3 - :nb_pos: 1 - - Parmi les affirmations suivantes relatives aux nombres en représentation binaire, une seule est vraie. Laquelle ? - - - .. positive:: - - La représentation binaire du nombre entier positif ``99`` est ``1100011`` - - .. positive:: - - La représentation binaire du nombre entier positif ``176`` est ``10110000`` - - .. negative:: - - La représentation binaire du nombre entier positif ``90`` est ``1100011`` - - .. comment:: La représentation binaire de ``90`` est ``1011010`` - - .. negative:: - - La représentation binaire du nombre entier positif ``176`` est ``10110001`` - - .. comment:: C'est la représentation de ``177``. - - .. negative:: - - La représentation binaire du nombre entier positif ``166`` est ``10110001`` - - .. comment:: C'est la représentation de ``177``. - - .. negative:: - - La représentation binaire d'un nombre entier positif impair a toujours ``0`` comme bit de poids faible. - - .. comment:: Ce sont les entiers positifs pairs (et zéro) qui ont ``0`` comme bit de poids faible. - - -Question 4. Notation binaire ----------------------------- - -.. question:: binaire2 - :nb_prop: 3 - :nb_pos: 1 - - Parmi les affirmations suivantes relatives aux nombres signés en représentation binaire, une seule est vraie. Laquelle ? - - - .. positive:: - - Si la variable ``x`` est un ``short`` (signé) sur 16 bits, alors la représentation binaire de ``-17`` est ``11111111 11101111`` - - .. positive:: - - Si la variable ``x`` est un ``short`` (signé) sur 16 bits, alors la représentation binaire de ``-23`` est ``11111111 11101001`` - - .. negative:: - - Si la variable ``x`` est un ``short`` (signé) sur 16 bits, alors la représentation binaire de ``-17`` est ``00000000 00010001`` - - .. comment:: C'est la représentation de ``17`` mais en non-signé - - .. negative:: - - Si la variable ``x`` est un ``short`` (signé) sur 16 bits, alors la représentation binaire de ``-17`` est ``10000000 00010001`` - - .. comment:: C'est la représentation de ``-32751`` - - .. negative:: - - Si la variable ``x`` est un ``short`` (signé) sur 16 bits, alors la représentation binaire de ``-23`` est ``00000000 00010111`` - - - .. comment:: C'est la représentation de ``23`` - - .. negative:: - - Si la variable ``x`` est un ``short`` (signé) sur 16 bits, alors la représentation binaire de ``-23`` est ``11111111 11100110`` - - - .. comment:: C'est la représentation de ``-26`` - - -.. http://www.binaryconvert.com/ pour des conversions sur le web - - - -Question 5. Manipulations de bits ---------------------------------- - -.. question:: manipbits - :nb_prop: 3 - :nb_pos: 1 - - Si la variable ``c`` est de type ``unsigned char`` sur 8 bits, laquelle des suites d'instructions ci-dessous permet d'en échanger les 4 bits de poids faible avec les 4 bits de poids fort ? - - - .. positive:: - - - .. code-block:: c - - unsigned char temp1, temp2; - temp1 = c & 0x0F; - temp2 = c & 0xF0; - temp1=temp1 << 4; - temp2=temp2 >> 4; - c= temp2|temp1; - - .. positive:: - - .. code-block:: c - - unsigned char temp1, temp2; - temp1=c << 4; - temp2=c >> 4; - c= temp2|temp1; - - - .. negative:: - - - .. code-block:: c - - unsigned char temp1, temp2; - temp1=c << 4; - temp2=c >> 4; - c= temp2||temp1; - - - .. comment:: Ne confondez pas l'opérateur binaire ``|`` avec la disjonction logique ``||``. - - - .. negative:: - - .. code-block:: c - - unsigned char temp1, temp2; - temp1=4 << temp1; - temp2=4 >> temp2; - c= temp2|temp1; - - - .. comment:: Cette utilisation de l'opérateur ``>>`` est incorrecte. Vous décalez de ``temp1`` bits (c'est-à -dire 0) la représentation binaire de ``4``. - - .. negative:: - - .. code-block:: c - - unsigned char temp1, temp2; - temp1 = c && 0x0F; - temp2 = c && 0xF0; - temp1=temp1 << 4; - temp2=temp2 >> 4; - c= temp2|temp1; - - - .. comment:: Ne confondez pas la l'opérateur binaire ``&`` avec la conjonction logique ``&&``. - - -Question 6. Multiplication entière ----------------------------------- - -.. question:: multiInt - :nb_prop: 3 - :nb_pos: 1 - - Parmi les expressions suivantes, une seule permet de calculer ``x*7`` lorsque ``x`` est un nombre entier. Laquelle ? - - - .. positive:: - - .. code-block:: c - - (x<<3)-x - - - .. comment:: Cette expression calcule en effet ``x<<3=x*8`` puis retire ``x``. - - .. negative:: - - - .. code-block:: c - - (x>>3)-x - - - .. comment:: Cette expression divise d'abord ``x`` par ``8`` puis retire x au résultat de cette division. - - .. negative:: - - .. code-block:: c - - (x<<3)+x - - .. comment:: Cette expression multiplie ``x`` par ``8`` puis ajoute ``x`` au résultat. Elle multiple donc ``x`` par ``9``. - - - .. negative:: - - .. code-block:: c - - (x<<7) - - - .. comment:: Cette expression multiplie ``x`` par :math:`2^7` - - .. negative:: - - .. code-block:: c - - (x>>7) - - .. comment:: Cette expression divise ``x`` par :math:`2^7` - -Question 7. Extraction de bits ------------------------------- - -.. question:: extraction - :nb_prop: 3 - :nb_pos: 1 - - Il est parfois nécessaire en C de manipuler directement la représentation binaire d'un nombre. Si ``f`` est un nombre de type ``float`` stocké sur 32 bits, laquelle des expressions ci-dessous peut-elle être intégrée dans ce code pour afficher positif ou négatif en fonction du signe de ce nombre ? - - .. code-block:: none - - if(<à compléter>) - printf("positif\n"); - else - printf("negatif\n"); - - - .. positive:: - - .. code-block:: c - - !(((unsigned int) f) & 0x80000000) - - .. positive:: - - .. code-block:: c - - !(((unsigned int) f) >> 31) - - .. negative:: - - - .. code-block:: c - - !(((unsigned int) f) & 0x10000000) - - .. comment:: En faisant ``& 0x10000000``, vous mettez tous les bits de ``f`` à ``0`` sauf le bit ``28`` alors que le bit de signe est le bit de poids fort (``31``). - - .. negative:: - - .. code-block:: c - - !(((unsigned int) f) << 31) - - .. comment:: Cette opération décale la représentation binaire de ``f`` de 31 bits vers la gauche, c'est-à -dire que seul le bit de poids faible reste. Malheureusement, le signe se trouve dans le bit de poids faible et non dans le bit de poids fort. - - - .. negative:: - - .. code-block:: c - - !(((unsigned int) f) > 31) - - .. comment:: Ne confondez pas ``>`` et ``>>``. - - - .. negative:: - - .. code-block:: c - - !(((unsigned int) f) & 31) - - .. comment:: Cette opération masque le nombre ``f`` avec ``00000000 00000000 00000000 00011111`` - - - -Question 8. Chaînes de caractères ---------------------------------- - -.. question:: string - :nb_prop: 3 - :nb_pos: 1 - - Une seule des fonctions ci-dessous retourne correctement le nombre d'occurrences du caractère ``c`` dans la chaîne de caractères ``c``. Laquelle ? - - .. positive:: - - .. code-block:: c - - int count1(char *s, char c) { - int i=0; - int count=0; - while(*(s+i)!='\0') { - if(*(s+i)==c) { - count++; - } - i++; - } - return(count); - } - - - .. positive:: - - .. code-block:: c - - int count(char *s, char c) { - int count=0; - while(*(s)!='\0') { - if(*(s)==c) { - count++; - } - s++; - } - return(count); - } - - - .. negative:: - - .. code-block:: c - - int count1(char *s, char c) { - int i=0; - int count=0; - while(i<s.length) { - if(*(s+i)==c) { - count++; - } - i++; - } - return(count); - } - - .. comment:: ``s`` est un pointeur vers une chaîne de caractères et non une structure. Ce code ne compile pas. - - .. negative:: - - .. code-block:: none - - int count1(char *s, char c) { - int i=0; - int count=0; - while(*s!=`\0`) { - if(*(s+i)==c) { - count++; - } - i++; - } - return(count); - } - - .. comment:: La boucle ``while`` se termine-t-elle ? Quelle est sa condition d'arrêt ? - - .. negative:: - - .. code-block:: c - - int count(char *s, char c) { - int count=0; - while(*(s)!='\0') { - s++; - if(*(s)==c) { - count++; - } - } - return(count); - } - - .. comment:: Ce code compte-il correctement le caractère si il est présent en première position de la chaîne ? - - - .. negative:: - - .. code-block:: c - - int count(char *s, char c) { - int count=0; - while(s!='\0') { - if(s==c) { - count++; - } - s++; - } - return(count); - } - - .. comment:: Ce code compare le pointeur ``s`` c'est-à -dire *l'adresse* du première caractère de la chaîne ``s`` en mémoire avec ``\0`` et ``c`` et non le caractère pointé par ``s``. - - -Question 9. Pointeurs ---------------------- - -.. question:: ptr - :nb_prop: 3 - :nb_pos: 1 - - Si ``ptr`` a été déclaré sous la forme ``int *ptr``, un seul des groupes d'affirmations suivantes est vrai, lequel ? - - .. positive:: - - - l'expression ``*(ptr + 1)`` est une valeur entière - - l'expression ``ptr[1]`` est une valeur entière - - l'expression ``ptr`` est une adresse en mémoire - - - .. positive:: - - - l'expression ``*(ptr) + 1`` est une valeur entière - - l'expression ``ptr[2]`` est une valeur entière - - l'expression ``ptr++`` est une adresse en mémoire - - - .. negative:: - - - l'expression ``&(ptr) + 1`` est un nombre entier - - l'expression ``ptr[2]`` est une valeur entière - - l'expression ``&ptr`` est une adresse en mémoire - - .. negative:: - - - l'expression ``*(ptr+1)==ptr[1]`` est syntaxiquement invalide - - l'expression ``ptr[2]`` est une valeur entière - - l'expression ``&ptr`` est une adresse en mémoire - - .. negative:: - - - l'expression ``*(ptr+1)==ptr[1]`` est toujours vraie - - l'expression ``ptr--`` est syntaxiquement invalide - - -Question 10. Pointeurs et tableaux ----------------------------------- - -Considérons le tableau ``tab`` déclaré comme suit : - - .. code-block:: c - - #define SIZE 30 - int tab[SIZE]; - int *ptr; - -.. question:: ptrtab - :nb_prop: 3 - :nb_pos: 1 - - Dans une architecture 32 bits, un seul des groupes d'affirmations ci-dessous est vrai. Lequel ? - - - .. positive:: - - - - l'expression ``tab[i]`` correspond à la même valeur dans le tableau que ``*(tab+i)`` lorsque ``0<=i<29`` - - l'assignation ``ptr=(tab+i)`` est valide et après cette assignation, ``*ptr`` retourne la même valeur que ``tab[i]`` lorsque ``0<=i<29`` - - - .. positive:: - - - l'expression ``tab[0]`` correspond à la même valeur dans le tableau que ``*(tab)`` - - l'assignation ``ptr=(tab+i)`` est valide et après cette assignation, ``*ptr`` retourne la même valeur que ``tab[i]`` lorsque ``0<=i<29`` - - - .. negative:: - - - l'expression ``tab[i]`` correspond à la même valeur dans le tableau que ``*(tab+i)`` lorsque ``0<=i<29`` - - l'assignation ``tab=(tab+i)`` est valide et après cette assignation, ``*tab`` retourne le ième élément du tableau lorsque ``0<=i<29`` - - .. comment:: Lorsque ``tab`` est déclaré comme étant un tableau, il est interdit de modifier sa position en mémoire. Il ne peut donc apparaître dans le membre de gauche d'une assignation. - - .. negative:: - - - l'expression ``tab[0]`` correspond à la même valeur dans le tableau que ``&(tab)`` - - l'assignation ``tab=(tab+i)`` est valide et après cette assignation, ``*tab`` retourne le ième élément du tableau lorsque ``0<=i<29`` - - .. comment:: Les deux affirmations sont fausses. - - .. negative:: - - - l'expression ``tab[i]`` correspond à la même valeur dans le tableau que ``*(tab)+i`` lorsque ``0<=i<29`` - - l'assignation ``ptr=(tab)`` est valide et après cette assignation, ``*(ptr+i)`` retourne le ième élément du tableau lorsque ``0<=i<29`` - - .. comment:: La première affirmation est fausse, ``*(tab)+i`` équivaut à ``tab[0]+i`` - - -Question 11. Pointeurs ----------------------- - -Considérons le fragment de code ci-dessous. - -.. code-block:: c - - int tab[]={ 10, 20, 30, 40 }; - int *ptr1=&tab[1]; - int *ptr2=&tab[3]; - -.. question:: cptr - :nb_prop: 3 - :nb_pos: 1 - - Dans ce code, une seule des affirmations suivantes est vraie, laquelle ? - - .. positive:: - - l'expression ``ptr2-ptr1`` vaut ``2`` - - .. positive:: - - les expressions ``*(ptr1-1)`` et ``*(ptr2-3)`` retournent toutes les deux la même valeur, ``10`` - - .. negative:: - - l'expression ``ptr2-ptr1`` vaut ``20`` - - .. comment:: ``ptr2`` et ``ptr1`` sont des pointeurs vers des entiers. L'arithmétique des pointeurs s'applique pour cette opération. Vu leur initialisation, la différence vaut ``2``. - - .. negative:: - - les expressions ``*(ptr1-1)`` et ``*(ptr2-3)`` retournent toutes les deux la même valeur, ``1`` - - .. comment:: L'expression ``*(ptr1-1)`` équivaut à ``tab[0]`` et ``*(ptr2-3)`` à ``tab[0]``. Cet élément du tableau contient la valeur ``10``. - - .. negative:: - - l'expression ``*(ptr2-ptr1)`` retourne la valeur ``20`` - - .. comment:: ``ptr2`` et ``ptr1`` sont des pointeurs vers des entiers. L'arithmétique des pointeurs s'applique pour cette opération. Vu leur initialisation, la différence vaut ``2``. L'expression ``*(2)`` correspond à une donnée à une adresse dans le bas de la mémoire qui n'est normalement pas accessible au programme. - - - -Question 12. Pointeurs et fonctions ------------------------------------ - -.. question:: ptrfct - :nb_prop: 3 - :nb_pos: 1 - - En C, il est parfois nécessaire d'échanger le contenu de deux variables. Si ``a`` et ``b`` sont des variables de type ``int``, laquelle des fonctions ci-dessous permet de réaliser cette échange entre les contenu des variables ? - - - .. positive:: - - - .. code-block:: c - - void swap(int *i, int *j) { - int k; - k=*i; - *i=*j; - *j=k; - } - //échange - swap(&a,&b); - - - .. positive:: - - .. code-block:: c - - void swap(int *i, int *j) { - int k; - k=*j; - *j=*i; - *i=k; - } - //échange - swap(&a,&b); - - .. negative:: - - - .. code-block:: c - - void swap(int i, int j) { - int k; - k=i; - i=j; - j=k; - } - //échange - swap(a,b); - - .. comment:: Cette fonction ne fait rien du tout d'utile. - - .. negative:: - - - .. code-block:: c - - void swap(int i, int j) { - int k; - k=i; - i=j; - } - //échange - swap(&a,&b); - - .. comment:: Cette fonction reçoit comme argument l'adresse de ``a`` et l'adresse de ``b`` mais ne modifie en rien le contenu de ces variables. - - .. negative:: - - .. code-block:: c - - void swap(int i, int j) { - int k; - int *i_ptr=&i; - int *j_ptr=&j; - k=i; - *(i_ptr)=j; - *(j_ptr)=k; - } - //échange - swap(a,b); - - .. comment:: Lors de son exécution, la fonction ``swap`` ci-dessus reçoit les valeurs des variables ``a`` et ``b``, mais elle n'a aucune idée de l'endroit où ces variables sont stockées en mémoire. Elle ne peut donc pas modifier leur contenu. - -Question 13. Pointeurs et structures ------------------------------------- - - -Dans un programme de manipulation de fractions, on définit la structure suivante pour représenter une fraction entière : - - .. code-block:: c - - struct fract_t { - int num; - int denum; - }; - -On veut pouvoir facilement écrire une fonction de type ``void`` qui remplace la valeur stockée dans la fraction par le résultat de l'addition de la fraction et un nombre entier passé en fragment. La spécification de cette fonction pourrait être : - - .. code-block:: c - - /* - * augmente la fraction passé en argument de l'entier n et place - * la somme calculée dans la fraction - * Exemples - * Si f vaut 1/3, alors l'application de la fonction avec f et 2 comme - * arguments a comme résultat de stocker la valeur 7/3 dans f - * Si f vaut 2/1, alors l'application de la fonction avec f et 1 comme - * arguments a comme résultat de stocker la valeur 3/1 dans f - */ - -.. question:: ptrstruct - - Laquelle des signatures ci-dessous peut-elle être utilisée pour effectuer cette opération et modifier la fraction passé en argument ? - - - .. positive:: - - - - .. code-block:: c - - void scale(struct *fract_t f, int s); - // appel à la fonction : - // scale(&f,3); - - .. negative:: - - .. code-block:: c - - void scale(struct fract_t f, int s); - // appel à la fonction : - // scale(f,3); - - .. negative:: - - .. code-block:: c - - void scale(int num, int den, int s); - // appel à la fonction : - // scale(f.num, f.denum,3); - - - diff --git a/Exercices/mcq-ex/qcm-3.rst b/Exercices/mcq-ex/qcm-3.rst deleted file mode 100644 index e820e105f44b2039075cadfab57c6c3f5ffc08ab..0000000000000000000000000000000000000000 --- a/Exercices/mcq-ex/qcm-3.rst +++ /dev/null @@ -1,598 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -Questions à choix multiples -=========================== - -:task_id: sinf1252-3 - -Cette semaine, la matière porte sur l'organisation de la mémoire et l'utilisation des fonctions `malloc(3)`_ et `free(3)`_ - - - http://sites.uclouvain.be/SystInfo/notes/Theorie/html/C/malloc.html#organisation-de-la-memoire - - - -Question 1. Portée des variables --------------------------------- - -Lorsque l'on écrit un programme C, il est préférable d'éviter d'avoir deux variables qui ont le même nom et peuvent être utilisées dans une fonction. Un étudiant a écrit le programme ci-dessous : - - .. code-block:: c - - #include <stdio.h> - int i = 1; - int main(int argc, char * argv[]) - { - int k; - printf("A:%d\n", i); - for(k=0; k<1; k++) - { - int i = 2, j = 1252; - printf("B:%d %d\n", i, j); - { - int i = 0; - printf("C:%d %d\n", i, j); - } - printf("D:%d\n", i); - } - return 0; - } - -.. question:: variables - :nb_prop: 3 - :nb_pos: 1 - - Lors de son exécution, ce programme affiche : - - .. positive:: - - - .. code-block:: console - - A:1 - B:2 1252 - C:0 1252 - D:2 - - - .. negative:: - - Le programme ne se compile pas, il est interdit de redéfinir la variable globale ``i``. - - .. comment:: Si, le programme se compile correctement. On peut redéfinir une variable dans plusieurs niveaux de portée différents, même si il vaut mieux l'éviter. - - .. negative:: - - .. code-block:: console - - A:1 - B:1 1252 - C:1 1252 - D:1 - - .. negative:: - - .. code-block:: console - - A:1 - B:2 1252 - C:2 1252 - D:2 - - .. negative:: - - .. code-block:: console - - A:1 - B:2 1252 - C:0 1252 - D:0 - -Question 2. Portée des variables --------------------------------- - -L'extrait ci-dessous provient d'un programme écrit par un étudiant. - - .. code-block:: c - - #include <stdio.h> - int i = 1252; - void f(int i) { - // code non fourni - } - void g(char* c) { - // code non fourni - } - int main(int argc, char * argv[]) - { - f(argc); - g(argv[0]); - } - -.. question:: porteevar - :nb_prop: 3 - :nb_pos: 1 - - Parmi les affirmations suivantes, un seul groupe est correct. Lequel ? - - .. positive:: - - - La fonction ``g`` peut accéder à la variable globale ``i`` et modifier sa valeur - - La fonction ``g`` ne peut lire la valeur de ``argc`` - - La fonction ``f`` ne peut modifier la valeur de la variable globale ``i`` - - .. negative:: - - - - La fonction ``g`` peut lire la variable globale ``i`` mais pas modifier sa valeur - - La fonction ``g`` ne peut lire la valeur de ``argc`` - - La fonction ``f`` peut modifier la valeur de la variable globale ``i`` - - .. comment:: La fonction ``g`` peut accéder à la variable globale ``i`` et modifier sa valeur par contre la fonction ``f`` ne peut pas le faire car elle ne peut accéder qu'à son argument nommé également ``i``. - - .. negative:: - - - La fonction ``f`` peut lire la variable globale ``i`` mais pas modifier sa valeur - - La fonction ``g`` peut lire la valeur de ``argc`` - - La fonction ``f`` peut modifier la valeur de la variable globale ``i`` - - .. comment:: Aucune de ces affirmations n'est correcte. - - - .. negative:: - - - La fonction ``f`` peut lire la variable globale ``i`` et modifier sa valeur - - La fonction ``g`` ne peut lire la valeur de ``argc`` - - La fonction ``f`` ne peut modifier la valeur de la variable globale ``i`` - - .. comment:: La fonction ``f`` n'a pas accès à la variable globale ``i``. - - - -Question 3. Organisation de la mémoire --------------------------------------- - -Considérons le fragment de programme ci-dessous. - - .. code-block:: c - - #include <stdio.h> - int i,j,k = 1252; // ligne A - int tab[1000]; // ligne B - void f(int i) { // ligne C - int j; // ligne D - // code non fourni - } - void g(char c) { - int i; // ligne E - // code non fourni - } - int main(int argc, char * argv[]) - { - int k=1; // ligne F - - f(argc); - g('a'); - } - -.. question:: orgmem - :nb_prop: 3 - :nb_pos: 1 - - Lors de l'exécution de ce programmes, les valeurs des différentes variables sont stockées en mémoire. Un seul des groupes d'affirmations ci-dessous est correct. Lequel ? - - - .. positive:: - - - - la variable ``i`` déclarée en ``ligne A`` est stockée dans la zone des variables non-initialisées - - l'argument ``i`` déclaré en ``ligne C`` est stocké sur la pile - - la variable ``j`` déclarée en ``ligne D`` est stockée sur la pile - - la variable ``k`` déclarée en ``ligne F`` est stockée sur la pile - - .. positive:: - - - la variable ``i`` déclarée en ``ligne A`` est stockée dans la zone des variables non-initialisées - - le tableau ``tab`` déclaré en ``ligne B`` est stocké dans la zone des variables non-initialisées - - l'argument ``i`` déclaré en ``ligne C`` est stocké sur la pile - - la variable ``i`` déclarée en ``ligne E`` est stockée sur la pile - - - - .. negative:: - - - - le tableau ``tab`` déclaré en ``ligne B`` est stocké dans la zone des variables initialisées - - l'argument ``i`` déclaré en ``ligne C`` est stocké sur la pile - - la variable ``j`` déclarée en ``ligne D`` est stockée sur la pile - - la variable ``i`` déclarée en ``ligne E`` est stockée sur la pile - - la variable ``k`` déclarée en ``ligne F`` est stockée dans la zone des variables non-initialisées - - .. negative:: - - - le tableau ``tab`` déclaré en ``ligne B`` est stocké dans la zone des variables non-initialisées - - l'argument ``i`` déclaré en ``ligne C`` est stocké sur le tas - - la variable ``k`` déclarée en ``ligne F`` est stockée sur la pile - - .. negative:: - - - le tableau ``tab`` déclaré en ``ligne B`` est stocké dans la zone des variables non-initialisées - - l'argument ``i`` déclaré en ``ligne C`` est stocké sur la pile - - la variable ``j`` déclarée en ``ligne D`` est stockée sur la pile - - la variable ``i`` déclarée en ``ligne E`` est stockée sur le tas - - la variable ``k`` déclarée en ``ligne F`` est stockée sur la pile - - .. negative:: - - - la variable ``i`` déclarée et initialisée en ``ligne A`` est stockée dans la zone des variables initialisées - - le tableau ``tab`` déclaré en ``ligne B`` est stocké dans la zone des variables non-initialisées - - l'argument ``i`` déclaré en ``ligne C`` est stocké sur la pile - - la variable ``k`` déclarée en ``ligne F`` est stockée sur le tas - - -Question 4. Initialisation des variables ----------------------------------------- - -En C, une règle de bonne pratique est d'initialiser toutes les variables avant leur utilisation. Utiliser une variable qui n'a pas été correctement initialisée pour être une source de problèmes. Un étudiant a écrit les déclarations ci-dessous : - - .. code-block:: c - - int k=0; - int i; - short j; - float f; - double d; - char c[10]; - char* string; - void* v; - int* ptr; - ptr=(int*) malloc(5*sizeof(int)); - -.. question:: varinit - :nb_prop: 3 - :nb_pos: 1 - - Après exécution de ces lignes, un seul des groupes d'affirmations ci-dessous est correct. Lequel ? - - .. positive:: - - - - la variable ``i`` est initialisée à la valeur ``0`` - - le pointeur ``string`` est initialisé à la valeur ``NULL`` - - ``c[2]`` contient le caractère ``'\0'`` - - Après exécution de ``malloc``, le contenu de l'adresse ``ptr+1`` est indéterminé - - .. comment:: Pour des raisons d'efficacité, `malloc(3)`_ n'initialise pas à zéro les zones mémoires allouées, contrairement à `calloc(3)`_ - - .. positive:: - - - - la variable ``j`` est initialisée à la valeur ``0`` - - le pointeur ``v`` est initialisé à la valeur ``NULL`` - - ``c[4]`` contient le caractère ``'\0'`` - - Après exécution de ``malloc``, le contenu de l'adresse ``ptr+4`` est indéterminé - - .. comment:: Pour des raisons d'efficacité, `malloc(3)`_ n'initialise pas à zéro les zones mémoires allouées, contrairement à `calloc(3)`_ - - .. negative:: - - - - la variable ``f`` est initialisée à la valeur ``0.0`` - - le pointeur ``string`` n'a aucune valeur et n'est pas utilisable - - ``c[2]`` contient le caractère espace - - Après exécution de ``malloc``, l'adresse ``ptr+1`` contient le caractère ``'\0'`` - - .. comment:: `malloc(3)`_ n'initialise pas la zone mémoire allouée. ``string`` contient ``NULL`` et ``c[2]`` le caractère ``'\0'`` - - .. negative:: - - - - la variable ``f`` est initialisée à la valeur ``0.0`` - - le pointeur ``v`` n'a aucune valeur et n'est pas utilisable - - ``c[2]`` contient le caractère espace - - Après exécution de ``malloc``, l'adresse ``ptr`` contient le caractère ``'\0'`` - - .. negative:: - - - - la variable ``f`` est initialisée à la valeur ``0.0`` - - le pointeur ``string`` est initialisé à ``NULL`` - - ``c[10]`` contient le caractère espace - - Après exécution de ``malloc``, l'adresse ``ptr+3`` contient le caractère ``'\0'`` - - .. comment:: ``c[10]`` est hors du tableau ``c``. `malloc(3)`_ n'initialise pas la zone mémoire allouée. - - .. negative:: - - - - la variable ``f`` est initialisée à la valeur ``0.0`` - - le pointeur ``v`` est initialisé à ``NULL`` - - ``c[6]`` contient le caractère ``'\0'`` - - Après exécution de ``malloc``, l'adresse ``ptr+5`` contient le caractère ``'\0'`` - - .. comment:: `malloc(3)`_ n'initialise pas la zone mémoire allouée. De plus, ``ptr+5`` se trouve en dehors de la zone mémoire allouée par `malloc(3)`_ - - -Question 5. `malloc(3)`_ et compagnie -------------------------------------- - -Cette question porte sur les fonctions `malloc(3)`_ et `free(3)`_ qui sont importantes pour la manipulation de la mémoire sur le tas. - -.. question:: malloc - :nb_prop: 3 - :nb_pos: 1 - - Parmi les groupes d'affirmation suivants, un seul est correct. Lequel ? - - .. positive:: - - - - la fonction `malloc(3)`_ retourne un pointeur de type ``void *`` - - la fonction `free(3)`_ prend comme argument un pointeur de type ``void *`` qui a été précédemment alloué par la fonction `malloc(3)`_ - - si l'appel à `calloc(3)`_ a retourné un pointeur différent de ``NULL``, alors la zone mémoire demandée a été allouée et est initialisée à zéro - - une implémentation possible (non efficace) de `realloc(3)`_ est - - .. code-block:: c - - void *realloc(void *ptr, size_t len) - { - void *r; - r = malloc(len); - if(r!=NULL) - { - memcpy(r, ptr, len); - free(ptr); - } - return r; - } - - - - .. negative:: - - - - la fonction `malloc(3)`_ retourne un pointeur de type ``void *`` - - la fonction `free(3)`_ prend comme argument n'importe quel type de pointeur - - si l'appel à `malloc(3)`_ a retourné un pointeur différent de ``NULL``, alors la zone mémoire demandée a été allouée mais n'est pas initialisée à zéro - - une implémentation possible (non efficace) de `realloc(3)`_ est - - .. code-block:: c - - void *realloc(void *ptr, size_t len) - { - void *r; - r = malloc(len); - memcpy(r, ptr, len); - return r; - } - - - .. negative:: - - - la fonction `calloc(3)`_ retourne un pointeur de type ``void *`` - - la fonction `free(3)`_ prend comme argument un pointeur de type ``void *`` qui a été précédemment alloué par la fonction `malloc(3)`_ - - si l'appel à `malloc(3)`_ a retourné un pointeur différent de ``NULL``, alors la zone mémoire demandée a été allouée et est initialisée - - une implémentation possible (non efficace) de `realloc(3)`_ est - - .. code-block:: c - - void *realloc(void *ptr, size_t len) - { - return malloc(len); - } - - - .. negative:: - - - la fonction `calloc(3)`_ retourne un pointeur de type ``void *`` - - la fonction `free(3)`_ prend comme argument un pointeur de type ``void *`` qui a été précédemment alloué par la fonction `malloc(3)`_ - - si l'appel à `malloc(3)`_ a retourné un pointeur différent de ``NULL``, alors la zone mémoire demandée a été allouée et est initialisée - - une implémentation possible (non efficace) de `realloc(3)`_ est - - .. code-block:: c - - void *realloc(void *ptr, size_t len) - { - void *r; - r = malloc(len); - if(r) - { - return r; - } - else - { - return NULL; - } - } - - - -Question 6. Stack ------------------ - -.. question:: stack - :nb_prop: 3 - :nb_pos: 1 - - Considérons le programme `stack.c` présenté dans le syllabus. Cette implémentation d'une pile permet d'ajouter et de retirer un élément de la pile. Laquelle des implémentations ci-dessous est-elle une implémentation correcte d'une fonction ``size`` permettant de calculer le nombre d'éléments stockés dans la pile ? - - .. positive:: - - - .. code-block:: c - - int size(struct node_t* stack) - { - struct node_t *curr = stack; - int count = 0; - while (curr!=NULL) { - count ++; - curr = stack->next; - } - return count; - } - - .. positive:: - - .. code-block:: c - - int size(struct node_t* stack) - { - int count = 0; - while (stack!=NULL) { - count ++; - stack = stack->next; - } - return count; - } - - - .. negative:: - - - .. code-block:: c - - int size(struct node_t* stack) - { - int count = 0; - while (stack!=NULL) { - count ++; - stack++; - } - return count; - } - - .. negative:: - - .. code-block:: c - - int size(struct node_t* stack) - { - return sizeof(stack); - } - - .. negative:: - - .. code-block:: c - - int size(struct node_t* stack) - { - struct node_t *curr = stack; - int count = 0; - while (curr) { - count ++; - curr++; - } - return count; - } - - .. negative:: - - .. code-block:: c - - int size(struct node_t stack) - { - struct node_t curr = stack; - int count = 0; - while (curr) { - count ++; - curr = stack->next; - } - return count; - } - - -Question 7. `strdup(3)`_ ------------------------- - -.. question:: strdup - :nb_prop: 3 - :nb_pos: 1 - - La librairie standard contient la fonction `strdup(3)`_. Laquelle des fonctions ci-dessous est-elle une implémentation de correcte `strdup(3)`_ ? - - .. positive:: - - .. code-block:: c - - char *strdup(const char *s) - { - char *new = (char *) malloc ((strlen(s)+1) * sizeof(char)); - if (new == NULL) - return NULL; - return memcpy(new, s, (strlen(s)+1) * sizeof(char)); - } - - .. positive:: - - .. code-block:: c - - char *strdup(const char *s) - { - char *new = (char *) malloc ((strlen(s)+1) * sizeof(char)); - if (!new) - return NULL; - return memcpy(new, s, (strlen(s)+1) * sizeof(char)); - } - - - .. negative:: - - - .. code-block:: c - - char *strdup(const char s) - { - void *new = malloc (strlen(s)); - if (new == NULL) - return NULL; - return memcpy(new, s, strlen(s)); - } - - .. negative:: - - .. code-block:: c - - char *strdup(const char *s) - { - char new [strlen(s)+1]; - return memcpy(new, s, (strlen(s)+1) * sizeof(char)); - } - - .. negative:: - - .. code-block:: c - - char *strdup(const char * s) - { - void *new = malloc (strlen(s+1)); - return memcpy(new, s, strlen(s+1)); - } - - .. negative:: - - .. code-block:: c - - char *strdup(const char *s) - { - char *new = (char *) calloc (strlen(s) * sizeof(char)); - if (new == NULL) - return NULL; - return memcpy(new, s, (strlen(s) * sizeof(char))); - } - - .. negative:: - - .. code-block:: c - - char *strdup(const char *s) - { - char *new = (char *) malloc (strlen(s) * sizeof(char)); - return memcpy(new, s, (strlen(s) * sizeof(char)); - } - - - - diff --git a/Exercices/mcq-ex/qcm-4-asm.rst b/Exercices/mcq-ex/qcm-4-asm.rst deleted file mode 100644 index e978d0865fd7a975a362383565c6b384c28f0bb3..0000000000000000000000000000000000000000 --- a/Exercices/mcq-ex/qcm-4-asm.rst +++ /dev/null @@ -1,1666 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -Questions à choix multiples -=========================== - -:task_id: sinf1252-4 - -Cette semaine, la matière porte sur l'organisation de la mémoire et sur le langage assembleur IA32. La matière couverte se trouve dans les sections suivantes du syllabus : - - - `Organisation des ordinateurs <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/Assembleur/memory.html>`_ - - `Etude de cas : IA32 <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/Assembleur/memory.html#etude-de-cas-architecture-ia32>`_ - -Question 1. Instruction ``mov`` -------------------------------- - -Les instructions de la famille ``mov`` permettent de déplacer des données entre registres ou d'initialiser des registres. Considérons le fragment de code C suivant (dans lequel ``g``, ``g2`` et ``s`` sont des variables globales de type ``int``) : - -.. code-block:: c - - g=1234; - g2=5678; - s=g; - g=g2; - g2=s; - -.. question:: mov - :nb_prop: 3 - :nb_pos: 1 - - Parmi les traductions en assembleur ci-dessus, une seule est correcte. Laquelle ? - - - .. positive:: - - - .. code-block:: nasm - - movl $1234, g - movl $5678, g2 - movl g, %ecx - movl %ecx, s - movl g2, %ecx - movl %ecx, g - movl s, %ecx - movl %ecx, g2 - - .. positive:: - - .. code-block:: nasm - - movl $1234, g - movl $5678, g2 - movl g, %eax - movl %eax, s - movl g2, %eax - movl %eax, g - movl s, %eax - movl %eax, g2 - - - .. negative:: - - - .. code-block:: nasm - - movl g, $1234 - movl g2, $5678 - movl %eax, g - movl s, %eax - movl %eax, g2 - movl g, %eax - movl s, %eax - movl g2, %eax - - .. comment:: L'instruction ``mov`` prend comme premier argument la source et comme second la destination. - - .. negative:: - - .. code-block:: nasm - - movl $1234, g - movl $5678, g2 - movl g2, %eax - movl %edx, s - movl g, %eax - movl %edx, g2 - movl s, %eax - movl %eax, g2 - - .. comment:: Ce code utilise les registres ``%edx`` et ``%eax``. ``%edx`` est utilisé sans être initialisé. - - .. negative:: - - .. code-block:: nasm - - movw $1234, g - movw $5678, g2 - movb g2, %eax - movb %eax, s - movb g, %eax - movb %eax, g2 - movb s, %eax - movb %eax, g2 - - .. comment:: L'instruction ``movb`` déplace un ``byte`` et non le contenu complet d'un registre de 32 bits. - - .. negative:: - - .. code-block:: nasm - - movw $1234, g - movw $5678, g2 - movb g2, %edx - movb %edx, s - movb g, %edx - movb %edx, g2 - movb s, %edx - movb %edx, g2 - - - .. comment:: - - L'instruction ``movb`` déplace un ``byte`` et non le contenu complet d'un registre de 32 bits. - -Question 2. Opérations arithmétiques ------------------------------------- - -Considérons le fragment de programme C ci-dessous : - - .. code-block:: c - - a=a+b; - b=b+b; - c=b-a; - -.. question:: add - :nb_prop: 3 - :nb_pos: 1 - - Une seule des séquences d'instructions assembleur ci-dessous est une traduction correcte de cette séquence d'instructions. Laquelle ? - - .. positive:: - - - .. code-block:: nasm - - movl a, %eax - addl b, %eax - movl %eax, a - movl b, %eax - addl b, %eax - movl %eax, b - movl b, %eax - subl a, %eax - movl %eax, c - - .. positive:: - - .. code-block:: nasm - - movl b, %eax - addl a, %eax - movl %eax, a - movl b, %eax - addl b, %eax - movl %eax, b - movl b, %eax - subl a, %eax - movl %eax, c - - - .. negative:: - - .. code-block:: nasm - - movl b, %eax - addl a, %eax - movl %eax, a - movl b, %eax - movl %eax, %ecx - addl $1, %ecx - movl %ecx, b - movl %eax, b - movl a, %eax - subl b, %eax - movl %eax, c - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - a=b+a; - b=b++; - c=a-b; - - .. negative:: - - .. code-block:: nasm - - movl b, %eax - addl a, %eax - movl %eax, c - movl b, %eax - movl %eax, %ecx - addl $1, %ecx - movl %ecx, b - movl %eax, b - movl a, %eax - subl b, %eax - movl %eax, a - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - c=b+a; - b=b++; - a=a-b; - - .. negative:: - - .. code-block:: nasm - - movl b, %eax - addl a, %eax - movl %eax, b - movl b, %eax - movl %eax, %ecx - addl $1, %ecx - movl %ecx, b - movl %eax, a - movl b, %eax - subl a, %eax - movl %eax, c - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - b=b+a; - a=b++; - c=b-a; - -Question 3. Instructions conditionnelles ----------------------------------------- - -Les instructions conditionnelles sont fréquemment utilisées en langage C et en assembleur. Considérons le fragment de programme C ci-dessous (``a`` et ``b`` sont des variables globales de type ``int``): - - .. code-block:: c - - if(b<4) - a++; - -.. question:: conditionnelles - :nb_prop: 3 - :nb_pos: 1 - - Une seule des séquences d'instructions assembleur ci-dessous est une traduction correcte de cette séquence d'instructions. Laquelle ? - - .. positive:: - - - .. code-block:: nasm - - begin: - cmpl $4, b - jge end - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - .. positive:: - - .. code-block:: nasm - - begin: - cmpl $4, b - jl next - jmp end - next: - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - if((b>=4)) - {} - else - a++; - - - .. negative:: - - - - .. code-block:: nasm - - begin: - cmpl $4, b - jg end - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - if(b<=4) - a++; - - - .. negative:: - - .. code-block:: nasm - - begin: - cmpl $4, b - je end - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - if(b!=4) - a++; - - .. negative:: - - .. code-block:: nasm - - begin: - cmpl $4, b - jl end - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - if(!(b<4)) - a++; - - .. negative:: - - .. code-block:: nasm - - begin: - cmpl $4, b - jl end - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - if(b>=4) - a++; - - -Question 4. Instructions conditionnelles ----------------------------------------- - -Les instructions conditionnelles sont fréquemment utilisées en langage C et en assembleur. Considérons le fragment de programme C ci-dessous : - - .. code-block:: c - - if(a<=b) - c++; - -.. question:: conditionnelles2 - :nb_prop: 3 - :nb_pos: 1 - - Une seule des séquences d'instructions en assembleur ci-dessous correspond à ce fragment de code C. Laquelle ? - - - .. positive:: - - - .. code-block:: nasm - - if: - movl a, %eax - cmpl b, %eax - jg next - movl c, %eax - addl $1, %eax - movl %eax, c - next: - - .. positive:: - - .. code-block:: nasm - - if: - movl b, %eax - cmpl a, %eax - jl next - movl c, %eax - addl $1, %eax - movl %eax, c - next: - - .. comment:: - - Ceci est en fait l'implémentation de : - - .. code-block:: c - - if(b>=a) - c++; - - - .. negative:: - - - .. code-block:: nasm - - if: - movl a, %eax - cmpl b, %eax - jne next - movl c, %eax - addl $1, %eax - movl %eax, c - next: - - .. comment:: - - Ceci est l'implémentation de : - - .. code-block:: c - - if(a==b) - c++; - - .. negative:: - - .. code-block:: nasm - - if: - movl a, %eax - cmpl b, %eax - jle next - movl c, %eax - addl $1, %eax - movl %eax, c - next: - - .. comment:: - - Ceci est l'implémentation de : - - .. code-block:: c - - if(a>b) - c++; - - .. negative:: - - .. code-block:: none - - if: - movl a, %eax - cmpl b, %eax - jge next - movl c, %eax - addl $1, %eax - movl %eax, c - next: - - - .. comment:: - - Ceci est l'implémentation de : - - .. code-block:: c - - if(a<b) - c++; - - .. negative:: - - .. code-block:: nasm - - if: - movl a, %eax - cmpl b, %eax - je next - movl c, %eax - addl $1, %eax - movl %eax, c - next: - - .. comment:: - - Ceci est l'implémentation de : - - .. code-block:: c - - if(a!=b) - c++; - - - -Question 5. Instructions conditionnelles ----------------------------------------- - -L'instruction conditionnelle ``if() ... else`` se retrouve dans de nombreux programmes en langage C. Considérons l'instruction ``if() ... else`` simple ci-dessous dans laquelle ``a`` et ``b`` sont des variables globales de type ``int`` : - -.. code-block:: c - - if(a>=b) - a++; - else - b++; - -.. question:: conditionnelles3 - :nb_prop: 3 - :nb_pos: 1 - - Parmi les séquences d'assembleur ci-dessous, une seule est une traduction correcte de cette instruction conditionnelle. Laquelle ? - - .. positive:: - - - .. code-block:: nasm - - movl a, %eax - cmpl b, %eax - jl label - movl a, %eax - addl $1, %eax - movl %eax, a - jmp end - label: - movl b, %eax - addl $1, %eax - movl %eax, b - end: - - .. positive:: - - .. code-block:: nasm - - movl b, %eax - cmpl a, %eax - jg label - movl a, %eax - addl $1, %eax - movl %eax, a - jmp end - label: - movl b, %eax - addl $1, %eax - movl %eax, b - end: - - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - if(b<=a) - a++; - else - b++; - - - .. negative:: - - .. code-block:: nasm - - - movl a, %eax - cmpl b, %eax - jl label - movl b, %eax - addl $1, %eax - movl %eax, b - jmp end - label: - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - if(a>=b) - b++; - else - a++; - - .. negative:: - - .. code-block:: nasm - - - movl b, %eax - cmpl a, %eax - jge label - movl a, %eax - addl $1, %eax - movl %eax, a - jmp end - label: - movl b, %eax - addl $1, %eax - movl %eax, b - end: - - - - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - if(b<a) - a++; - else - b++; - - .. negative:: - - .. code-block:: nasm - - movl b, %eax - cmpl a, %eax - jle label - movl b, %eax - addl $1, %eax - movl %eax, b - jmp .LBB4_3 - label: - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - if(b>a) - b++; - else - a++; - - .. negative:: - - .. code-block:: nasm - - movl a, %eax - cmpl b, %eax - jl label - movl a, %eax - addl $1, %eax - movl %eax, a - label: - movl b, %eax - addl $1, %eax - movl %eax, b - end: - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - if(a>=b) { - a++; - } - b++; - - - -Question 6. Boucles ``while`` ------------------------------ - -Les boucles ``while`` sont fréquemment utilisées dans des programmes C. Considérons la boucle suivante qui utilise des variables globales (toutes de type ``int``): - - .. code-block:: c - - while(a!=c) - { - a++; - b=b+c; - } - -.. question:: while - :nb_prop: 3 - :nb_pos: 1 - - Parmi les séquences d'assembleur ci-dessous, une seule est une traduction correcte de cette boucle ``while``. Laquelle ? - - .. positive:: - - - .. code-block:: nasm - - begin: - movl a, %eax - cmpl c, %eax - je end - movl a, %eax - addl $1, %eax - movl %eax, a - movl b, %eax - addl c, %eax - movl %eax, b - jmp begin - end: - - .. positive:: - - .. code-block:: nasm - - begin: - movl c, %eax - cmpl a, %eax - je end - movl a, %eax - addl $1, %eax - movl %eax, a - movl b, %eax - addl c, %eax - movl %eax, b - jmp begin - end: - - - .. negative:: - - - .. code-block:: nasm - - begin: - movl c, %eax - cmpl a, %eax - jle end - movl a, %eax - addl $1, %eax - movl %eax, a - movl b, %eax - addl c, %eax - movl %eax, b - jmp begin - end: - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - while(c>a) - { - a++; - b=b+c; - } - - .. negative:: - - .. code-block:: nasm - - begin: - movl a, %eax - addl $1, %eax - movl %eax, a - movl b, %eax - addl c, %eax - movl %eax, b - movl c, %eax - cmpl a, %eax - jne begin - end: - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - do - { - a++; - b=b+c; - } - while(c!=a); - - .. negative:: - - .. code-block:: nasm - - begin: - movl c, %eax - cmpl a, %eax - jne end - movl a, %eax - addl $1, %eax - movl %eax, a - movl b, %eax - addl c, %eax - movl %eax, b - jmp begin - end: - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - while(c==a) - { - a++; - b=b+c; - } - - -Question 7. Boucles ``for`` ---------------------------- - -Rares sont les programmes C qui ne contiennent pas de boucles ``for``. Considérons la boucle ci-dessous qui utilise uniquement des variables globales (de type ``int``) : - -.. code-block:: c - - for(a=0;a<c;a++) { - b=b-c; - } - -.. question:: for - :nb_prop: 3 - :nb_pos: 1 - - Parmi les séquences d'instructions en assembleur ci-dessous, une seule traduit correctement la boucle ``for`` ci-dessus. Laquelle ? - - - .. positive:: - - - .. code-block:: nasm - - begin: - movl $0, a - loop: - movl a, %eax - cmpl c, %eax - jge end - movl b, %eax - subl c, %eax - movl %eax, b - movl a, %eax - addl $1, %eax - movl %eax, a - jmp loop - end: - - .. positive:: - - .. code-block:: nasm - - begin: - movl $0, a - loop: - movl c, %eax - cmpl a, %eax - jle end - movl b, %eax - subl c, %eax - movl %eax, b - movl a, %eax - addl $1, %eax - movl %eax, a - jmp loop - end: - - .. negative:: - - - .. code-block:: nasm - - begin: - movl a, %eax - addl $1, %eax - movl %eax, a - loop: - movl c, %eax - cmpl a, %eax - jle end - movl b, %eax - subl c, %eax - movl %eax, b - movl $0, a - jmp loop - end: - - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - for(a=a+1;c>a;a=0) { - b=b-c; - } - - .. negative:: - - .. code-block:: nasm - - begin: - movl $0, a - loop: - movl a, %eax - cmpl c, %eax - jg end - movl b, %eax - subl c, %eax - movl %eax, b - movl a, %eax - addl $1, %eax - movl %eax, a - jmp loop - end: - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - for(a=0;a<=c;a++) { - b=b-c; - } - - .. negative:: - - .. code-block:: nasm - - begin: - movl $0, a - movl a, %eax - cmpl c, %eax - jge end - movl b, %eax - subl c, %eax - movl %eax, b - movl a, %eax - addl $1, %eax - movl %eax, a - end: - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - a=0; - if(a<c) { - b=b-c; - a++; - } - - .. negative:: - - .. code-block:: nasm - - begin: - loop: - movl a, %eax - cmpl c, %eax - jge end - movl $0, a - movl b, %eax - subl c, %eax - movl %eax, b - movl a, %eax - addl $1, %eax - movl %eax, a - jmp loop - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - for(;a<c;a++) { - a=0; - b=b-c; - } - - -Question 8. Fonctions ---------------------- - -Un programme C contient en général de nombreuses fonctions. Considérons une fonction simple qui effectue un calcul en utilisant un argument et une variable globale (``a``) : - -.. code-block:: c - - - int f(int i) - { - return i+a; - } - - -.. question:: fonction - :nb_prop: 3 - :nb_pos: 1 - - Parmi les séquences d'instructions en assembleur ci-dessous, une seule traduit correctement la fonction ci-dessus. Laquelle ? - - .. positive:: - - .. code-block:: nasm - - pushl %eax - movl 8(%esp), %eax - movl %eax, (%esp) - movl (%esp), %eax - addl a, %eax - popl %edx - ret - - - .. positive:: - - .. code-block:: nasm - - subl $8, %esp - movl 12(%esp), %eax - movl %eax, 4(%esp) - movl a, %eax - movl %eax, (%esp) - movl (%esp), %eax - addl 4(%esp), %eax - addl $8, %esp - ret - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - int f(int i) - { - int j=a; - return j+i; - } - - - .. negative:: - - - .. code-block:: nasm - - subl $8, %esp - movl 12(%esp), %eax - movl %eax, 4(%esp) - movl 4(%esp), %eax - addl a, %eax - movl %eax, (%esp) - addl $8, %esp - ret - - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - void f3(int i) // incorrect - { - int j=i+a; - } - - .. negative:: - - .. code-block:: nasm - - pushl %eax - movl (%esp), %eax - addl a, %eax - popl %edx - ret - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - - int f() - { - int i; - return i+a; - } - - .. negative:: - - .. code-block:: nasm - - pushl %eax - movb 8(%esp), %al - movb %al, 3(%esp) - movsbl 3(%esp), %ecx - addl a, %ecx - movl %ecx, %eax - popl %edx - ret - - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - int f(char c) - { - return c+a; - } - - .. negative:: - - .. code-block:: nasm - - pushl %eax - movb 8(%esp), %al - movb %al, 3(%esp) - movsbl 3(%esp), %ecx - addl a, %ecx - movb %cl, %al - movsbl %al, %eax - popl %edx - ret - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - char f(char c) - { - return c+a; - } - - - - - -Question 9. Fonction ``max`` ----------------------------- - -Considérons la fonction C qui calcule le maximum entre deux entiers : - -.. code-block:: c - - int max(int i, int j) { - if (i>j) - return i; - else - return j; - } - -.. question:: max - :nb_prop: 3 - :nb_pos: 1 - - Parmi les groupes d'instructions ci-dessous, un seul est la traduction de cette fonction. Lequel ? - - .. positive:: - - .. code-block:: nasm - - - max: - subl $12, %esp - movl 20(%esp), %eax - movl 16(%esp), %ecx - movl %ecx, 4(%esp) - movl %eax, (%esp) - movl 4(%esp), %eax - cmpl (%esp), %eax - jle next - movl 4(%esp), %eax - movl %eax, 8(%esp) - jmp label - next: - movl (%esp), %eax - movl %eax, 8(%esp) - label: - movl 8(%esp), %eax - addl $12, %esp - ret - - .. positive:: - - .. code-block:: nasm - - max2: - subl $12, %esp - movl 20(%esp), %eax - movl 16(%esp), %ecx - movl %ecx, 4(%esp) - movl %eax, (%esp) - movl 4(%esp), %eax - cmpl (%esp), %eax - jge label1 - movl (%esp), %eax - movl %eax, 8(%esp) - jmp label2 - label1: - movl 4(%esp), %eax - movl %eax, 8(%esp) - label2: - movl 8(%esp), %eax - addl $12, %esp - ret - - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - int max(int i, int j) { - if (i<j) - return j; - else - return i; - } - - - .. negative:: - - - .. code-block:: nasm - - max: - subl $8, %esp - movl 12(%esp), %eax - movl %eax, (%esp) - movl (%esp), %eax - cmpl (%esp), %eax - jge label1 - movl (%esp), %eax - movl %eax, 4(%esp) - jmp label2 - label1: - movl (%esp), %eax - movl %eax, 4(%esp) - label2: - movl 4(%esp), %eax - addl $8, %esp - ret - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - - int max(int i) { - if (i<i) - return i; - else - return i; - } - - .. negative:: - - .. code-block:: nasm - - max: - subl $12, %esp - movl 20(%esp), %eax - movl 16(%esp), %ecx - movl %ecx, 4(%esp) - movl %eax, (%esp) - movl 4(%esp), %eax - cmpl (%esp), %eax - jge label1 - movl (%esp), %eax - movl %eax, 8(%esp) - jmp label2 - label1: - movl (%esp), %eax - movl %eax, 8(%esp) - label2: - movl 8(%esp), %eax - addl $12, %esp - ret - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - int max4(int i, int j) { //incorrect - if (i<j) - return j; - else - return j; - } - - .. negative:: - - .. code-block:: nasm - - max: - subl $12, %esp - movl 20(%esp), %eax - movl 16(%esp), %ecx - movl %ecx, 4(%esp) - movl %eax, (%esp) - movl 4(%esp), %eax - cmpl (%esp), %eax - jge label1 - movl 4(%esp), %eax - movl %eax, 8(%esp) - jmp label2 - label1: - movl (%esp), %eax - movl %eax, 8(%esp) - label2: - movl 8(%esp), %eax - addl $12, %esp - ret - - - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - int max5(int i, int j) { - if (i<j) - return i; - else - return j; - } - -Question 10. Fonctions récursives ---------------------------------- - -Les fonctions récursives sont parfois utilisées en langage C. Lors de leur exécution, la pile permet de stocker temporairement les valeurs des variables et les adresses de retour. Considérons la fonction récursive suivante (où ``a`` est une variable globale) : - -.. code-block:: c - - int f(int i) - { - return a+f(i-1); - } - -.. question:: recursive - :nb_prop: 3 - :nb_pos: 1 - - Parmi les séquences d'instructions assembleur ci-dessous, une seule est une traduction correctement de cette fonction. Laquelle ? - - .. positive:: - - - .. code-block:: nasm - - - f: - pushl %ebp - movl %esp, %ebp - subl $12, %esp - movl 8(%ebp), %eax - movl %eax, -4(%ebp) - movl a, %eax - movl -4(%ebp), %ecx - subl $1, %ecx - movl %ecx, (%esp) - movl %eax, -8(%ebp) - calll f - movl -8(%ebp), %ecx - addl %eax, %ecx - movl %ecx, %eax - addl $12, %esp - popl %ebp - ret - - .. positive:: - - .. code-block:: nasm - - f: - pushl %ebp - movl %esp, %ebp - subl $12, %esp - movl 8(%ebp), %eax - movl %eax, -4(%ebp) - movl -4(%ebp), %eax - subl $1, %eax - movl %eax, (%esp) - calll f - movl %eax, -8(%ebp) - movl -8(%ebp), %eax - addl a, %eax - addl $12, %esp - popl %ebp - ret - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - int f(int i) - { - int j=f(i-1); - return j+a; - } - - - .. negative:: - - - .. code-block:: nasm - - f: - pushl %ebp - movl %esp, %ebp - subl $12, %esp - movl 8(%ebp), %eax - movl %eax, -4(%ebp) - movl a, %eax - movl -4(%ebp), %ecx - movl %ecx, (%esp) - movl %eax, -8(%ebp) - calll f - movl -8(%ebp), %ecx - addl %eax, %ecx - movl %ecx, %eax - addl $12, %esp - popl %ebp - ret - - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - int f(int i) - { - return a+f(i); - } - - .. negative:: - - .. code-block:: nasm - - f: - pushl %ebp - movl %esp, %ebp - subl $8, %esp - movl 8(%ebp), %eax - movl %eax, -4(%ebp) - movl -4(%ebp), %eax - addl a, %eax - movl %eax, (%esp) - calll f - addl $8, %esp - popl %ebp - ret - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - int f(int i) // incorrect - { - return f(i+a); - } - - .. negative:: - - .. code-block:: nasm - - pushl %ebp - movl %esp, %ebp - subl $12, %esp - movl 8(%ebp), %eax - movl %eax, -4(%ebp) - movl -4(%ebp), %eax - subl $1, %eax - movl %eax, (%esp) - calll f - movl %eax, -8(%ebp) - movl a, %eax - addl $12, %esp - popl %ebp - ret - - .. comment:: - - Ceci est la traduction de : - - .. code-block:: c - - int f(int i) - { - int j=f(i-1); - return a; - } - - -Question 10. Pointeurs en assembleur ------------------------------------- - -Pour comprendre le fonctionnement des pointeurs en C, il est parfois utile de se ramener à la traduction en assembleur de fragments de code C. Considérons les lignes suivantes : - - .. code-block:: c - - int a=1252; - int * ptr; - - int main(int argc, const char *argv[]) { - ptr=&a; - } - -.. question:: ptrasm - :nb_prop: 3 - :nb_pos: 1 - - Parmi les séquences d'instructions en assembleur ci-dessous, une seule est la traduction de l'assignation de l'adresse de ``a`` au pointeur ``ptr``. Laquelle - - .. positive:: - - - .. code-block:: nasm - - leal a, %eax - movl %eax, ptr - - .. negative:: - - - .. code-block:: nasm - - movl a, %eax - movl ptr, %ecx - movl %eax, (%ecx) - - .. comment:: Cette séquence d'instructions est la traduction de ``*ptr=a``. - - .. negative:: - - .. code-block:: nasm - - movl a, %eax - movl %eax, ptr - - .. comment:: Cette séquence d'instructions est la traduction de ``ptr=(int )a;``. - - .. negative:: - - - .. code-block:: nasm - - pushl %eax - leal (%esp), %eax - movl a, %ecx - movl %ecx, (%esp) - movl %eax, ptr - popl %eax - - .. comment:: - - Cette séquence d'instructions est la traduction de : - - .. code-block:: c - - int b=a; - ptr=&(b); - - .. negative:: - - - .. code-block:: nasm - - leal a, %eax - addl $4, %eax - movl %eax, ptr - - .. comment:: - - Cette séquence d'instructions est la traduction de ``ptr=&a+1;``. - - diff --git a/Exercices/mcq-ex/qcm-4.rst b/Exercices/mcq-ex/qcm-4.rst deleted file mode 100644 index d55932bffad1a498c61ac3f83cc93ad106f45c75..0000000000000000000000000000000000000000 --- a/Exercices/mcq-ex/qcm-4.rst +++ /dev/null @@ -1,315 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -Questions à choix multiples -=========================== - -:task_id: sinf1252-4 - - -Question 1. Pointeurs et tableaux ---------------------------------- - -Les pointeurs peuvent être utilisés pour accéder à des tableaux. Considérons un fragment de code C utilisant un tableau d'entiers à une dimension : - -.. code-block:: c - - int a[]={2,4,3,4,8}; - int * ptr; - - printf("%d %d %d %d\n",a[0],a[1],a[2],a[a[3]]); - - -Lors de son exécution, ce programme affiche ``2 4 3 8`` sur sa sortie standard. - -.. question:: ptr-tableaux - :nb_prop: 3 - :nb_pos: 1 - - Après exécution de ``ptr=&(a[0]);``, une seule des instructions ci-dessous affiche la même séquence de chiffres. Laquelle ? - - .. positive:: - - - .. code-block:: c - - printf("%d %d %d %d\n",*ptr,*(ptr+1),*(ptr+2),*(ptr+*(ptr+3))); - - .. negative:: - - .. code-block:: c - - printf("%d %d %d %d\n",*ptr,*ptr+1,*ptr+2,*(ptr+*(ptr+3))); - - .. comment:: - - Cette ligne affiche ``2 3 4 8``. Sur base des règles de précédence entre les opérations, l'expression ``*ptr+1`` équivaut en fait à ``(*ptr)+1``. En cas de doute, utilisez les parenthèses. - - - .. negative:: - - .. code-block:: c - - printf("%d %d %d %d\n",*ptr,*(ptr++),(*ptr++),*(ptr+*(ptr++))); - - .. comment:: - - Cette ligne affiche ``2 2 4 ???``. La dernière expression ``*(ptr+*(ptr++))`` accède une zone de mémoire en dehors du tableau et dont la valeur est inconnue (notez que la valeur de ``ptr++`` est la valeur de ptr AVANT l'incrémentation, contrairement à ``++ptr``). - - .. negative:: - - .. code-block:: c - - printf("%d %d %d %d\n",*ptr,*(ptr+0),*(ptr+1),*ptr+*(ptr+2)); - - .. comment:: - - Cette ligne affiche ``2 2 4 5``. ``*(ptr+0)`` est ``a[0]`` et non ``a[1]``. - - .. negative:: - - .. code-block:: c - - printf("%d %d %d %d\n",*ptr,*ptr+1,(*ptr+1),*(ptr+(ptr+3))); - - .. comment:: - - Cette ligne est syntaxiquement invalide. L'expression ``ptr+(ptr+3)`` est invalide. On ne peut pas additionner deux pointeurs. - - - -Question 2. Traitement de ``argv`` ----------------------------------- - -Un programme C doit souvent pouvoir manipuler les arguments qui lui sont passés. Les variables ``argc`` et ``argv`` qui sont passées à la fonction ``main`` permettent d'accéder à ces arguments. Le fragment de programme ci-dessous affiche sur la sortie standard ses différents arguments. - -.. code-block:: c - - while(i<argc) { - printf("%d %p %s\n",i,&(argv[i]),argv[i]); - i++; - } - -Un exemple d'exécution de ce fragment de programme est présenté ci-dessous : - -.. code-block:: console - - #./a.out a b cd - 0 0x7fff5fbff788 ./a.out - 1 0x7fff5fbff790 a - 2 0x7fff5fbff798 b - 3 0x7fff5fbff7a0 cd - -.. question:: argv - :nb_prop: 3 - :nb_pos: 1 - - A côté de la notation ``argv[i]``, il est aussi possible d'accéder à ``argv`` en utilisant des pointeurs. Parmi les fragments de programme ci-dessous, un seul est correct et affiche le même résultat que ci-dessus. - - .. positive:: - - - .. code-block:: c - - char **ptr; - int i=0; - ptr=argv; - while(i<argc) { - printf("%d %p %s\n",i,&(*ptr),*ptr); - i++; - ptr++; - } - - - .. negative:: - - .. code-block:: c - - char **ptr; - int i=0; - ptr=argv; - while(i<argc) { - printf("%d %p %s\n",i,&(ptr),*ptr); - i++; - ptr++; - } - - - .. comment:: - - ``&(ptr)`` est l'adresse à laquelle le pointeur ``ptr`` est stocké. Notez que ce n'est pas l'adresse à laquelle la chaîne de caractère argument ``i`` est stockée. Ce programme affiche : - - .. code-block:: console - - 0 0x7fff5fbff738 ./a.out - 1 0x7fff5fbff738 a - 2 0x7fff5fbff738 b - 3 0x7fff5fbff738 cd - - .. negative:: - - .. code-block:: c - - char *ptr; - int i=0; - ptr=*argv; - while(i<argc) { - printf("%d %p %s\n",i,&(ptr),*ptr); - i++; - ptr++; - } - - .. comment:: - - Notez dans ce code que ``ptr`` est déclaré comme ``char *``, alors que ``argv`` est un ``char **``. Si vous tenez d'exécutez ce code, il provoquera un segmentation fault. - - .. negative:: - - .. code-block:: c - - int i=0; - while(i<argc) { - printf("%d %p %s\n",i,&(argv+i),*(argv+i)); - i++; - } - - .. comment:: - - La compilation de ce fragment de programme provoque un warning. L'expression ``&(argv+i)`` est invalide car ``argv`` est un pointeur (de type ``char **``) et donc ``argv+i`` est également une adresse en mémoire et l'opérateur ``&`` ne peut pas s'y appliquer. - - .. negative:: - - .. code-block:: c - - int i=0; - while(i<argc) { - printf("%d %p %s\n",i,&(*(argv+i)),(argv+i)); - i++; - } - - - .. comment:: - - Dans ce fragment de code, ``argv+i`` est de type ``char **`` alors qu'il faut un ``char *`` pour passer un string à `printf(3)`_. - - - -Question 3. Pointeurs et tableaux à deux dimensions ---------------------------------------------------- - -En C, il est possible d'accéder aux données stockées dans un tableau à deux dimensions via la notation ``a[i][j]`` mais aussi en utilisant des pointeurs. Considérons le fragment de code ci-dessous : - -.. code-block:: c - - int m[3][4]= { { 1, 2, 3, 4} , - { 5, 6, 7, 8} , - { 9, 10, 11, 12} }; - - printf("%p %d %d %d\n",m, m[1][2], m[0][5], m[2][2]); - - -Un compilateur Java n'accepterait pas de compiler ce programme qui tente d'accéder à l'élément ``m[0][5]`` de la matrice, élément qui n'existe pas sur base de l'initialisation du tableau ``m``. De nombreux compilateurs C acceptent ce fragment de code sans contrainte. Lorsque le programme s'exécute il affiche : - -.. code-block:: console - - 0x7fff5fbff750 7 6 11 - -.. question:: ptr-tableaux2d - :nb_prop: 3 - :nb_pos: 1 - - Parmi les fragments de programme ci-dessous, un seul utilisant la notation avec les pointeurs est correct et affiche la même sortie. Lequel ? - - .. positive:: - - - .. code-block:: c - - int *ptr; - - ptr=&(m[0][0]); - printf("%p %d %d %d\n",ptr, *(ptr+4*1+2), *(ptr+4*0+5), *(ptr+2*4+2)); - - - .. negative:: - - .. code-block:: c - - int **ptr=m; - printf("%p %d %d %d\n",ptr, *(ptr+4*1+2), *(ptr+4*0+5), *(ptr+2*4+2)); - - .. comment:: - - La déclaration ``int **ptr=m`` est invalide. - - .. negative:: - - .. code-block:: c - - int *ptr=m; - printf("%p %d %d %d\n",ptr, *(ptr+4*1+2), *(ptr+4*0+5), *(ptr+2*4+2)); - - - .. comment:: - - La déclaration ``int *ptr=m;`` est invalide, ``m`` n'est pas de type ``int *``. - -Question 4. Variable ``errno`` ------------------------------- -.. question:: errno - :nb_prop: 3 - :nb_pos: 1 - - En C, la variable ``errno`` est utilisée par le système pour fournir une indication sur une erreur qui s'est produite lors de l'exécution d'un appel système ou d'une fonction de la librairie. Parmi les fonctions ci-dessous, une seule ne modifie pas ``errno`` en cas d'erreur. Laquelle ? - - .. positive:: - - `getpid(2)`_ - - .. comment:: - - Voir page de manuel. - - .. negative:: - - `malloc(3)`_ - - .. comment:: - - Notez que `malloc(3)`_ retourne ``NULL`` en cas d'erreur d'allocation mais met ENONMEM comme erreur dans ``errno`` - - .. positive:: - - `exit(2)`_ - - .. comment:: - - Comme cette fonction ne se termine jamais, elle ne peux pas modifier ``errno``. - - .. negative:: - - `setenv(3)`_ - - .. comment:: - - Voir page de manuel. - - .. negative:: - - `unsetenv(3)`_ - - .. comment:: - - Voir page de manuel. - - .. negative:: - - `pthread_join(3)`_ - - .. comment:: - - Voir page de manuel et aussi http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html. La plupart des fonctions pthread_* ne modifient pas la valeur de ``errno``, mais le standard n'est pas 100% clair sur ce qu'une implémentation doit faire. Linux ne semble pas fixer la valeur de ``errno``. - - diff --git a/Exercices/mcq-ex/qcm-5.rst.old b/Exercices/mcq-ex/qcm-5.rst.old deleted file mode 100644 index 82f2193b520b8d2b748833fa261d94082fafe41c..0000000000000000000000000000000000000000 --- a/Exercices/mcq-ex/qcm-5.rst.old +++ /dev/null @@ -1,330 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -Questions à choix multiples -=========================== - -:task_id: sinf1252-5 - -Cette semaine porte sur deux modules de théorie. Le premier est la fin du chapitre consacré aux bases du langage C : - - - :ref:`complementsC` - -Le second est le début du chapitre consacré aux systèmes multiprocesseurs et l'utilisation de threads en particulier : - - - :ref:`threads` - -Question 1. Pointeurs en assembleur ------------------------------------ - -Pour comprendre le fonctionnement des pointeurs en C, il est parfois utile de se ramener à la traduction en assembleur de fragments de code C. Considérons les lignes suivantes : - - .. code-block:: c - - int a=1252; - int * ptr; - - int main(int argc, const char *argv[]) { - ptr=&a; - } - -.. question:: ptrasm - :nb_prop: 3 - :nb_pos: 1 - - Parmi les séquences d'instructions en assembleur ci-dessous, une seule est la traduction de l'assignation de l'adresse de ``a`` au pointeur ``ptr``. Laquelle - - .. positive:: - - - .. code-block:: nasm - - leal a, %eax - movl %eax, ptr - - .. negative:: - - - .. code-block:: nasm - - movl a, %eax - movl ptr, %ecx - movl %eax, (%ecx) - - .. comment:: Cette séquence d'instructions est la traduction de ``*ptr=a``. - - .. negative:: - - .. code-block:: nasm - - movl a, %eax - movl %eax, ptr - - .. comment:: Cette séquence d'instructions est la traduction de ``ptr=(int )a;``. - - .. negative:: - - - .. code-block:: nasm - - pushl %eax - leal (%esp), %eax - movl a, %ecx - movl %ecx, (%esp) - movl %eax, ptr - popl %eax - - .. comment:: - - Cette séquence d'instructions est la traduction de : - - .. code-block:: c - - int b=a; - ptr=&(b); - - .. negative:: - - - .. code-block:: nasm - - leal a, %eax - addl $4, %eax - movl %eax, ptr - - .. comment:: - - Cette séquence d'instructions est la traduction de ``ptr=&a+1;``. - - - -Question 6. Utilisation de `pthread_create(3)`_ ------------------------------------------------- - - -.. question:: pthread_create - :nb_prop: 3 - :nb_pos: 1 - - - La fonction `pthread_create(3)`_ permet de créer un thread. Parmi les fragments de code ci-dessous, un seul crée correctement un thread qui appelle la fonction ``f`` en lui passant la chaîne de caractères ``s`` comme argument. Lequel ? - - .. positive:: - - .. code-block:: c - - void * f( void * param) { - // incomplet - return NULL; - } - - int main (int argc, char *argv[]) { - - pthread_t t; - int err; - char *s; - err=pthread_create(&t,NULL,&(f),(void *) s); - } - - - .. negative:: - - .. code-block:: c - - void * f (void * param) { - // incomplet - return NULL; - } - - int main (int argc, char *argv[]) { - - pthread_t t; - int err; - char *s; - err=pthread_create(&t,NULL,&(f),(void *) &s); - } - - .. comment:: Ce fragment contient une erreur. La fonction ``f`` a la bonne signature, mais le dernier argument à `pthread_create(3)`_ doit être de type ``void *``, or ``s`` est un ``char *`` et donc ce dernier argument doit être ``(void *) s``. - - .. negative:: - - .. code-block:: c - - void f(void * param) { - // incomplet - return NULL; - } - - int main (int argc, char *argv[]) { - - pthread_t *t; - int err; - char *s; - err=pthread_create(t,NULL,*f,(void *) *s); - } - - .. comment:: Ce fragment contient plusieurs erreurs. La fonction ``f`` n'a pas la bonne signature (d'ailleurs ``return NULL;`` pour une fonction ``void`` est incorrect). Ensuite, l'appel à `pthread_create(3)`_ doit prendre comme premier argument l'adresse vers une structure de type ``pthread_t`` qui est stockée en mémoire. Ce n'est pas le cas ici. Les troisième et quatrième arguments sont également incorrects. - - .. negative:: - - .. code-block:: c - - - void *f(void ** param) { - // incomplet - return NULL; - } - - int main (int argc, char *argv[]) { - - pthread_t t; - int err; - char s; - err=pthread_create(&t,NULL,&(f),(void *) s); - } - - .. comment:: Dans ce fragment de code, la signature de la fonction ``f`` ainsi que l'appel à `pthread_create(3)`_ sont incorrects. - - - -Question 7. Passage d'arguments à un thread -------------------------------------------- - -Considérons un thread qui a pour objectif de convertir une fraction en un nombre en virgule flottante. Ce n'est pas une bonne utilisation de threads puisque le calcul à effectuer est très simple, mais cela nous permettra de voir comment un thread peut recevoir des arguments directement. En dehors des threads, cette fonction de conversion pourrait s'écrire : - -.. code-block:: c - - struct fraction { - int num; - int denum; - }; - - typedef struct fraction Fraction_t; - - float tofloat(Fraction_t t) { - return (float) t.num/ (float) t.denum; - } - -.. question:: argthread - :nb_prop: 3 - :nb_pos: 1 - - Parmi les programmes ci-dessous, un seul calcule correctement la valeur attendue (le test des valeurs de retour des fonctions n'est pas présenté pour garder le code concis). Lequel ? - - - .. positive:: - - - .. code-block:: c - - void *mythread(void * param) { - Fraction_t *f=(Fraction_t *) param; - float *r=(float *)malloc(sizeof(float)); - *r=(float) f->num/ (float) f->denum; - return((void *) r); - } - - int main (int argc, char *argv[]) { - - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - float *r; - int err; - - err=pthread_create(&t,NULL,&mythread,&(f)); - - err=pthread_join(t,(void **) &r); - - } - - - .. negative:: - - .. code-block:: c - - void *mythread(void * param) { - Fraction_t f= *param; - float r; - r=(float) f.num/ (float) f.denum; - return((void *) &r); - } - - int main (int argc, char *argv[]) { - - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - float r; - int err; - - err=pthread_create(&t,NULL,&mythread,&(f)); - - err=pthread_join(t,(void **) &r); - - } - - .. comment:: La fonction ``mythread`` est incorrect. L'initialisation de ``f`` ne fonctionne pas et en plus le résultat de la fonction est une variable locale (``r``) qui disparaît après son exécution. L'adresse de cette variable, même en étant castée en ``void *`` ne peut pas être retournée à la fonction ``main``. - - .. negative:: - - .. code-block:: c - - - void *mythread(void * param) { - Fraction_t *t=(Fraction_t *) param; - float *r=(float *)malloc(sizeof(float)); - *r=(float) t->num/ (float) t->denum; - return((void *) r); - } - - int main (int argc, char *argv[]) { - - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - float r; - int err; - - err=pthread_create(&t,NULL,&mythread,&f); - r=pthread_join(t,NULL); - - } - - .. comment:: Dans cette variable, l'appel à `pthread_join(3)`_ est incorrect. - - .. negative:: - - .. code-block:: c - - float mythread(Fraction_t param) { - float *r=(float *)malloc(sizeof(float)); - *r=(float) param->num/ (float) param->denum; - return(r); - } - - int main (int argc, char *argv[]) { - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - printf("%f \n",tofloat(f)); - float *r; - int err; - - err=pthread_create(&t,NULL,&mythread,&(f)); - - err=pthread_join(t,(void *) &r); - } - - .. comment:: Cette variante contient deux erreurs. La première est le prototype de la fonction ``mythread``. Celle-ci doit obligatoirement être de type ``void * fct(void * param)``, il n'est pas possible d'utiliser un autre prototype. Ensuite, l'appel à `pthread_join(3)`_ est incorrect puisque le deuxième argument de `pthread_join(3)`_ doit être de type ``void **`` et non ``void *``. - - -.. include:: ../../links.rst -.. include:: ../../man_links.rst -.. include:: ../../incl_links.rst diff --git a/Exercices/mcq-ex/qcm-6.rst b/Exercices/mcq-ex/qcm-6.rst deleted file mode 100644 index e850fd7c20da2ab1eb79cefd3c136125ef583a99..0000000000000000000000000000000000000000 --- a/Exercices/mcq-ex/qcm-6.rst +++ /dev/null @@ -1,722 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -Questions à choix multiples -=========================== - -:task_id: sinf1252-6 - -Cette semaine porte sur la communication et la synchronisation entre threads. Plus précisément, la matière est décrite dans les deux sections suivantes : - - - :ref:`theorie:threads` (sauf la section `Utilisation d'instruction atomique`) - - :ref:`theorie:comthreads` (jusqu'à la section `Le problème des philosophes`) - -.. - `Communication entre threads <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/Threads/threads2.html>`_ -.. - `Coordination entre threads <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/Threads/threads2.html#coordination-entre-threads>`_ - - - - -Question 1. Utilisation de `pthread_create(3)`_ ------------------------------------------------- - - -.. question:: pthread_create - :nb_prop: 3 - :nb_pos: 1 - - - La fonction `pthread_create(3)`_ permet de créer un thread. Parmi les fragments de code ci-dessous, un seul crée correctement un thread qui appelle la fonction ``f`` en lui passant la chaîne de caractères ``s`` comme argument. Lequel ? - - .. positive:: - - .. code-block:: c - - void * f( void * param) { - // incomplet - return NULL; - } - - int main (int argc, char *argv[]) { - - pthread_t t; - int err; - char *s; - err=pthread_create(&t,NULL,&(f),(void *) s); - } - - - .. negative:: - - .. code-block:: c - - void * f (void * param) { - // incomplet - return NULL; - } - - int main (int argc, char *argv[]) { - - pthread_t t; - int err; - char *s; - err=pthread_create(&t,NULL,&(f),(void *) &s); - } - - .. comment:: Ce fragment contient une erreur. La fonction ``f`` a la bonne signature, mais le dernier argument à `pthread_create(3)`_ doit être de type ``void *``, or ``s`` est un ``char *`` et donc ce dernier argument doit être ``(void *) s``. - - .. negative:: - - .. code-block:: c - - void f(void * param) { - // incomplet - return NULL; - } - - int main (int argc, char *argv[]) { - - pthread_t *t; - int err; - char *s; - err=pthread_create(t,NULL,*f,(void *) *s); - } - - .. comment:: Ce fragment contient plusieurs erreurs. La fonction ``f`` n'a pas la bonne signature (d'ailleurs ``return NULL;`` pour une fonction ``void`` est incorrect). Ensuite, l'appel à `pthread_create(3)`_ doit prendre comme premier argument l'adresse vers une structure de type ``pthread_t`` qui est stockée en mémoire. Ce n'est pas le cas ici. Les troisième et quatrième arguments sont également incorrects. - - .. negative:: - - .. code-block:: c - - - void *f(void ** param) { - // incomplet - return NULL; - } - - int main (int argc, char *argv[]) { - - pthread_t t; - int err; - char s; - err=pthread_create(&t,NULL,&(f),(void *) s); - } - - .. comment:: Dans ce fragment de code, la signature de la fonction ``f`` ainsi que l'appel à `pthread_create(3)`_ sont incorrects. - - - -Question 2. Passage d'arguments à un thread -------------------------------------------- - -Considérons un thread qui a pour objectif de convertir une fraction en un nombre en virgule flottante. Ce n'est pas une bonne utilisation de threads puisque le calcul à effectuer est très simple, mais cela nous permettra de voir comment un thread peut recevoir des arguments directement. En dehors des threads, cette fonction de conversion pourrait s'écrire : - -.. code-block:: c - - struct fraction { - int num; - int denum; - }; - - typedef struct fraction Fraction_t; - - float tofloat(Fraction_t t) { - return (float) t.num/ (float) t.denum; - } - -.. question:: argthread - :nb_prop: 3 - :nb_pos: 1 - - Parmi les programmes ci-dessous, un seul calcule correctement la valeur attendue (le test des valeurs de retour des fonctions n'est pas présenté pour garder le code concis). Lequel ? - - - .. positive:: - - - .. code-block:: c - - void *mythread(void * param) { - Fraction_t *f=(Fraction_t *) param; - float *r=(float *)malloc(sizeof(float)); - *r=(float) f->num/ (float) f->denum; - return((void *) r); - } - - int main (int argc, char *argv[]) { - - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - float *r; - int err; - - err=pthread_create(&t,NULL,&mythread,&(f)); - - err=pthread_join(t,(void **) &r); - - } - - - .. negative:: - - .. code-block:: c - - void *mythread(void * param) { - Fraction_t f= *param; - float r; - r=(float) f.num/ (float) f.denum; - return((void *) &r); - } - - int main (int argc, char *argv[]) { - - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - float r; - int err; - - err=pthread_create(&t,NULL,&mythread,&(f)); - - err=pthread_join(t,(void **) &r); - - } - - .. comment:: La fonction ``mythread`` est incorrect. L'initialisation de ``f`` ne fonctionne pas et en plus le résultat de la fonction est une variable locale (``r``) qui disparaît après son exécution. L'adresse de cette variable, même en étant castée en ``void *`` ne peut pas être retournée à la fonction ``main``. - - .. negative:: - - .. code-block:: c - - - void *mythread(void * param) { - Fraction_t *t=(Fraction_t *) param; - float *r=(float *)malloc(sizeof(float)); - *r=(float) t->num/ (float) t->denum; - return((void *) r); - } - - int main (int argc, char *argv[]) { - - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - float r; - int err; - - err=pthread_create(&t,NULL,&mythread,&f); - r=pthread_join(t,NULL); - - } - - .. comment:: Dans cette variable, l'appel à `pthread_join(3)`_ est incorrect. - - .. negative:: - - .. code-block:: c - - float mythread(Fraction_t param) { - float *r=(float *)malloc(sizeof(float)); - *r=(float) param->num/ (float) param->denum; - return(r); - } - - int main (int argc, char *argv[]) { - pthread_t t; - Fraction_t f; - f.num=1; - f.denum=3; - printf("%f \n",tofloat(f)); - float *r; - int err; - - err=pthread_create(&t,NULL,&mythread,&(f)); - - err=pthread_join(t,(void *) &r); - } - - .. comment:: Cette variante contient deux erreurs. La première est le prototype de la fonction ``mythread``. Celle-ci doit obligatoirement être de type ``void * fct(void * param)``, il n'est pas possible d'utiliser un autre prototype. Ensuite, l'appel à `pthread_join(3)`_ est incorrect puisque le deuxième argument de `pthread_join(3)`_ doit être de type ``void **`` et non ``void *``. - - -Question 3. Algorithme de Peterson ----------------------------------- - -.. question:: peterson - :nb_prop: 3 - :nb_pos: 1 - - L'algorithme de Peterson peut s'écrire de différentes façons. Pour bien comprendre son fonctionnement, il est utile de réfléchir à d'autres formulations que celle utilisées dans le syllabus. Parmi les fragments de code ci-dessous, un seul implémente correctement l'algorithme de Peterson. Lequel ? - - - .. positive:: - - .. code-block:: c - - /* initialisation */ - bool in1 = false; - bool in2 = false; - int last = 1; - // thread 1 - while (true) { - in1 = true; - last = 1; - while ( in2 && (last==1)) {}; - section_critique(); - in1=false; - // ... - } - // thread2 - while (true) { - in2 = true; - last = 2; - while ( in1 && (last==2)) {}; - section_critique(); - in2=false; - // ... - } - - .. positive:: - - .. code-block:: c - - /* initialisation */ - bool in1 = false; - bool in2 = false; - int last = 2; - // thread 1 - while (true) { - in1 = true; - last = 1; - while ( in2 && (last==1)) {}; - section_critique(); - in1=false; - // ... - } - // thread2 - while (true) { - in2 = true; - last = 2; - while ( in1 && (last==2)) {}; - section_critique(); - in2=false; - // ... - } - - .. negative:: - - - .. code-block:: c - - // initialisation - bool in1 = false; - bool in2 = false; - int last = 1; - // thread 1 - while (true) { - in1 = true; - last = 1; - while ( in1 && (last==1)) {}; - section_critique(); - in1=false; - // ... - } - // thread2 - while (true) { - in2 = true; - last = 2; - while ( in2 && (last==2)) {}; - section_critique(); - in2=false; - // ... - } - - .. comment:: - - Cette solution ne fonctionne pas. Si un des deux threads est seul, il n'entrera jamais en section critique. - - .. negative:: - - .. code-block:: c - - // initialisation - bool in1 = false; - bool in2 = false; - int last = 2; - // thread 1 - while (true) { - in1 = true; - last = 1; - while ( in2 && (last==2)) {}; - section_critique(); - in1=false; - // ... - } - // thread2 - while (true) { - in2 = true; - last = 2; - while ( in1 && (last==1)) {}; - section_critique(); - in2=false; - // ... - } - - .. comment:: - - Cette solution ne fonctionne pas. Il est possible que le thread 1 rentre en section critique puis le thread 2 met ``last`` à 2 et peut également y entrer sans que thread 1 n'en soit sorti. - - .. negative:: - - .. code-block:: c - - // initialisation - bool in1 = false; - bool in2 = false; - int last = 1; - // thread 1 - while (true) { - last = 1; - in1 = true; - while ( in2 && (last==1)) {}; - section_critique(); - in1=false; - // ... - } - // thread2 - while (true) { - last = 2; - in2 = true; - while ( in1 && (last==2)) {}; - section_critique(); - in2=false; - // ... - } - - .. comment:: - - Cette solution ne fonctionne pas. Il y a un risque de violation de section critique. Si le thread 1 fait ``last=1;`` puis est interrompu avant de faire ``in1=true;``. Le thread 2 exécute alors ``last=2;`` suivi de ``in2=true;``. A cet instant, ``in2==false`` et le thread 2 rentre en section critique puisque ``in1==false``. Le thread 1 se réveille et exécute ``in1=true;``. Il peut ensuite immédiatement entre en section critique puisque ``last`` vaut ``2`` à cet instant. - -Question 4. Initialisation de mutex ------------------------------------ - -.. question:: mutexinit - :nb_prop: 3 - :nb_pos: 1 - - Avant de pouvoir utiliser un mutex POSIX, il est nécessaire de déclarer la structure correspondante et initialiser le mutex. Parmi les fragments de code ci-dessous, lequel est celui qui déclare et initialise correctement un mutex ? - - .. positive:: - - .. code-block:: c - - pthread_mutex_t mutex; - pthread_mutexattr_t attr; - - err= pthread_mutexattr_init(&attr); - if(err!=0) - error(err,"pthread_mutexattr_init"); - - err=pthread_mutex_init( &mutex, &attr); - if(err!=0) - error(err,"pthread_mutex_init"); - - .. comment:: - - Notez que dans ce cas, le mutex est initialisé avec les attributs par défaut. - - - .. positive:: - - .. code-block:: c - - pthread_mutex_t mutex; - - err=pthread_mutex_init( &mutex, NULL); - if(err!=0) - error(err,"pthread_mutex_init"); - - .. comment:: - - Notez que dans ce cas, le mutex est initialisé avec les attributs par défaut. - - .. negative:: - - - .. code-block:: c - - pthread_mutex_t mutex; - pthread_mutexattr_t attr; - - err= pthread_mutexattr_init(attr); - if(err!=0) - error(err,"pthread_mutexattr_init"); - - err=pthread_mutex_init(mutex, attr); - if(err!=0) - error(err,"pthread_mutex_init"); - - .. comment:: Tant `pthread_mutexattr_init(3posix)`_ que `pthread_mutex_init(3posix)`_ prennent comme arguments un *pointeur* vers une structure de type ``pthread_mutex_t``. Ces deux fonctions modifient le contenu de cette structure et doivent donc en recevoir l'adresse comme argument. - - - .. negative:: - - .. code-block:: c - - pthread_mutex_t mutex; - pthread_mutexattr_t attr; - - err= pthread_mutexattr_init(&attr); - if(err!=0) - error(err,"pthread_mutexattr_init"); - - err=pthread_mutex_init(&mutex, attr); - if(err!=0) - error(err,"pthread_mutex_init"); - - .. comment:: Tant `pthread_mutexattr_init(3posix)`_ que `pthread_mutex_init(3posix)`_ prennent comme arguments un *pointeur* vers une structure de type ``pthread_mutex_t``. Ces deux fonctions modifient le contenu de cette structure et doivent donc en recevoir l'adresse comme argument. - - - .. negative:: - - .. code-block:: c - - pthread_mutex_t *mutex; - pthread_mutexattr_t *attr; - - err= pthread_mutexattr_init(attr); - if(err!=0) - error(err,"pthread_attr_init"); - - err=pthread_mutex_init(mutex, attr); - if(err!=0) - error(err,"pthread_mutex_init"); - - .. comment:: Tant `pthread_mutexattr_init(3posix)`_ que `pthread_mutex_init(3posix)`_ prennent comme arguments un *pointeur* vers une structure de type ``pthread_mutex_t``. La mémoire permettant de stocker ces deux structures doit avoir été réservée en utilisant `malloc(3)`_ avant de faire appel à ces deux fonctions. - - - -Question 5. Utilisation de `pthread_mutex_lock(3posix)`_ et `pthread_mutex_unlock(3posix)`_ -------------------------------------------------------------------------------------------- - -.. question:: pthread_mutex_lock - :nb_prop: 3 - :nb_pos: 1 - - Un programme utilisant plusieurs threads doit mettre à jour une variable globale partagée entre tous les threads. Pour cela, le développeur écrit une fonction ``update`` qui prend comme arguments la variable à mettre à jour et le mutex qui y est associé. Parmi les extraits ci-dessous, lequel permet de mettre à jour la variable sans risque de contention entre les threads qui y accèdent ? - - .. positive:: - - - .. code-block:: c - - void update(int * val, pthread_mutex_t * mutex) { - - err=pthread_mutex_lock(mutex); - if(err!=0) - error(err,"pthread_mutex_lock"); - - // mise à jour de la variable globale - - err=pthread_mutex_unlock(mutex); - if(err!=0) - error(err,"pthread_mutex_unlock"); - - } - - - .. negative:: - - - .. code-block:: c - - void update(int * val, pthread_mutex_t * mutex) { - - err=pthread_mutex_unlock(mutex); - if(err!=0) - error(err,"pthread_mutex_unlock"); - - // mise à jour de la variable globale - - err=pthread_mutex_lock(mutex); - if(err!=0) - error(err,"pthread_mutex_lock"); - - } - - .. comment:: Ce code est incorrect. Un mutex s'utilise en faisant d'abord ``pthread_mutex_lock`` et ensuite ``pthread_mutex_unlock``. - - .. negative:: - - .. code-block:: c - - void update(int val, pthread_mutex_t mutex) { - - err=pthread_mutex_lock(mutex); - if(err!=0) - error(err,"pthread_mutex_lock"); - - // mise à jour de la variable globale - - err=pthread_mutex_unlock(mutex); - if(err!=0) - error(err,"pthread_mutex_unlock"); - - } - - .. comment:: L'utilisation de cette fonction implique que la structure ``pthread_mutex_t`` doit être copiée sur le stack avant de pouvoir être utilisée par la fonction. Cette solution ne peut fonctionner car la structure de données qui contient toute l'information relative à un mutex et placée à un endroit donné en mémoire et ne peut pas être copiée. - - - .. negative:: - - .. code-block:: c - - void update(int * val, pthread_mutex_t mutex) { - - err=pthread_mutex_lock(&mutex); - if(err!=0) - error(err,"pthread_mutex_lock"); - - // mise à jour de la variable globale - - err=pthread_mutex_unlock(&mutex); - if(err!=0) - error(err,"pthread_mutex_unlock"); - - } - - .. comment:: L'utilisation de cette fonction implique que la structure ``pthread_mutex_t`` doit être copiée sur le stack avant de pouvoir être utilisée par la fonction. Cette solution ne peut fonctionner car la structure de données qui contient toute l'information relative à un mutex et placée à un endroit donné en mémoire et ne peut pas être copiée. - - - -Question 6. Utilisation de plusieurs mutex ------------------------------------------- - - - -Dans certains programmes, il est nécessaire de définir plusieurs mutex qui sont utilisés par différents threads pour gérer l'accès à des variables partagées. Considérons un programme qui utilise trois variables globales et est découpé en plusieurs threads. - -.. code-block:: c - - long a=5; // variable globale partagée - long b=7; // variable globale partagée - long c=9; // variable globale partagée - - pthread_mutex_t x; // variable globale associée à a - pthread_mutex_t y; // variable globale associée à b - pthread_mutex_t z; // variable globale associée à c - - - void update(int * val1, int * val2, pthread_mutex_t * mutex1, pthread_mutex_t * mutex2) { - - err=pthread_mutex_lock(mutex1); - if(err!=0) - error(err,"pthread_mutex_lock"); - err=pthread_mutex_lock(mutex2); - if(err!=0) - error(err,"pthread_mutex_lock"); - - // mise à jour val1 - // mise à jour val2 - - err=pthread_mutex_unlock(mutex1); - if(err!=0) - error(err,"pthread_mutex_unlock"); - - err=pthread_mutex_unlock(mutex2); - if(err!=0) - error(err,"pthread_mutex_unlock"); - - } - -.. question:: plusieursmutex - :nb_prop: 3 - :nb_pos: 1 - - Ce programme utilise plusieurs threads qui modifient les variables ``a``, ``b`` et ``c``. Parmi les fragments de code ci-dessous qui utilisent plusieurs threads, un seul est correct. Lequel ? - - .. positive:: - - - .. code-block:: c - - // thread A - - update(&a,&b,&x,&y); - update(&a,&c,&x,&z); - - // thread B - - update(&b,&c,&y,&z); - update(&a,&c,&x,&z); - - - .. positive:: - - .. code-block:: c - - // thread A - - update(&a,&b,&x,&y); - update(&b,&c,&y,&z); - - // thread B - - update(&b,&c,&y,&z); - update(&a,&c,&x,&z); - - - .. negative:: - - - .. code-block:: c - - // thread A - - update(&a,&b,&x,&y); - update(&c,&a,&z,&x); - - // thread B - - update(&b,&c,&y,&z); - update(&a,&c,&x,&z); - - .. comment:: Lorsqu'un thread utilise plusieurs ressources protégées par un mutex, il est important que les accès à ces mutex se fasse chaque fois dans le même ordre. Dans cet exemple, il faut toujours accéder à ``x`` puis à ``y`` puis à ``z`` (ou un autre ordre). Accéder à ``z`` puis à ``x`` dans le thread A et à ``x`` puis à ``z`` dans le thread B est une source de deadlocks potentiels. - - .. negative:: - - .. code-block:: none - - // thread A - - update(&a,&b,&x,&y); - update(&a,&c,&x,&z); - - // thread B - - update(&b,&c,&y,&z); - update(&c,&a,&z,&x); - - .. comment:: Lorsqu'un thread utilise plusieurs ressources protégées par un mutex, il est important que les accès à ces mutex se fasse chaque fois dans le même ordre. Dans cet exemple, il faut toujours accéder à ``x`` puis à ``y`` puis à ``z`` (ou un autre ordre). Accéder à ``z`` puis à ``x`` dans le thread B et à ``x`` puis à ``z`` dans le thread A est une source de deadlocks potentiels. - - .. negative:: - - .. code-block:: c - - // thread A - - update(&a,&b,&x,&y); - update(&a,&b,&x,&y); - - // thread B - - update(&b,&a,&y,&x); - update(&a,&c,&x,&z); - - .. comment:: Lorsqu'un thread utilise plusieurs ressources protégées par un mutex, il est important que les accès à ces mutex se fasse chaque fois dans le même ordre. Dans cet exemple, il faut toujours accéder à ``x`` puis à ``y`` puis à ``z`` (ou un autre ordre). Accéder à ``a`` puis à ``y`` dans le thread A et à ``y`` puis à ``x`` dans le thread B est une source de deadlocks potentiels. - diff --git a/Exercices/mcq-ex/qcm-7.rst b/Exercices/mcq-ex/qcm-7.rst deleted file mode 100644 index 0aeb7fb1a6821fab0e1457aa92ca649bea2e17c1..0000000000000000000000000000000000000000 --- a/Exercices/mcq-ex/qcm-7.rst +++ /dev/null @@ -1,445 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - - - -Questions à choix multiples -=========================== - -:task_id: sinf1252-7 - - -Question 1. Utilisation des sémaphores --------------------------------------- - -.. question:: sem1 - :nb_prop: 3 - :nb_pos: 1 - - Avant d'être utilisé, un sémaphore doit être déclaré et initialisé. Après son utilisation, il doit être détruit. Parmi les séquences d'instructions ci-dessous, une seule initialise correctement un sémaphore à la valeur 1. Laquelle ? - - .. positive:: - - .. code-block:: c - - sem_t semaphore; - - sem_init(&semaphore, 0,1); - - // ... - - sem_destroy(&semaphore); - - - .. positive - - .. code-block:: c - - sem_t *semaphore; - semaphore=(sem_t *)malloc(sizeof(struct sem_t)); - if (semaphore==NULL) - error("malloc"); - - sem_init(semaphore, 0,1); - - // ... - - sem_destroy(semaphore); - - - .. negative:: - - .. code-block:: c - - sem_t semaphore; - - sem_init(semaphore, 1,0); - - // ... - - sem_destroy(semaphore); - - .. comment:: - - `sem_init(3)`_ et `sem_destroy(3)`_ prennent comme premier argument un pointeur vers une structure ``sem_t``. `sem_init(3)`_ prend comme troisième argument la valeur initiale du sémaphore. - - .. negative:: - - .. code-block:: c - - sem_t semaphore; - - sem_init(&semaphore, 1,0); - - // ... - - sem_destroy(&semaphore); - - .. comment:: - - `sem_init(3)`_ prend comme troisième argument la valeur initiale du sémaphore. - - .. negative:: - - .. code-block:: c - - sem_t *semaphore; - semaphore=(sem_t *)malloc(sizeof(struct sem_t)); - if (semaphore==NULL) - error("malloc"); - - sem_init(semaphore, 1, 0); - - // ... - - sem_destroy(semaphore); - - .. comment:: - - `sem_init(3)`_ prend comme troisième argument la valeur initiale du sémaphore. - - - .. negative:: - - .. code-block:: none - - sem_t *semaphore; - semaphore=(sem_t *)malloc(sizeof(struct sem_t)); - if (semaphore==NULL) - error("malloc"); - - sem_init(semaphore, 1, 0); - - // ... - - sem_destroy(&semaphore); - - .. comment:: - - `sem_init(3)`_ prend comme troisième argument la valeur initiale du sémaphore. `sem_destroy(3)`_ prennent comme premier argument un pointeur vers une structure ``sem_t``. - - -Question 2. Exclusion mutuelle ------------------------------- - -.. question:: semmutex - :nb_prop: 3 - :nb_pos: 1 - - Les sémaphores peuvent être utilisés tout comme les mutex pour résoudre des problèmes d'exclusion mutuelle. Parmi les extraits de programmes ci-dessous, une seule est une solution correcte au problème de l'exclusion mutuelle en utilisant des sémaphores. Laquelle ? - - .. positive:: - - - .. code-block:: c - - - static sem_t semaphore; - long global=0; - - int increment(int i) { - // ... - } - - void *inc(void * param) { - for(int j=0;j<1000000;j++) { - sem_wait(&semaphore); - global=increment(global); - sem_post(&semaphore); - } - } - - int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - - sem_init(&semaphore, 0,1); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&inc,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - // reste non fourni - } - - .. positive:: - - .. code-block:: c - - - sem_t * semaphore; - long global=0; - - int increment(int i) { - // ... - } - - void *inc(void * param) { - for(int j=0;j<1000000;j++) { - sem_wait(semaphore); - global=increment(global); - sem_post(semaphore); - } - } - - int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - semaphore=(sem_t *)malloc(sizeof(sem_t)) - if(semaphore==NULL) - error("malloc"); - - sem_init(semaphore, 0,1); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&inc,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - // reste non fourni - } - - .. negative:: - - - .. code-block:: c - - - static sem_t semaphore; - long global=0; - - int increment(int i) { - // ... - } - - void *inc(void * param) { - for(int j=0;j<1000000;j++) { - sem_wait(&semaphore); - global=increment(global); - sem_post(&semaphore); - } - } - - int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - - sem_init(&semaphore, 0,0); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&inc,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - // reste non fourni - } - - .. comment:: - - Pour résoudre un problème d'exclusion mutuelle, il faut initialiser le sémaphore à ``1`` avec `sem_init(3)`_ et non à ``0`` comme dans cet exemple. - - .. negative:: - - .. code-block:: c - - - static sem_t semaphore; - long global=0; - - int increment(int i) { - // ... - } - - void *inc(void * param) { - for(int j=0;j<1000000;j++) { - sem_post(&semaphore); - global=increment(global); - sem_wait(&semaphore); - } - } - - int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - - sem_init(&semaphore, 0,0); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&inc,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - // reste non fourni - } - - .. comment:: - - Pour résoudre un problème d'exclusion mutuelle, il faut initialiser le sémaphore à ``1`` avec `sem_init(3)`_ et non à ``0`` comme dans cet exemple. En outre, l'accès à la section critique doit être précédée par un appel à `sem_wait(3)`_ et suivie par un appel à `sem_post(3)`_ et non l'inverse comme dans cet exemple. - - .. negative:: - - .. code-block:: c - - - sem_t * semaphore; - long global=0; - - int increment(int i) { - // ... - } - - void *inc(void * param) { - for(int j=0;j<1000000;j++) { - sem_wait(semaphore); - global=increment(global); - sem_post(semaphore); - } - } - - int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - semaphore=(sem_t *)malloc(sizeof(sem_t)) - if(semaphore==NULL) - error("malloc"); - - sem_init(semaphore, 0,0); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&inc,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - // reste non fourni - } - - .. comment:: - - Pour résoudre un problème d'exclusion mutuelle, il faut initialiser le sémaphore à ``1`` avec `sem_init(3)`_ et non à ``0`` comme dans cet exemple. - - .. negative:: - - .. code-block:: c - - - sem_t * semaphore; - long global=0; - - int increment(int i) { - // ... - } - - void *inc(void * param) { - for(int j=0;j<1000000;j++) { - sem_post(semaphore); - global=increment(global); - sem_wait(semaphore); - } - } - - int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - semaphore=(sem_t *)malloc(sizeof(sem_t)) - if(semaphore==NULL) - error("malloc"); - - sem_init(semaphore, 0,0); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&inc,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - // reste non fourni - } - - .. comment:: - - Pour résoudre un problème d'exclusion mutuelle, il faut initialiser le sémaphore à ``1`` avec `sem_init(3)`_ et non à ``0`` comme dans cet exemple. En outre, l'accès à la section critique doit être précédée par un appel à `sem_wait(3)`_ et suivie par un appel à `sem_post(3)`_ et non l'inverse comme dans cet exemple. - - - -Question 3. Fonctions 'thread-safe' ------------------------------------ - -.. question:: threadsafe - :nb_prop: 3 - :nb_pos: 1 - - La plupart des fonctions de la librairie standard sont des fonctions thread-safe, c'est-à -dire des fonctions que l'on peut utiliser dans plusieurs threads distincts sans risquer de problèmes d'accès concurrent. Cependant, certaines fonctions, souvent parmi les plus anciennes, ne sont pas thread-safe. Parmi les fonctions ci-dessous, une seule est thread-safe. Laquelle ? - - .. positive:: - - `gettimeofday(2)`_ - - .. comment:: - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - - .. positive:: - - `strsep(3)`_ - - .. comment:: - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - - .. negative:: - - `getenv(3)`_ - - .. comment:: - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - - .. negative:: - - `getopt(3)`_ - - .. comment:: - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - - .. negative:: - - `asctime(3)`_ - - .. comment:: - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - - .. negative:: - - `strtok(3)`_ - - .. comment:: - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - - .. negative:: - - `strerror(3)`_ - - .. comment:: - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - - .. negative:: - - `getopt(3)`_ - - .. comment:: - - Les fonctions qui ne sont pas thread-safe sont listées dans `pthreads(7)`_. - - diff --git a/Exercices/mcq-ex/qcm-8.rst b/Exercices/mcq-ex/qcm-8.rst deleted file mode 100644 index c0eb19846a866bab4529a0e7ca67b15caf699200..0000000000000000000000000000000000000000 --- a/Exercices/mcq-ex/qcm-8.rst +++ /dev/null @@ -1,488 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - - - - -Questions à choix multiples -=========================== - -:task_id: sinf1252-8 - -La matière couverte cette semaine couvre les processus. - - - `Les processus <http://sites.uclouvain.be/SystInfo/notes/Theorie/html/Threads/processus.html>`_ - -Question 1. `fork(2)`_ ------------------------ - -L'appel système `fork(2)`_ permet de créer une copie du processus courant. Un étudiant a écrit le fragment de code ci-dessous se trouvant dans la fonction ``main``: - -.. code-block:: c - - int n=... - for(int i=0; i<n ; i++) { - printf("i=%d\n",i); - pid_t pid; - pid=fork(); - if (pid==-1) { - perror("fork"); - exit(EXIT_FAILURE); - } - else { - if(pid!=0) { - printf("Running in %d\n",pid); - } - } - } - return(EXIT_SUCCESS); - -.. question:: fork - :nb_prop: 3 - :nb_pos: 1 - - Lors de l'exécution de ce programme, combien de processus sont créés en fonction de la valeur de ``n`` ? - - .. positive:: - - Lorsque ``n`` est initialisé à ``2``, quatre processus sont créés. - - .. comment:: - - Le premier processus démarre son exécution. Il exécute `fork(2)`_. Un nouveau processus est donc créé. Ces deux processus exécutent à leur tour `fork(2)`_ et deux processus supplémentaires sont donc créés. - - .. positive:: - - Lorsque ``n`` est initialisé à ``3``, huit processus sont créés. - - .. comment:: - - Le premier processus démarre son exécution. Il exécute `fork(2)`_. Un nouveau processus est donc créé. Ces deux processus exécutent à leur tour `fork(2)`_ et deux processus supplémentaires sont donc créés. Chacun de ces quatre processus exécute à son tour `fork(2)`_ et il y a donc huit processus au total. - - .. negative:: - - Lorsque ``n`` est initialisé à ``2``, deux processus sont créés. - - .. comment:: - - Le premier processus démarre son exécution. Il exécute `fork(2)`_. Un nouveau processus est donc créé. Chacun de ces deux processus poursuit son exécution et la valeur de ``i`` est incrémentée. - - .. negative:: - - Lorsque ``n`` est initialisé à ``2``, trois processus sont créés. - - .. comment:: - - Le premier processus démarre son exécution. Il exécute `fork(2)`_. Un nouveau processus est donc créé. Chacun de ces deux processus poursuit son exécution et la valeur de ``i`` est incrémentée. - - .. negative:: - - Lorsque ``n`` est initialisé à ``3``, trois processus sont créés. - - .. comment:: - - Le premier processus démarre son exécution. Il exécute `fork(2)`_. Un nouveau processus est donc créé. Chacun de ces deux processus poursuit son exécution et la valeur de ``i`` est incrémentée. - - .. negative:: - - Lorsque ``n`` est initialisé à ``3``, quatre processus sont créés. - - .. comment:: - - Le premier processus démarre son exécution. Il exécute `fork(2)`_. Un nouveau processus est donc créé. Chacun de ces deux processus poursuit son exécution et la valeur de ``i`` est incrémentée. - -Question 2. `execve(2)`_ ------------------------- - -.. question:: execve - :nb_prop: 3 - :nb_pos: 1 - - Parmi les extraits de programme ci-dessous, lequel est un appel correct à `execve(2)`_ pour lancer le programme ``/bin/echo`` avec comme arguments ``-n`` et ``SINF1252`` ? - - .. positive:: - - - .. code-block:: c - - char *arguments[]={"echo", "-n", "SINF1252", NULL}; - char *environnement[]={"LANG=fr",NULL}; - int err=execve("/bin/echo", arguments, environnement); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - - .. positive:: - - .. code-block:: c - - - char prog[]="echo"; - char param1[]="-n"; - char param2[]="SINF1252"; - char *arguments[4]; - arguments[0]=prog; - arguments[1]=param1; - arguments[2]=param2; - arguments[3]=NULL; - char *environnement[]={"LANG=fr", NULL}; - int err=execve("/bin/echo", arguments, environnement); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - - - .. negative:: - - - .. code-block:: c - - char arguments[]={"echo", "-n", "SINF1252", NULL}; - char environnement[]={"LANG=fr",NULL}; - int err=execve("/bin/echo", arguments, environnement); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - - - .. comment:: - - Les deuxième et troisième arguments à `execve(2)`_ doivent être de type ``char *arg[]``. - - .. negative:: - - .. code-block:: c - - - char prog[]="echo"; - char param1[]="-n"; - char param2[]="SINF1252"; - char *arguments[4]; - arguments[0]=prog; - arguments[1]=param1; - arguments[2]=param2; - arguments[3]=NULL; - char *environnement[]={"LANG=fr"}; - int err=execve("/bin/echo", arguments, environnement); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - - .. comment:: - - Les deuxième et troisième arguments à `execve(2)`_ doivent être de type ``char *arg[]``. - - .. negative:: - - .. code-block:: c - - - char prog[]="echo"; - char param1[]="-n"; - char param2[]="SINF1252"; - char *arguments[3]; - arguments[0]=prog; - arguments[1]=param1; - arguments[2]=param2; - char *environnement[]={"LANG=fr"}; - int err=execve("/bin/echo", arguments, environnement); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - - .. comment:: - - Le dernier élément des tableaux de pointeurs ``argv` et ``environnement`` doivent obligatoirement contenir ``NULL``. Sans cela, il n'est pas possible de déterminer le nombre d'éléments dans ces tableaux. - - .. negative:: - - .. code-block:: c - - char *arguments[]={"echo", "-n", "SINF1252"}; - char *environnement[]={"LANG=fr"}; - int err=execve("/bin/echo", arguments, environnement); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - - .. comment:: - - Le dernier élément des tableaux de pointeurs ``argv` et ``environnement`` doivent obligatoirement contenir ``NULL``. Sans cela, il n'est pas possible de déterminer le nombre d'éléments dans ces tableaux. - - -Question 3. `execve(2)`_ ------------------------- - -.. question:: execve2 - :nb_prop: 3 - :nb_pos: 1 - - L'appel système `execve(2)`_ permet d'exécuter un programme en remplaçant le programme en cours d'exécution par celui se trouvant sur disque dont le nom est spécifié. Un étudiant a écrit le programme ci-dessous pour tester `execve(2)`_ : - - .. code-block:: c - - #include <stdio.h> - #include <stdlib.h> - #include <unistd.h> - - extern char **environ; - - int main (int argc, char *argv[]) { - - int n=... - int i=0; - for(i=0;i<n;i++) { - sleep(1); - printf("%d\n",i); - int err=execve(argv[0], argv, environ); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - } - return(EXIT_SUCCESS); - } - - .. positive:: - - Lorsque ``n`` est initialisé à ``3``, le programme ne s'arrête jamais et affiche : - - .. code-block:: console - - 0 - 0 - 0 - ... - - .. comment:: - - Lors de l'exécution de `execve(2)`_, le programme est remplacé par lui-même puisque ``argv[0]`` contient toujours le nom de l'exécutable qui est en train d'être exécuté. Ce programme redémarre son exécution au début de la fonction ``main``... - - .. positive:: - - Lorsque ``n`` est initialisé à ``2``, le programme ne s'arrête jamais et affiche : - - .. code-block:: console - - 0 - 0 - 0 - ... - - - .. comment:: - - Lors de l'exécution de `execve(2)`_, le programme est remplacé par lui-même puisque ``argv[0]`` contient toujours le nom de l'exécutable qui est en train d'être exécuté. Ce programme redémarre son exécution au début de la fonction ``main``... - - - - .. negative:: - - Lorsque ``n`` est initialisé à ``3``, le programme affiche : - - .. code-block:: console - - 0 - 1 - 2 - - - .. comment:: - - Lors de l'exécution de `execve(2)`_, le programme est remplacé par lui-même puisque ``argv[0]`` contient toujours le nom de l'exécutable qui est en train d'être exécuté. Ce programme redémarre son exécution au début de la fonction ``main``... - - .. negative:: - - Lorsque ``n`` est initialisé à ``2``, le programme affiche : - - .. code-block:: console - - 0 - 1 - - - .. comment:: - - Lors de l'exécution de `execve(2)`_, le programme est remplacé par lui-même puisque ``argv[0]`` contient toujours le nom de l'exécutable qui est en train d'être exécuté. Ce programme redémarre son exécution au début de la fonction ``main``... - - .. negative:: - - Lorsque ``n`` est initialisé à ``2``, l'appel à `execve(2)`_ est erroné et le programme s'arrête. - - .. comment:: - - L'appel à `execve(2)`_ est tout à fait correct, même si il n'est pas recommandé d'utiliser `execve(2)`_ de cette façon... - - .. negative:: - - - Lorsque ``n`` est initialisé à ``3``, l'appel à `execve(2)`_ est erroné et le programme s'arrête. - - .. comment:: - - L'appel à `execve(2)`_ est tout à fait correct, même si il n'est pas recommandé d'utiliser `execve(2)`_ de cette façon... - - - -Question 4. Utilisation de `waitpid(2)`_ ----------------------------------------- - -.. question:: waitpid - :nb_prop: 3 - :nb_pos: 1 - - L'appel système `waitpid(2)`_ permet à un processus d'attendre les valeurs de retour de ses processus fils. Un étudiant a écrit un programme qui lance de nombreux processus et veut faire une boucle qui permet de récupérer tous les processus fils qu'il a créé. Parmi les fragments de code ci-dessous, un seul est correct. Lequel ? - - - .. positive:: - - - - .. code-block:: c - - - int fils; - int done=false; - while(!done) { - int status; - fils=waitpid(0,&status,0); - if( (fils==-1) && (errno==ECHILD) ) - done=true; - } - - .. positive:: - - .. code-block:: c - - - int fils; - int done=false; - while(!done) { - int status; - if( (waitpid(0,&status,0)==-1) && (errno==ECHILD) ) - done=true; - } - - - - .. negative:: - - - .. code-block:: c - - - int fils; - int done=false; - int status; - while(waitpid(0,status,0)!=0) { - if( (fils==-1) && (errno==ECHILD) ) - done=true; - } - - - .. comment:: - - Le second argument de `waitpid(2)`_ est un pointeur vers un entier et non un entier. - - .. negative:: - - - .. code-block:: c - - - int fils; - int done=false; - while(!done) { - int status; - fils=waitpid(getpid(),&status,0); - if( (fils==-1) && (errno==ECHILD) ) - done=true; - } - - .. comment:: - - Lorsque le premier argument de `waitpid(2)`_ est un entier positif, il s'agit de l'identifiant du processus pour lequel `waitpid(2)`_ attend. Dans ce cas, `getpid(2)`_ retourne l'identifiant du processus qui existe `waitpid(2)`_ et un processus ne peut pas être un fils de lui-même. - -Question 5. Récupération du résultat d'un processus avec `waitpid(2)`_ ----------------------------------------------------------------------- - -.. question:: waitpid2 - :nb_prop: 3 - :nb_pos: 1 - - Un étudiant souhaite récupérer le résultat du processus ``pid`` qu'il a créé en faisant `fork(2)`_ et l'afficher sur ``stdout``. Parmi les fragments de programmes ci-dessous, un seul est correct. Lequel ? - - .. positive:: - - - .. code-block:: c - - int status; - int p=waitpid(pid,&status,0); - if(p==-1) { - perror("wait"); - exit(EXIT_FAILURE); - } - if(WIFEXITED(status)) { - printf("Le processus a retourne %d\n",WEXITSTATUS(status)); - } - - - .. negative:: - - - .. code-block:: c - - int status; - int p=waitpid(pid,status,0); - if(p==-1) { - perror("wait"); - exit(EXIT_FAILURE); - } - printf("Le processus a retourne %d\n",WEXITSTATUS(status)); - - .. comment:: - - L'appel système `waitpid(2)`_ prend comme second argument un pointeur vers un ``int`` et non un `ìnt``. - - .. negative:: - - - .. code-block:: c - - int status; - int p=waitpid(pid,&status,0); - if(p==-1) { - perror("wait"); - exit(EXIT_FAILURE); - } - printf("Le processus a retourne %d\n",p); - - .. comment:: - - La valeur de retour de `waitpid(2)`_ indique si l'appel système s'est exécuté correctement ou non. Pour récupérer le statut du processus fils ``pid``, il faut utiliser la macro ``WEXITSTATUS``. - - .. negative:: - - .. code-block:: c - - int *status; - int p=waitpid(pid,status,0); - if(p==-1) { - perror("wait"); - exit(EXIT_FAILURE); - } - printf("Le processus a retourne %d\n",p); - - .. comment:: - - La valeur de retour de `waitpid(2)`_ indique si l'appel système s'est exécuté correctement ou non. Pour récupérer le statut du processus fils ``pid``, il faut utiliser la macro ``WEXITSTATUS``. Le pointeur ``int * status`` doit pointer vers une zone mémoire allouée par malloc. Ici, il pointe vers ``NULL``. - diff --git a/Exercices/mcq-ex/qcm-9.rst b/Exercices/mcq-ex/qcm-9.rst deleted file mode 100644 index c6ccfa12d1d03ffd564404bb392a014f4c71d6c5..0000000000000000000000000000000000000000 --- a/Exercices/mcq-ex/qcm-9.rst +++ /dev/null @@ -1,534 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -Questions à choix multiples -=========================== - -:task_id: sinf1252-9 - -La matière couverte cette semaine porte sur le système de fichiers et sa manipulation par les processus. - -Question 1. Accès aux fichiers ------------------------------- - -Les bits de permissions permet de contrôler l'accès aux fichiers. Considérons le répertoire ci-dessous : - -.. code-block:: console - - -rw-r--r-- 1 obo obo 0 23 mar 21:57 a - -r-xr-x--x 1 obo obo 0 23 mar 21:57 b - -rw------- 1 obo obo 0 23 mar 21:57 c - -rw------x 1 obo obo 0 23 mar 21:57 d - --w-----w- 1 obo obo 0 23 mar 21:57 e - - -.. question:: fileperm - :nb_prop: 3 - :nb_pos: 1 - - Un seul des groupes d'affirmations ci-dessous est vrai. Lequel ? - - .. positive:: - - - l'utilisateur ``obo`` peut lire le fichier ``c``, exécuter le fichier ``b`` et modifier le contenu du fichier ``d`` - - - .. positive:: - - l'utilisateur ``obo`` peut lire le fichier ``a``, exécuter le fichier ``b`` et modifier le contenu du fichier ``c`` - - - .. negative:: - - l'utilisateur ``obo`` peut lire le fichier ``e``, exécuter le fichier ``b`` et modifier le contenu du fichier ``e`` - - .. comment:: - - Le fichier ``e`` n'est pas lisible par cet utilisateur. - - .. negative:: - - l'utilisateur ``obo`` peut lire le fichier ``c``, exécuter le fichier ``d`` et modifier le contenu du fichier ``b`` - - .. comment:: - - Le fichier ``b`` n'est pas modifiable par cet utilisateur. - - .. negative:: - - l'utilisateur ``obo`` peut lire le fichier ``c``, exécuter le fichier ``a`` et modifier le contenu du fichier ``d`` - - .. comment:: - - Le fichier ``a`` n'est pas exécutable par cet utilisateur. - - -Question 2. Fichiers et répertoires ------------------------------------ - -Les permissions associées aux répertoires ont un rôle un peu différent de celles qui sont associées aux fichiers. Considérons le répertoire ci-dessous qui contient 4 sous-répertoires. - -.. code-block:: console - - drw------- 2 obo obo 68 23 mar 22:25 a - dr-x------ 2 obo obo 68 23 mar 22:25 b - d-wx------ 3 obo obo 102 23 mar 22:27 c - drwx------ 3 obo obo 102 23 mar 22:26 d - -Chacun de ces répertoires contient un fichier qui a comme nom ``f``. La commande `touch(1)`_ peut être utilisée pour créer un fichier vide. Ainsi, dans ce répertoire, la commande ``touch f`` va créer le fichier ``f`` - -.. code-block:: console - - ls -l f - -rw-r--r-- 1 obo obo 0 23 mar 22:30 f - -.. question:: touch - :nb_prop: 3 - :nb_pos: 1 - - - Dans le répertoire ci-dessus, une seule séquence de commandes fonctionne sans erreur. Laquelle ? - - .. positive:: - - .. code-block:: console - - ls -l d - touch c/x - cd b - - .. positive:: - - .. code-block:: console - - ls -l b - cat c/f - cd d - - - .. negative:: - - - .. code-block:: console - - ls -l c - touch d/x - cd a - - .. comment:: - - Il n'est pas possible d'aller dans le répertoire ``a``. En outre, le contenu du répertoire ``c`` ne peut pas être lu avec `ls(1)`_ - - .. negative:: - - - .. code-block:: console - - ls -l c - touch a/x - cd c - - .. comment:: - - Il n'est pas possible de créer un fichier dans le répertoire ``a``. - - .. negative:: - - .. code-block:: console - - ls -l b - touch b/x - cd b - - .. comment:: - - Il n'est pas possible de créer un fichier dans le répertoire ``b``. - - - -Question 3. Permissions sur les fichiers ----------------------------------------- - -.. question:: chmod - :nb_prop: 3 - :nb_pos: 1 - - La page de manuel de `chmod(1posix)`_ décrit en détails les permissions relatives aux fichiers et répertoires. Ces permissions peuvent être représentées sous une forme numérique ou textuelle. Parmi les affirmations suivantes, relatives à des permissions pour des `fichiers`, un seul groupe est vrai. Lequel ? - - - .. positive:: - - - - Le fichier ayant ``00467`` comme permissions est exécutable par n'importe quel utilisateur - - Le fichier ayant ``00777`` comme permissions est lisible par son propriétaire - - Le fichier ayant ``00600`` ne peut être lu que par son propriétaire - - .. positive:: - - - Le fichier ayant ``00647`` comme permissions est exécutable par n'importe quel utilisateur - - Le fichier ayant ``00700`` comme permissions est lisible par son propriétaire - - Le fichier ayant ``00421`` comme permissions ne peut être lu que par son propriétaire - - .. negative:: - - - - Le fichier ayant ``00476`` comme permissions est exécutable par n'importe quel utilisateur - - Le fichier ayant ``00747`` comme permissions est lisible par son propriétaire - - Le fichier ayant ``00601`` comme permissions ne peut être lu que par son propriétaire - - .. comment:: - - Le fichier ayant ``00476`` comme permissions ne peut être exécuté que par un membre du groupe correspondant à ce fichier. - - .. negative:: - - - Le fichier ayant ``00677`` comme permissions est exécutable par n'importe quel utilisateur - - Le fichier ayant ``00017`` comme permissions est lisible par son propriétaire - - Le fichier ayant ``00400`` comme permissions ne peut être lu que par son propriétaire - - .. comment:: - - Le fichier ayant ``00017`` comme permissions n'est pas lisible par son propriétaire - - .. negative:: - - - - Le fichier ayant ``00755`` comme permissions est exécutable par n'importe quel utilisateur - - Le fichier ayant ``00417`` comme permissions est lisible par son propriétaire - - Le fichier ayant ``00222`` comme permissions ne peut être lu que par son propriétaire - - .. comment:: - - Le fichier ayant ``00222`` comme permissions n'est pas lisible par son propriétaire - - .. negative:: - - - - Le fichier ayant ``00666`` comme permissions est exécutable par n'importe quel utilisateur - - Le fichier ayant ``00400`` comme permissions est modificale par son propriétaire - - Le fichier ayant ``00400`` comme permissions ne peut être lu que par son propriétaire - - .. comment:: - - Le fichier ayant ``00666`` comme permissions n'est pas exécutable - - -Question 4. Permissions sur les fichiers ----------------------------------------- - -Les bits de permissions associés à un fichiers sont généralement représentés sous forme textuelle lorsque la commande `ls(1)`_ affiche le contenu d'un répertoire. Considérons le répertoire ci-dessous : - - .. code-block:: console - - -rw-r--r-- 1 obo obo 0 23 mar 21:57 a - -rwxr-x--x 1 obo obo 0 23 mar 21:57 b - -rw------- 1 obo obo 0 23 mar 21:57 c - -rw------x 1 obo obo 0 23 mar 21:57 d - --w-r--rw- 1 obo obo 0 23 mar 21:57 e - -.. question:: chmod2 - :nb_prop: 3 - :nb_pos: 1 - - Parmi les commandes suivantes, un seul groupe permet d'obtenir les mêmes permissions que ci-dessous. Lequel ? - - .. positive:: - - - .. code-block:: console - - chmod 644 a - chmod 751 b - chmod 600 c - chmod 601 d - chmod 246 e - - .. negative:: - - - .. code-block:: console - - chmod 446 a - chmod 157 b - chmod 006 c - chmod 106 d - chmod 642 e - - .. comment:: - - Relisez la page de manuel de `chmod(1)`_ - - .. negative:: - - .. code-block:: console - - chmod 444 a - chmod 751 b - chmod 600 c - chmod 604 d - chmod 123 e - - .. comment:: - - Relisez la page de manuel de `chmod(1)`_ - - .. negative:: - - .. code-block:: console - - chmod 322 a - chmod 364 b - chmod 300 c - chmod 301 d - chmod 123 e - - .. comment:: - - Relisez la page de manuel de `chmod(1)`_ - - -Question 5. Système de fichiers -------------------------------- - -.. question:: inodes - :nb_prop: 3 - :nb_pos: 1 - - - Le système de fichiers Unix utilise des `inode` pour stocker les meta-données relatives à un fichier/répertoire. Parmi les groupes d'affirmations suivants, un seul est correct. Lequel ? - - .. positive:: - - - - deux fichiers se trouvant dans des répertoires différents sur le même disque peuvent avoir le même `inode` - - le champ ``nlinks`` est toujours positif - - un accès au fichier modifie le ``atime`` associé à ce fichier - - - .. negative:: - - - - deux fichiers ont toujours des `inode` différents - - l'`inode` contient le nom du fichier - - une écriture dans un fichier modifie le ``mtime`` associé à ce fichier - - .. comment:: - - Les deux premières affirmations sont fausses. - - - .. negative:: - - - un fichier et un répertoire se trouvant sur le même disque peuvent avoir le même `inode` - - une lecture dans un fichier modifie le ``mtime`` associé à ce fichier - - l'`inode` contient le nom du fichier - - .. comment:: - - Toutes les affirmations sont fausses. - - .. negative:: - - - une copie d'un fichier incrémente la valeur du champ ``nlinks`` de son `inode` - - une lecture dans un fichier modifie le ``atime`` associé à ce fichier - - il n'y a jamais deux fichiers qui ont le même `inode` - - .. comment:: - - La première et la troisième affirmation sont fausses. - -Question 6. Manipulation des répertoires ----------------------------------------- - -Les répertoires sont des fichiers spéciaux. Pour les utiliser, il faut faire appel aux fonctions `opendir(3)`_, `readdir(3)`_ et `closedir(3)`_. - -.. code-block:: c - - /* - * name!=NULL - * retourne le nombre de fichiers dans le répertoire name - * et -1 en cas d'erreur - */ - -.. question:: fileperm - :nb_prop: 3 - :nb_pos: 1 - - Parmi les séquences d'instructions ci-dessous, laquelle permet de compter le nombre de fichiers se trouvant dans le répertoire courant ? - - .. positive:: - - - .. code-block:: c - - int nfiles(char * name) { - - DIR *dirp; - struct dirent *dp; - dp=malloc(sizeof(struct dirent)); - if(dp==NULL) { - return -1; - } - dirp = opendir(name); - if(dirp==NULL) { - return -1; - } - int count=0; - while ((dp = readdir(dirp)) != NULL) { - if (dp->d_type==DT_REG) { - count++; - } - } - int err = closedir(dirp); - if(err<0) { - return -1; - } - return(count); - } - - .. negative:: - - - .. code-block:: c - - int nfiles(char * name) { - - DIR *dirp; - struct dirent *dp; - dirp = opendir(name); - if(dirp==NULL) { - return -1; - } - int count=0; - while (readdir(dirp) != NULL) { - count++; - } - int err = closedir(dirp); - if(err<0) { - return -1; - } - return(count); - } - - .. comment:: - - Ce code compte toutes les entrées dans le répertoire et pas seulement le fichiers. - - .. negative:: - - .. code-block:: c - - int nfiles2(char * name) { - - DIR dirp; - struct dirent dp; - dirp = opendir(name); - if(dirp==-1) { - return -1; - } - int count=0; - while ((dp = readdir(dirp)) != -1) { - count++; - } - - int err = closedir(dirp); - if(err<0) { - return -1; - } - return(count); - } - - .. comment:: - - Ce code est erroné. `opendir(3)`_ retourne un pointeur et `readdir(3)`_ également. - - .. negative:: - - .. code-block:: c - - int nfiles(char * name) { - - DIR dirp; - struct dirent dp; - dirp = opendir(name); - int count=0; - while ((dp = readdir(dirp)) != NULL) { - if (dp->d_type==DT_REG) { - count++; - } - } - int err = closedir(dirp); - if(err<0) { - return -1; - } - return(count); - } - - .. comment:: - - Ce code est erroné. `opendir(3)`_ retourne un pointeur et `readdir(3)`_ également. - - -Question 7. Liens symboliques ------------------------------ - -Considérons un répertoire dans lequel les commandes suivantes sont exécutées : - -.. code-block:: console - - touch a - cp a b - ln a c - ln b d - echo "test" > c - ln -s d e - echo essai > e - - -.. question:: liens - :nb_prop: 3 - :nb_pos: 1 - - Après exécution de ces commandes, un seul des groupes d'affirmations suivant est correct. Lequel ? - - .. positive:: - - - - les fichiers ``a`` et ``c`` ont le même `inode` - - les fichiers ``b`` et ``d`` ont la même taille - - l'`inode` correspondant au fichier ``d`` indique qu'il y a deux liens vers lui - - .. positive:: - - - - les fichiers ``d`` et ``e`` ont des `inode` différents - - les fichiers ``a`` et ``c`` ont la même taille - - l'`inode` correspondant au fichier ``b`` indique qu'il y a deux liens vers lui - - - .. negative:: - - - - les fichiers ``a`` et ``c`` ont des `inode` différents - - les fichiers ``e`` et ``d`` ont la même taille - - l'`inode` correspondant au fichier ``d`` indique qu'il y a trois liens vers lui - - .. negative:: - - - les fichiers ``a`` et ``d`` ont des `inode` différents - - les fichiers ``b`` et ``d`` ont la même taille - - l'`inode` correspondant au fichier ``b`` indique qu'il y a trois liens vers lui - - .. comment:: - - Il y a deux liens (hard) vers le fichier ``b``. Le fichier ``e`` est un lien symbolique vers ce fichier et non un lien `hard`. - - .. negative:: - - - les fichiers ``b``, ``d`` et ``e`` ont le même `inode` - - les fichiers ``a`` et ``c`` ont la même taille - - l'`inode` correspondant au fichier ``a`` indique qu'il y a deux liens vers lui - diff --git a/Exercices/mcq-ex/revision.rst.old b/Exercices/mcq-ex/revision.rst.old deleted file mode 100644 index ba8cb2364174c6f4af040b43326c0cb3b62a4c8d..0000000000000000000000000000000000000000 --- a/Exercices/mcq-ex/revision.rst.old +++ /dev/null @@ -1,118 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -.. Les lignes qui commencent par .. sont des commentaires ou des commandes restructuredtext. Celle-ci est un commentaire - -.. Si vous proposez une ou des questions, mettez à jour l'information ci-dessous - -.. sectionauthor:: Jean Tartempion <email> - -Questions à choix multiples -=========================== - -.. La ligne ci-dessous identifie le numéro du groupe de question et ne devrait pas être modifiée - -:task_id: sinf1252-revision - -.. Toute question a un titre - -Question 1. Conversion de types -------------------------------- - -.. Si votre question comprend plusieurs paragraphe d'introduction, placez ces paragraphes avant de définir la question. Commencez votre paragraphe en première colonne pour éviter toute surprise avec les indentations. - -En C tout comme dans des langages comme Java, il est possible de convertir des nombres d'un type primitif vers un autre. Cependant, alors que le compilateur Java vérifie si la conversion est sans risque, le compilateur C ne fait aucune vérification et suppose que si le programmeur a effectué une conversion explicite entre types, il a pris ses précautions. Sur une architecture où les types de données sont stockés comme suit : - -.. Ceci est un exemple de code-source en C. Notez que le code est aligné sur la quatrième colonne comme le caractère c - -.. code-block:: c - - // char 1 octet(s) - // unsigned char 1 octet(s) - // short 2 octet(s) - // unsigned short 2 octet(s) - // int 4 octet(s) - // unsigned int 4 octet(s) - - int i; - short s; - long l; - char c; - unsigned int ui; - unsigned char uc; - unsigned long ul; - unsigned short us; - -.. Cette directive définit la question à choix multiples. Elle a un identifiant que vous devez choisir et qui doit être unique. Deux paramètres sont définis : nb_prop est le nombre de propositions qui sont présentées par le javascript (3 est un minimum, mais vous pouvez en proposer plus). nb_pos est le nombre de propositions positives qui sont présentées par le javascript. Si nb_pos > 1, alors la formulation de votre question doit demander à l'étudiant de sélectionner toutes les réponses correctes. - -.. Une question doit nécessairement contenir un paragraphe de texte. Sinon, la compilation échouera. Pensez à aligner le paragraphe contenant la question en quatrième colonne - -.. question:: revision-conversiontypes - :nb_prop: 3 - :nb_pos: 1 - - Un seul des fragments de code ci-dessous contient des conversions de type qui sont sans risque. Lequel ? - - .. positive:: - - .. code-block:: c - - i=(int ) s; - s=(short) uc; - l=(long )i; - -.. la directive positive permet de spécifier une réponse positive. Celle-ci peut contenir un paragraphe ou une autre directive restructured text (dans cet exemple du code). Pensez à aligner le contenu de la directive positive sur la huitième colonne pour éviter tout problème d'indentation. - -.. une deuxième réponse positive qui est aussi correcte. - - .. positive:: - - .. code-block:: c - - ui=(unsigned int) us; - s=(short) c; - ul=(unsigned long )ui; - -.. une première réponse négative. Notez que le commentaire permet à l'étudiant d'apprendre de ses erreurs. Celui-ci est tout aussi important que la réponse négative qui est proposée. Veillez à respecter l'alignement de la directive comment sur la huitième colonne (caractère n de negative) - - .. negative:: - - .. code-block:: c - - ui=(unsigned int ) s; - us=(unsigned short) uc; - l=(long )i; - - .. comment:: Si ``s`` est négatif, la conversion en ``unsigned int`` risque de poser problème. - -.. Dans l'exemple ci-dessous, le commentaire contient un paragraphe complet. Son indentation est alignée sur la onzième colonne. - - .. negative:: - - .. code-block:: c - - i=(int ) us; - us=(unsigned short) i; - l=(long )c; - - .. comment:: - - La conversion d'un ``int`` en un ``unsigned short`` risque de poser problème. - - .. negative:: - - .. code-block:: c - - ui=(int) s; - s=(short) c; - ul=(unsigned long )ui; - - .. comment:: La première conversion risque de poser des problèmes. - - -.. Ces include vous permettent de charger les liens vers les pages de manuel et les fichiers include standard de Linux auxquels vos commentaires et vos questions peuvent bien entendu faire appel - -.. include:: ../links.rst -.. include:: ../man_links.rst -.. include:: ../incl_links.rst diff --git a/Exercices/mcq/mcq.py b/Exercices/mcq/mcq.py deleted file mode 100644 index 7c25c416dc1b77471940d38242fdd2cc7a2cc8b1..0000000000000000000000000000000000000000 --- a/Exercices/mcq/mcq.py +++ /dev/null @@ -1,414 +0,0 @@ -# -*- coding: utf-8 -*- -# Extension by Lionel Chalet - -from docutils import nodes -from docutils.parsers.rst import Directive -from sphinx.errors import SphinxError -import os, sys, copy, hashlib, random - -__version__ = '0.1' - -question_number = 0 -alternative_number = 0 -language = 'en' - -translations = { - 'fr': { - 'verify_title': u'Verifiez vos réponses', - 'verify': u'Vérifier' - }, - 'en': { - 'verify_title': 'Verify your answers', - 'verify': 'Verify' - } -} - -def setup(app): - app.add_config_value('mcq_nb_prop', -1, '') - app.add_config_value('mcq_nb_rows', 7, '') - app.add_config_value('mcq_upload_url', '', '') - app.add_config_value('mcq_inginious_url', '', '') - - app.add_node(Question, html=(html_visit_question, html_depart), latex=(latex_visit_question, pass_visit)) - app.add_node(Query, html=(html_visit_query, html_depart), latex=(pass_visit, pass_visit)) - app.add_node(Positive, html=(html_visit_positive, html_depart_alternative), latex=(latex_visit_posneg, latex_depart_posneg)) - app.add_node(Negative, html=(html_visit_negative, html_depart_alternative), latex=(latex_visit_posneg, latex_depart_posneg)) - app.add_node(Textbox, html=(html_visit_textbox, html_depart), latex=(latex_visit_textbox, None)) - app.add_node(Comment, html=(html_visit_comment, html_depart), latex=(skip_visit, None)) - - app.add_directive('question', QuestionDirective) - app.add_directive('positive', PositiveDirective) - app.add_directive('negative', NegativeDirective) - app.add_directive('textbox', TextboxDirective) - app.add_directive('comment', CommentDirective) - - app.connect('builder-inited', add_dependencies) - app.connect('doctree-resolved', verify_structure) - app.connect('doctree-resolved', html_add_content) - app.connect('doctree-resolved', latex_add_content) - app.connect('doctree-resolved', latex_shuffle) - app.connect('doctree-resolved', epub_add_javascript) - -class CopyableNode(nodes.General, nodes.Element): - def deepcopy(self): - """ - Nodes attributes aren't available with the LaTeX builder after the 'doctree-read' event - This is some kind of patch I suppose ... - """ - return copy.copy(self) - -class Question(CopyableNode): - id = None - nb_pos = 1 - nb_prop = -1 - -class Alternative(CopyableNode): - pass - -class Query(Alternative): - pass - -class Positive(Alternative): - pass - -class Negative(Alternative): - pass - -class Textbox(Alternative): - nb_rows = 7 - -class Comment(CopyableNode): - pass - -def html_visit_question(self, node): - global question_number, alternative_number - question_number += 1 - alternative_number = 0 - classes = 'question' - if not node.id: - node.id = 'questionId' + str(question_number) - else: - classes += ' inginious' - self.body.append(self.starttag(node, 'div', CLASS=classes, IDS=[str(node.id)])) - self.body.append("<input type='hidden' class='nb_pos' value='" + str(node.nb_pos) + "' />") - self.body.append("<input type='hidden' class='nb_prop' value='" + str(node.nb_prop) + "' />") - -def html_visit_query(self, node): - self.body.append(self.starttag(node, 'div', CLASS='query')) - -def html_visit_positive(self, node): - global alternative_number - self.body.append(self.starttag(node, 'div', CLASS='positive', IDS=[str(alternative_number)])) - html_visit_alternative(self, node) - alternative_number += 1 - -def html_visit_negative(self, node): - global alternative_number - self.body.append(self.starttag(node, 'div', CLASS='negative', IDS=[str(alternative_number)])) - html_visit_alternative(self, node) - alternative_number += 1 - -def html_visit_alternative(self, node): - if node.parent.nb_pos > 1: - self.body.append("<input type='checkbox' class='choice' name='" + str(question_number) + "' />") - else: - self.body.append("<input type='radio' class='choice' name='" + str(question_number) + "' />") - self.body.append(self.starttag(node, 'div', CLASS='content')) - -def html_visit_textbox(self, node): - self.body.append(self.starttag(node, 'div', CLASS='textbox')) - self.body.append('<textarea rows="' + str(node.nb_rows) + '" cols="65"></textarea>') - -def html_visit_comment(self, node): - self.body.append(self.starttag(node, 'div', CLASS='comment', STYLE='display:none')) - -def html_depart(self, node): - self.body.append('</div>') - -def html_depart_alternative(self, node): - for x in range(2): - html_depart(self, node) - -def skip_visit(self, node): - raise nodes.SkipNode - -def pass_visit(self, node): - pass - -def latex_visit_question(self, node): - pass - -def latex_visit_posneg(self, node): - latex_visit_posneg.count += 1 - self.body.append('\n\\needspace{3\\baselineskip}' - '\n\\CheckBox[name=' + str(latex_visit_posneg.count) + ',bordercolor=0 0 0]{}' - '\n\\vspace{-0.7cm}' - '\n\\begin{addmargin}[0.8cm]{0cm}') -latex_visit_posneg.count = 0 - -def latex_depart_posneg(self, node): - self.body.append('\\end{addmargin}\n') - -def latex_visit_textbox(self, node): - self.body.append('\n\TextFieldFill[multiline=true,height=' + str(node.nb_rows) + '\\baselineskip,bordercolor=0 0 0]{}') - raise nodes.SkipNode - -class BaseDirective(Directive): - has_content = True - - # This has to be replaced in subclasses - node_class = None - - def run(self): - node = self.node_class() - self.state.nested_parse(self.content, self.content_offset, node) - return [node] - -class QuestionDirective(BaseDirective): - optional_arguments = 1 - option_spec = { - 'nb_pos': int, - 'nb_prop': int - } - - node_class = Question - - def run(self): - node = super(QuestionDirective, self).run()[0] - if len(self.arguments) > 0: - node.id = self.arguments[0] - query = Query() - for child in node.children[:]: # Must make a copy to remove while iterating - if not isinstance(child, Alternative): - node.remove(child) - query += child - node.insert(0, query) - app = self.state.document.settings.env.app - node.nb_prop = app.config.mcq_nb_prop - for option, value in self.options.items(): - setattr(node, option, value) - validate_question_options(app, node) - return [node] - -class PositiveDirective(BaseDirective): - node_class = Positive - -class NegativeDirective(BaseDirective): - node_class = Negative - -class TextboxDirective(BaseDirective): - option_spec = { - 'nb_rows': int - } - - node_class = Textbox - - def run(self): - node = super(TextboxDirective, self).run() - app = self.state.document.settings.env.app - if 'nb_rows' in self.options: - node[0].nb_rows = validate_nb_rows(app, self.options['nb_rows']) - else: - node[0].nb_rows = validate_nb_rows(app, app.config.mcq_nb_rows) - return node - -class CommentDirective(BaseDirective): - node_class = Comment - -def add_dependencies(app): - global language - if app.config.language == 'fr': - language = 'fr' - - preamble = ('\\usepackage{scrextend}' - '\n\\usepackage{hyperref}' - '\n\\usepackage{needspace}' - '\n\n\\newlength\\TextFieldLength' - '\n\\newcommand\\TextFieldFill[2][]{%' - '\n\t\\setlength\\TextFieldLength{\\linewidth}%' - '\n\t\\settowidth{\\dimen0}{#2 }%' - '\n\t\\addtolength\\TextFieldLength{-\\dimen0}%' - '\n\t\\addtolength\\TextFieldLength{-2.22221pt}%' - '\n\t\\TextField[#1,width=\\TextFieldLength]{\\raisebox{2pt}{#2 }}%' - '\n}') - if 'preamble' in app.config.latex_elements: - app.config.latex_elements['preamble'] += '\n' + preamble - else: - app.config.latex_elements['preamble'] = preamble - - app.add_javascript('jquery-shuffle.js') - app.add_javascript('rst-form.js') - app.add_stylesheet('ext.css') - -def validate_question_options(app, node): - if node.nb_pos < 1: - app.warn('The number of positive answers to display must be greater than 0.') - node.nb_pos = 1 - if node.nb_prop < node.nb_pos: - app.warn('The number of propositions to display in a question ('+str(node.nb_prop)+') must be greater or equal than the number of positive answers ('+str(node.nb_pos)+') to display.') - nb_prop = app.config.mcq_nb_prop - if nb_prop < node.nb_pos: - node.nb_prop = sys.maxint - else: - node.nb_prop = nb_prop - if node.nb_prop == node.nb_pos: - app.warn('The number of positive answers shouldn\'t be the same as the number of propositions. It\'s like giving the answer.') - -def validate_nb_rows(app, nb_rows): - if nb_rows < 1: - app.warn('The number of rows in a textbox must be greater than 0.') - return 1 - return nb_rows - -class StructureError(SphinxError): - category = 'Wrong document structure' - -def verify_structure(app, doctree, docname): - verify_alternatives(app, doctree) - verify_comments(app, doctree) - verify_textbox(app, doctree) - verify_questions(app, doctree) - -def verify_alternatives(app, doctree): - for node in doctree.traverse(Alternative): - if type(node.parent) != Question: - raise StructureError('Every "positive", "negative" and "textbox" directives must be direct children to a "question" directive.') - if type(node) != Textbox and len(node.children) < 1: - raise StructureError('Every "question", "positive" and "negative" directives must have content.') - -def verify_comments(app, doctree): - for node in doctree.traverse(Comment): - parent_type = type(node.parent) - if len(parent_type.__bases__) < 1 or parent_type.__bases__[0] != Alternative: - raise StructureError('Every "comment" directive must be a direct child of a "question", "positive", "negative" or "textbox" directive.') - if len(node.children) < 1: - raise StructureError('Every "comment" directive must have content.') - if len(node.traverse(condition=Comment, descend=False, siblings=True)) > 1: - raise StructureError('A "comment" directive cannot have a "comment" directive sibling.') - -def verify_textbox(app, doctree): - for node in doctree.traverse(Textbox): - if len(node.children) > 1: - raise StructureError('A "textbox" directive can only contain one directive (of type "comment").') - -def verify_questions(app, doctree): - for node in doctree.traverse(Question): - if len(node.children) < 2: - raise StructureError('A question must have some content and (a "textbox" or at least one "positive" directive).') - if len(node.children[0].traverse(Question)) > 0: - raise StructureError('A question cannot contain another question, you fool!') - query_count, positive_count, negative_count, textbox_count = count_children(node) - if len(node.children) == 2: - if query_count != 1 or positive_count != 1 and textbox_count != 1: - raise StructureError('A "question" directive must have at least some content and (a "positive" or "textbox" directive).') - else: - if query_count != 1: - raise StructureError('Internal error. This should never happen. This is a huge bug in this program.') - if positive_count < 1: - raise StructureError('A "question" directive must contain at least one "positive" directive. (or only one "textbox" directive)') - if positive_count < node.nb_pos: - raise StructureError('A "question" directive must have at least the given number of "positive" directives children.') - if negative_count < 1: - app.warn('Not giving any negative proposition in a question is the same as giving the answer.') - -def count_children(node): - query_count, positive_count, negative_count, textbox_count = 0, 0, 0, 0 - for child in node.children: - child_type = type(child) - if len(child_type.__bases__) < 1 or child_type.__bases__[0] != Alternative: - raise StructureError('Internal error. This should never happen. This is a huge bug in this program.') - if child_type == Query: - query_count += 1 - elif child_type == Positive: - positive_count += 1 - elif child_type == Negative: - negative_count += 1 - else: - textbox_count += 1 - return query_count, positive_count, negative_count, textbox_count - -def html_add_content(app, doctree, docname): - field_list = doctree.next_node(nodes.field_list) - task_id = '' - if field_list: - for field in field_list.traverse(nodes.field): - field_name = field.next_node(nodes.field_name).astext() - if field_name == 'task_id': - task_id = field.next_node(nodes.field_body).astext() - field_list.parent.remove(field_list) - builder = app.builder - if not hasattr(builder, 'format') or builder.format != 'html': - return - h = hashlib.md5(str(doctree)).hexdigest() - title = '' - node = doctree - for t in doctree.traverse(nodes.title): - title = t.children[0].astext() - node = t.parent - break - section = nodes.section(ids=["checker"], name=["checker"]) - section += nodes.title(text=translations[language]['verify_title']) - text = u'<div id="results" style="display: none;"></div>' - if app.config.mcq_inginious_url and task_id: - text += '<input type="submit" value="' + translations[language]['verify'] + '" id="submit" />' - section += nodes.raw(format='html', text=text) - node += section - js = nodes.raw(format='html') - js += nodes.Text(u'\n<script type="text/javascript">var language = "' + unicode(language) + '";' - u' var upload_url = "' + unicode(app.config.mcq_upload_url) + '";' - u' var hash = "' + unicode(h) + '"; var title = "' + unicode(title) + '";' - u' var html_title = "' + unicode(app.config.html_title) + '";') - if app.config.mcq_inginious_url and task_id: - js += nodes.Text(u' var task_id = "' + unicode(task_id) + '"; var inginious_url = "' + unicode(app.config.mcq_inginious_url) + '";') - js += nodes.Text(u'</script>'); - doctree += js - -def latex_add_content(app, doctree, docname): - node_begin = nodes.raw(format='latex') - node_end = nodes.raw(format='latex') - node_begin += nodes.Text('\n\\begin{Form}') - node_end += nodes.Text('\n\\end{Form}') - doctree.insert(0, node_begin) - doctree.append(node_end) - - for q in doctree.traverse(Question): - q.parent.children.insert(0, nodes.raw(format='latex', text='\n\\needspace{6\\baselineskip}\n')) - -def latex_shuffle(app, doctree, docname): - builder = app.builder - if not hasattr(builder, 'format') or builder.format != 'latex': - return # The rest of this function is done in JS with the HTML writer - for q in doctree.traverse(Question): - query_node = None - pos_nodes = [] - neg_nodes = [] - textbox_node = None - for node in q.children: - node_type = type(node) - if node_type == Negative: - neg_nodes.append(node) - elif node_type == Positive: - pos_nodes.append(node) - elif node_type == Query: - query_node = node - else: - textbox_node = node - children = [] - random.shuffle(pos_nodes) - random.shuffle(neg_nodes) - children += pos_nodes[:q.nb_pos] - children += neg_nodes[:q.nb_prop - q.nb_pos] - random.shuffle(children) - children.insert(0, query_node) - if textbox_node: - children.append(textbox_node) - q.children = children - -def epub_add_javascript(app, doctree, docname): - builder = app.builder - if not hasattr(builder, 'name') or not builder.name.startswith('epub'): - return - # Current epub3 builders does not include .js files in the .epub - builder.media_types.update({'.js': 'text/javascript'}) - # The page.html template used does not include javascript if embedded - builder.globalcontext['embedded'] = False diff --git a/Exercices/mcq/static/ext.css b/Exercices/mcq/static/ext.css deleted file mode 100644 index 7f958cffaffafc37bb6d27703cd4f6f8beaf830f..0000000000000000000000000000000000000000 --- a/Exercices/mcq/static/ext.css +++ /dev/null @@ -1,72 +0,0 @@ -.query, .textbox textarea { - margin-bottom: 10px; -} - -div:not(.content) { - clear: both; -} - -.choice, .checkmark, .content { - position: relative; - margin-bottom: 10px; -} - -.choice, .content { - left: 55px; -} - -.choice { - margin-bottom: -20px; -} - -.content { - margin-left: 30px; - margin-right: 55px; -} - -.checkmark + .content { - margin-top: -20px; - min-height: 76px; -} - -.query + .checkmark { - left: 0px; -} - -.checkmark { - left: -20px; - margin-bottom: -56px; -} - -.textbox textarea { - width: 100%; -} - -.result { - display: inline; - margin-left: 30px; - font-weight: bold; -} - -#results p, p.problem { - padding: 20px; - border-bottom-left-radius: 10%; - border-bottom-right-radius: 10%; - color: white; -} - -#results .success { - background-color: #1a3511; -} - -#results .failed, p.problem { - background-color: #666666; -} - -#results .error { - background-color: #691414; -} - -#results .request-failed { - background-color: #320a73; -} diff --git a/Exercices/mcq/static/false.png b/Exercices/mcq/static/false.png deleted file mode 100644 index c2ea1ab74e1a161151754adf7d2055e5e1b0c897..0000000000000000000000000000000000000000 Binary files a/Exercices/mcq/static/false.png and /dev/null differ diff --git a/Exercices/mcq/static/jquery-shuffle.js b/Exercices/mcq/static/jquery-shuffle.js deleted file mode 100644 index ec707c0f18255ca14e00cc9564a5f0e8225cf5a0..0000000000000000000000000000000000000000 --- a/Exercices/mcq/static/jquery-shuffle.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * jQuery shuffle - * - * Copyright (c) 2008 Ca-Phun Ung <caphun at yelotofu dot com> - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * http://yelotofu.com/labs/jquery/snippets/shuffle/ - * - * Shuffles an array or the children of a element container. - * This uses the Fisher-Yates shuffle algorithm <http://jsfromhell.com/array/shuffle [v1.0]> - */ - -(function($){ - - $.fn.shuffle = function() { - return this.each(function(){ - var items = $(this).children().clone(true); - return (items.length) ? $(this).html($.shuffle(items)) : this; - }); - } - - $.shuffle = function(arr) { - for(var j, x, i = arr.length; i; j = parseInt(Math.random() * i), x = arr[--i], arr[i] = arr[j], arr[j] = x); - return arr; - } - -})(jQuery); diff --git a/Exercices/mcq/static/rst-form.js b/Exercices/mcq/static/rst-form.js deleted file mode 100644 index cc52f6b5d854a695cff8e7670b86959c8f074920..0000000000000000000000000000000000000000 --- a/Exercices/mcq/static/rst-form.js +++ /dev/null @@ -1,182 +0,0 @@ -var score; - -var translations = { - fr: { - score: 'Votre score est de', - inginious_success: 'Tout s\'est bien passé', - request_fail: 'La requête a échoué' - }, - en: { - score: 'You have a score of ', - inginious_success: 'Everything wen well', - request_fail: 'The request failed' - } -}; - -$(function() { - $('input:checked').prop('checked', false); - $('.question').each(shuffle); - $('#submit').click(submit); -}); - -function shuffle(index) { - var nb_pos = $(this).children('.nb_pos').val(); - var nb_prop = $(this).children('.nb_prop').val(); - $(this).shuffle(); - $(this).children('.positive').slice(nb_pos).remove(); - $(this).children('.negative').slice(nb_prop-nb_pos).remove(); - $(this).children('.query').prependTo($(this)); - $(this).children('h2').prependTo($(this)); -} - -function submit() { - check(); - log(); -//OB : remove inginious -// inginious(); -} - -function check() { - score = 0; - $('.comment').hide(); - $('.checkmark').remove(); - $('.result').remove(); - $('.query .comment').show('slow'); - $('input:checked').siblings().children('.comment').show('slow'); - $('.textbox .comment').show('slow'); - $('.question').each(compute_score); - $('#checker').append('<div class="result">' + translations[language]['score'] + ' ' + - score + '/' + - $('.positive').parent().length + '</div>'); -} - -function compute_score() { - if ($(this).children('.textbox').length > 0) { - return; - } - var nb_pos = $(this).children('.nb_pos').val(); - var nb_pos_checked = $(this).children('.positive').children('input:checked').length; - var nb_neg_checked = $(this).children('.negative').children('input:checked').length; - // for sphinx - var pos_img = '<img class="checkmark" src="'+DOCUMENTATION_OPTIONS.URL_ROOT+'/_static/true.png" />'; - var neg_img = '<img class="checkmark" src="'+DOCUMENTATION_OPTIONS.URL_ROOT+'/_static/false.png" />'; - var scored = false; - if (nb_neg_checked == 0 && nb_pos_checked == nb_pos) { - scored = true; - score++; - } - if (nb_pos > 1 || nb_pos_checked + nb_neg_checked == 0) { - if (scored) { - $(this).children('.query').after(pos_img); - } else { - $(this).children('.query').after(neg_img); - } - } else { - $(this).children('.positive').children('input:checked').after(pos_img); - $(this).children('.negative').children('input:checked').after(neg_img); - } -} - -function log() { - if (upload_url != '') { - var json = makeJson(); - if (!$.isEmptyObject(json.questions)) { - $.ajax({ - type: 'POST', - url: upload_url, - data: JSON.stringify(json) - }); - } - } -} - -function makeJson() { - var json = { - html_title: html_title, - title: title, - hash: hash, - questions: {} - }; - $('.question').each(function(index) { - var query = $(this).children('.query'); - query.children('.comment').removeAttr('style'); - query = query.html(); - $comment = $(this).children('.textbox').children('.comment'); - if ($comment.length > 0) { - query += "<div class='comment'>" + $comment.html() + "</div>"; - } - var $input = $(this).children().children('input:checked'); - var answers = []; - while ($input.length > 0) { - $content = $input.siblings('.content'); - $content.children('.comment').removeAttr('style'); - answers.push($content.html()); - $input = $input.slice(1); - } - var textbox = $(this).children('.textbox').children('textarea').val(); - var isTextbox = false; - if (textbox != undefined && textbox != '') { - answers.push(textbox); - isTextbox = true; - } - if (answers.length > 0) { - json.questions[$(this).attr('id')] = { - title: $(this).prev().text().slice(0, -1), - query: query, - answers: answers, - textbox: isTextbox - }; - } - }); - return json; -} - -function inginious() { - if (inginious_url && inginious_url != '' && task_id != '') { - var input = makeInginiousInput(); - $('#results').hide().children().remove(); - $('.problem').remove(); - $.ajax({ - type: 'POST', - url: inginious_url, - data: {taskid: task_id, input: JSON.stringify(input)}, - dataType: 'json' - }).done(function(result) { - if (result['status'] == 'error') { - result['result'] = 'error'; - result['text'] = result['status_message']; - } - if (result['text'] == '') { - result['text'] = translations[language]['inginious_success']; - } - $('#results').append("<p class='" + result['result'] + "'>INGInious: " + result['text'] + "</p>"); - for (var key in result['problems']) { - $('#' + key).prepend('<p class="problem">INGInious: ' + result['problems'][key] + '</p>'); - } - }).fail(function(e) { - $('#results').append("<p class='request-failed'>INGInious: " + translations[language]['request_failed'] + "</p>"); - }).always(function() { - $('#results').show(); - }); - } -} - -function makeInginiousInput() { - var input = {}; - $('.question.inginious').each(function(index) { - choices = []; - $input = $(this).children().children('input:checked'); - while($input.length > 0) { - choices.push(parseInt($input.parent().attr('id'))); - $input = $input.slice(1); - } - if (choices.length == 0) { - $textbox = $(this).children('.textbox').children('textarea'); - if ($textbox.length > 0) { - choices = $textbox.val(); - } - } - input[$(this).attr('id')] = choices; - }); - return input; -} diff --git a/Exercices/mcq/static/true.png b/Exercices/mcq/static/true.png deleted file mode 100644 index 7f6e8675d08f0744d3839536a2d6004ce92e90f3..0000000000000000000000000000000000000000 Binary files a/Exercices/mcq/static/true.png and /dev/null differ diff --git a/Outils/.gitkeep b/Outils/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/Outils/Makefile b/Outils/Makefile deleted file mode 100644 index 0a8ac3d9e440478f60b924e1d23e98df0b34e1d4..0000000000000000000000000000000000000000 --- a/Outils/Makefile +++ /dev/null @@ -1,161 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = a4 -BUILDDIR = ../web/notes/Outils - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext qcm projets sinf1252 - -help: - @echo "Please use \`make <target>' where <target> is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/SINF1252.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/SINF1252.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/SINF1252" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/SINF1252" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -qcm: - @for dir in Exercices/QCM/S*; do make -C $${dir}; done - -projets: - @for dir in Projets/P*; do [ -e $${dir}/Makefile ] && make -C $${dir}; true; done - -sinf1252: qcm projets html latexpdf epub diff --git a/Outils/README.md b/Outils/README.md deleted file mode 100644 index faa247ffdc58b802fd117ab644bcaf08c333da84..0000000000000000000000000000000000000000 --- a/Outils/README.md +++ /dev/null @@ -1 +0,0 @@ -Ce répertoire est destiné à contenir une description des outils informatiques qui peuvent être utiles à tout étudiant travaillant en C sur Unix/Linux. Une brève description sera fournie pour les principaux outils et les étudiants seront encouragés à améliorer ces descriptions. diff --git a/Outils/_static b/Outils/_static deleted file mode 120000 index 7a2b653646f86d98f976df94c66c017b5d24ecbe..0000000000000000000000000000000000000000 --- a/Outils/_static +++ /dev/null @@ -1 +0,0 @@ -../_static \ No newline at end of file diff --git a/Outils/_templates b/Outils/_templates deleted file mode 120000 index db3df549a44959a192630b263daa927927264ea8..0000000000000000000000000000000000000000 --- a/Outils/_templates +++ /dev/null @@ -1 +0,0 @@ -../_templates \ No newline at end of file diff --git a/Outils/bib.rst b/Outils/bib.rst deleted file mode 100644 index f011349ece0bef62bb87889e6dfd7ef88ef23395..0000000000000000000000000000000000000000 --- a/Outils/bib.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -************* -Bibliographie -************* - - -.. [DeveloppezMake] Introduction à Makefile, http://gl.developpez.com/tutoriel/outil/makefile/ - - -.. [GNUMake] The GNU Make Manual, http://www.gnu.org/software/make/manual/make.html - - - -.. [Honeyford2006] Honeyford, M., `Speed your code with the GNU profiler`, http://www.ibm.com/developerworks/library/l-gnuprof.html - diff --git a/Outils/conf.py b/Outils/conf.py deleted file mode 100644 index 7a9e81ee239169140d54a09166c62e63a9c2e7ee..0000000000000000000000000000000000000000 --- a/Outils/conf.py +++ /dev/null @@ -1,312 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SINF1252 documentation build configuration file, created by -# sphinx-quickstart on Tue Jan 3 16:17:09 2012. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.todo', 'sphinx.ext.ifconfig', 'sphinx.ext.mathjax', 'sphinx.ext.intersphinx' ] - -# ucomment -#sys.path.append(os.path.abspath(os.getcwd())) -#extensions.append('ucomment-extension') -#html_translator_class = 'ucomment-extension.ucomment_html_translator' - -# Point to your Django application, which contains all -# the other settings required. -#ucomment = {} -#ucomment['django_application_path'] = '/home/cpaasch/sinf1252/ucommentsite/ucommentapp' - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -source_encoding = 'utf-8' -#source_encoding = 'latin1' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'SINF1252 : Outils informatiques' -copyright = u'2012-2014, O. Bonaventure, G. Detal, C. Paasch, B. Legat, N. Houtain, M. Demol' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '2013' -# The full version, including alpha/beta/rc tags. -release = '2013' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -language = 'fr' - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['_build', '.#*', '*/.#*', 'Exercices/QCM/*' ] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -rst_epilog = """ -.. include:: /../Theorie/links.rst -.. include:: /../Theorie/man_links.rst -.. include:: /../Theorie/incl_links.rst -""" -# Intersphinx -intersphinx_mapping = {'theorie': ('https://sites.uclouvain.be/SystInfo/notes/Theorie/html/', None), 'outils': ('https://sites.uclouvain.be/SystInfo/notes/Outils/html/', None), 'exercices': ('https://sites.uclouvain.be/SystInfo/notes/Exercices/html/', None)} - - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'haiku' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -html_title = u'Systèmes informatiques' - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'SINF1252doc' - - -# -- Options for LaTeX output -------------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -'papersize': 'a4paper', - -# The font size ('10pt', '11pt' or '12pt'). -'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'SINF1252.tex', u'SINF1252', - u'O. Bonaventure, G. Detal, C. Paasch', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'sinf1252', u'SINF1252', - [u'O. Bonaventure, G. Detal, C. Paasch'], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------------ - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'SINF1252', u'SINF1252', - u'O. Bonaventure, G. Detal, C. Paasch', 'SINF1252', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - - -# -- Options for Epub output --------------------------------------------------- - -# Bibliographic Dublin Core info. -epub_title = u'SINF1252' -epub_author = u'O. Bonaventure, G. Detal, C. Paasch' -epub_publisher = u'O. Bonaventure, G. Detal, C. Paasch' -epub_copyright = u'2013, O. Bonaventure, G. Detal, C. Paasch' - -# The language of the text. It defaults to the language option -# or en if the language is not set. -#epub_language = '' - -# The scheme of the identifier. Typical schemes are ISBN or URL. -#epub_scheme = '' - -# The unique identifier of the text. This can be a ISBN number -# or the project homepage. -#epub_identifier = '' - -# A unique identification for the text. -#epub_uid = '' - -# A tuple containing the cover image and cover page html template filenames. -#epub_cover = () - -# HTML files that should be inserted before the pages created by sphinx. -# The format is a list of tuples containing the path and title. -#epub_pre_files = [] - -# HTML files shat should be inserted after the pages created by sphinx. -# The format is a list of tuples containing the path and title. -#epub_post_files = [] - -# A list of files that should not be packed into the epub file. -#epub_exclude_files = [] - -# The depth of the table of contents in toc.ncx. -#epub_tocdepth = 3 - -# Allow duplicate toc entries. -#epub_tocdup = True - -#try: -# open('.staff','r') -# tags.add('staff') -# print "Build as staff member" -#except: -# print "Build as student" diff --git a/Outils/cunit.rst b/Outils/cunit.rst deleted file mode 100644 index ccb5c35aad56fabdf743c6a279acd2dadf171c6e..0000000000000000000000000000000000000000 --- a/Outils/cunit.rst +++ /dev/null @@ -1,276 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. _ref_cunit: - -CUnit: librairie de tests -------------------------- - -`CUnit <http://cunit.sourceforge.net>`_ est une librairie de tests unitaires -en C. Cette librarie vous sera utile lors de développement de projets en C. - -Installation -^^^^^^^^^^^^ - -CUnit n'est pas installé par défaut sur les machines des salles. Vous devez -donc l'installer par vous-même. Le reste de cette section a pour but de vous -aider dans l'installation de celle-ci. - -La première étape consiste à récupérer les sources de CUnit sur -`<http://sourceforge.net/projects/cunit/files/>`_. Les sources se trouvent -dans une archive ``CUnit-*-src.tar.bz2`` et la dernière version devrait se -nommer ``CUnit-2.1.2-src.tar.bz2``. Une fois l'archive téléchargée, ouvrez un -terminal et placez-vous dans le dossier où se trouve celle-ci. Exécutez: - - .. code-block:: console - - $ tar xjvf CUnit-2.1.2-src.tar.bz2 - $ cd CUnit-2.1-2 - $ ./configure --prefix=$HOME/local - $ make - $ make install - -Une fois ces commandes exécutées, la librairie ainsi que ses fichiers d'entête -sont installés dans le dossier ``$HOME/local`` (``$HOME`` est en fait une -variable bash qui définit votre répertoire principal). Comme vous n'avez pas -les droits administrateur, vous ne pouvez pas installer d'application ni de -librairie dans les chemins classiques (c.-à -d., par exemple dans ``/usr/lib``, -``/usr/include``, ``/usr/bin``). C'est pour cela que nous installons la -librairie dans un dossier local. - -Compilation, édition des liens et exécution -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Comme la librairie n'est pas installée dans les chemins classiques, il faut -pouvoir dire à gcc où se trouvent les fichiers d'entête ainsi que la librairie -afin d'éviter les erreurs de compilation. Pour cela, il faut spécifier à la -compilation l'argument ``-I${HOME}/local/include`` afin de lui dire qu'il doit -également aller chercher des fichiers d'entête dans le dossier -``$HOME/local/include`` en plus des chemins classiques tels que -``/usr/include`` et ``/usr/local/include``. - -Lors de l'édition des liens avec le linker, il faut spécifier où se trouve la -librairie dynamique afin de résoudre les symboles. Pour cela, il faut passer -l'argument ``-lcunit`` pour effectuer la liaison avec la librairie CUnit ainsi -que lui spécifier ``-L${HOME}/local/lib`` afin qu'il cherche également des -librairies dans le dossier ``$HOME/local/lib``. - -Lors de l'exécution, il faut également spécifier où se trouvent les -librairies. Par exemple pour un binaire ``test`` qui utilise la librairie -CUnit, on peut exécuter: - - .. code-block:: console - - $ export LD_LIBRARY_PATH=$HOME/local/lib:$LD_LIBRARY_PATH - $ ./test - -Utilisation -^^^^^^^^^^^ - -Dans CUnit, on retrouve toutes les fonctions nécessaire pour gérer un ensemble -de suites de tests. Cet ensemble forme un catalogue; il est composé d'une ou -plusieurs suite(s) de tests; chaque suite est composée d'un ou plusieurs -tests. - -Pour pouvoir concrètement exécuter un ensemble de tests, il est nécessaire -de réaliser les différentes étapes suivantes: - -1. Ecrire les tests -2. Initialiser le catalogue -3. Ajouter les suites de tests dans le catalogue -4. Ajouter les tests dans les suites de tests -5. Exécuter les tests -6. Terminer proprement l'exécution des tests - -La suite de la section détaille chacune de ces étapes. - -Tout d'abord, il est nécessaire d'écrire les tests. Aucune libraire ne peut -les écrire pour vous. Toutefois, CUnit vient avec un certain nombre de macros -permettant de vérifier les propriétés qui nous intéressent. Pour pouvoir -utiliser ces macros, il est nécessaire d'importer ``CUnit.h``. La table -suivante récapitule les principales macros. Il est important d'appeller ces -macros lorsque l'on rédige les tests, ce sont ces appels qui détermineront si -oui ou non, le test est fructueux. - -============================================================== =========== -Assertion Définition -============================================================== =========== -``CU_ASSERT(int expression)`` Vérifie que la valeur est non-nulle (``true``). -``CU_ASSERT_TRUE(value)`` Vérifie que la valeur est non-nulle (``true``). -``CU_ASSERT_FALSE(value)`` Vérifie que la valeur est nulle (``false``). -``CU_ASSERT_EQUAL(actual, expected)`` Vérifie que ``actual`` est égal à ``expected``. -``CU_ASSERT_NOT_EQUAL(actual, expected))`` Vérifie que ``actual`` n'est pas égal à ``expected``. -``CU_ASSERT_PTR_EQUAL(actual, expected)`` Vérifie que le pointeur ``actual`` est égal au pointeur ``expected``. -``CU_ASSERT_PTR_NOT_EQUAL(actual, expected)`` Vérifie que le pointeur ``actual`` est différent du pointeur ``expected``. -``CU_ASSERT_PTR_NULL(value)`` Vérifie que le pointeur est ``NULL``. -``CU_ASSERT_PTR_NOT_NULL(value)`` Vérifie que le pointeur n'est pas ``NULL``. -``CU_ASSERT_STRING_EQUAL(actual, expected)`` Vérifie que la chaine de caractère ``actual`` est égale à la chaine de caractère ``expected``. -``CU_ASSERT_STRING_NOT_EQUAL(actual, expected)`` Vérifie que la chaine de caractère ``actual`` n'est pas égale à la chaine de caractère ``expected``. -``CU_ASSERT_NSTRING_EQUAL(actual, expected, count)`` Vérifie que les ``count`` premiers caractères de la chaine ``actual`` sont égaux aux ``count`` premiers caractères de la chaine ``expected``. -``CU_ASSERT_NSTRING_NOT_EQUAL(actual, expected, count)`` Vérifie que les ``count`` premiers caractères de la chaine ``actual`` ne sont pas égaux aux ``count`` premiers caractères de la chaine ``expected``. -``CU_ASSERT_DOUBLE_EQUAL(actual, expected, granularity)`` Vérifie que ``actual`` et ``expected`` ne diffèrent pas plus que ``granularity`` (:math:`|actual-expected| \leq |granularity|`) -``CU_ASSERT_DOUBLE_NOT_EQUAL(actual, expected, granularity)`` Vérifie que ``actual`` et ``expected`` diffèrent de plus que ``granularity`` (:math:`|actual-expected| > |granularity|`) -``CU_PASS(message)`` Ne vérifie rien mais notifie que le test est réussis -``CU_FAIL(message)`` Ne vérifie rien mais notifie que le test est raté -============================================================== =========== - -Par exemple, les méthodes ci-dessous vérifie chacune certaines propriétés. - - .. code-block:: c - - void test_assert_true(void) - { - CU_ASSERT(true); - } - - void test_assert_2_not_equal_minus_1(void) - { - CU_ASSERT_NOT_EQUAL(2, -1); - } - - void test_string_equals(void) - { - CU_ASSERT_STRING_EQUAL("string #1", "string #1"); - } - - void test_failure(void) - { - CU_ASSERT(false); - } - - void test_string_equals_failure(void) - { - CU_ASSERT_STRING_EQUAL("string #1", "string #2"); - } - -Une fois les tests écrits, il faut initialiser le catalogue (et donc -l'infrastructure de tests) en appelant la méthode -``CU_initialize_registry()``. Cette méthode retourne un code d'erreur qu'il -est impératif de vérifier pour s'assurer du bon fonctionnement de la -vérification des tests. Par exemple, - - .. code-block:: c - - if (CUE_SUCCESS != CU_initialize_registry()) - return CU_get_error(); - -Pour ajouter les suites de tests au catalogue, il faut faire appel à la -méthode ``CU_add_suite(const char* strName, CU_InitializeFunc pInit, -CU_CleanupFunc pClean)``. Comme on peut le voir, cette méthode demande un nom -(qui doit être unique pour un catalogue) ainsi que deux pointeurs de fonction. -Ces pointeurs de fonction permettent d'exécuter du code avant (typiquement -appelé 'setup') ou après (typiquement 'teardown') l'exécution des tests de la -suite. Ces méthodes sont utiles pour initialiser un environnement d'exécution -pour des tests le nécessitants (par exemple, s'assurer de la présence de -fichier, initialiser certaines variables, etc.). Ces méthodes sont bien sûr -optionnelles, si aucune n'est nécessaire, il suffit alors de passer ``NULL`` -en paramètre. Par ailleurs, notons que ces méthodes doivent retourner 0 si -tout c'est bien passé, un chiffre positif dans le cas contraire. Comme pour -l'initialisation du catalogue, il est bien entendu nécessaire de vérifier le -code retourné par la méthode. La table suivante décrit les codes d'erreurs. - -===================== ========================= -Code d'erreur Définition -===================== ========================= -``CUE_SUCCESS`` Aucune erreur -``CUE_NOREGISTRY`` Erreur d'initialisation -``CUE_NO_SUITENAME`` Nom manquant -``CUE_DUP_SUITE`` Nom non unique -``CUE_NOMEMORY`` Pas de mémoire disponible -===================== ========================= - -Par exemple, le code suivant crée une nouvelle suite de test nommée *ma_suite*, -avec une fonction d'initialisation et une fonction de terminaison. - - .. code-block:: c - - int setup(void) { return 0; } - int teardown(void) { return 0; } - // ... - CU_pSuite pSuite = NULL; - // ... - pSuite = CU_add_suite("ma_suite", setup, teardown); - if (NULL == pSuite) { - CU_cleanup_registry(); - return CU_get_error(); - } - -Les tests peuvent ensuite être ajoutés à la suite de test. Pour cela, il faut -faire appel à la méthode ``CU_add_test(CU_pSuite pSuite, const char* -strName, CU_TestFunc pTestFunc)``. Comme pour une suite de tests, il est -nécessaire de préciser un nom. Ce nom doit être unique pour la suite de test. -Le second paramètre est un pointeur vers la fonction de test. A nouveau, il -est important de vérifier la valeur de retour de la méthode. - -===================== ========================================= -Code d'erreur Définition -===================== ========================================= -``CUE_SUCCESS`` Aucune erreur -``CUE_NOSUITE`` Suite de tests ``NULL`` -``CUE_NO_TESTNAME`` Nom manquant -``CUE_DUP_TEST`` Nom non unique -``CUE_NO_TEST`` Pointeur de fonction ``NULL`` ou invalide -``CUE_NOMEMORY`` Pas de mémoire disponible -===================== ========================================= - -Le code suivant ajoute les tests décrits ci-dessus à la suite de test que nous -avons créé juste avant. - - .. code-block:: c - - if ((NULL == CU_add_test(pSuite, "Test assert true", test_assert_true)) || - (NULL == CU_add_test(pSuite, "Test assert 2 not equal -1", test_assert_2_not_equal_minus_1)) || - (NULL == CU_add_test(pSuite, "Test string equals", test_string_equals)) || - (NULL == CU_add_test(pSuite, "Test failure", test_failure)) || - (NULL == CU_add_test(pSuite, "Test string equals failure", test_string_equals_failure))) - { - CU_cleanup_registry(); - return CU_get_error(); - } - -Maintenant que le catalogue est initialisé, qu'il contient des suites de tests -et que les tests ont été ajoutés à ces suites, il nous est possible d'exécuter -ces tests. Il existe plusieurs moyens d'exécuter les tests CUnit, nous -présentons uniquement le mode de base, non interactif. Pour les autres modes, -referez-vous à la `documentation -<http://cunit.sourceforge.net/doc/running_tests.html>`_. Pour faire tourner -les tests, il suffit d'appeler la méthode ``CU_basic_run_tests()`` qui -appellera tous les tests dans toutes les suites des catalogues référencés. -Ensuite, on peut afficher le rapport à l'aide de -``CU_basic_show_failures(CU_pFailureRecord pFailure)`` et -``CU_get_failure_list()``. - - .. code-block:: c - - CU_basic_run_tests(); - CU_basic_show_failures(CU_get_failure_list()); - -Avec le programme illustré ci-dessous, la console nous affiche les messages -suivants : - - .. code-block:: console - - - CUnit - A unit testing framework for C - Version 2.1-2 - http://cunit.sourceforge.net/ - - - Suite ma_suite, Test Test failure had failures: - 1. cunit.c:24 - false - Suite ma_suite, Test Test string equals failure had failures: - 1. cunit.c:29 - CU_ASSERT_STRING_EQUAL("string #1","string #2") - - Run Summary: Type Total Ran Passed Failed Inactive - suites 1 1 n/a 0 0 - tests 5 5 3 2 0 - asserts 5 5 3 2 n/a - - Elapsed time = 0.000 seconds - - - 1. cunit.c:24 - false - 2. cunit.c:29 - CU_ASSERT_STRING_EQUAL("string #1","string #2") - -Enfin, il est nécessaire de libérer les ressources en appelant -``CU_cleanup_registry()``. \ No newline at end of file diff --git a/Outils/figures/graph.dot b/Outils/figures/graph.dot deleted file mode 100644 index a5640f9ebd32ff009cda15c96a427131c396b779..0000000000000000000000000000000000000000 --- a/Outils/figures/graph.dot +++ /dev/null @@ -1,35 +0,0 @@ -digraph "git history" { - "master" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="master"]; - "master" -> "245e4"; - "hello" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="hello"]; - "hello" -> "f4dff"; - "hey" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="hey"]; - "hey" -> "22931"; - "hi" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="hi"]; - "hi" -> "4cd75"; - "ho" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="ho"]; - "ho" -> "22931"; - "v0.1" [shape="box",style="rounded,filled",color="seagreen", fillcolor="palegreen", label="v0.1"]; - "v0.1" -> "245e4"; - "HEAD" [shape="box",style="rounded,filled",color="lightgoldenrod3", fillcolor="khaki1", label="HEAD"]; - "HEAD" -> "master"; - "22931" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="22931\ng"]; - "22931" -> "54978"; - "f4dff" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="f4dff\nf"]; - "f4dff" -> "88305"; - "4cd75" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="4cd75\nMerge branch 'hello' into hi"]; - "4cd75" -> "245e4"; - "4cd75" -> "88305"; - "245e4" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="245e4\ne"]; - "245e4" -> "05e80"; - "88305" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="88305\nd"]; - "88305" -> "0ef13"; - "05e80" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="05e80\nMerge branch 'hello'"]; - "05e80" -> "b443e"; - "05e80" -> "0ef13"; - "0ef13" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="0ef13\nc"]; - "0ef13" -> "54978"; - "b443e" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="b443e\nb"]; - "b443e" -> "54978"; - "54978" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="54978\na"]; -} diff --git a/Outils/figures/graph.png b/Outils/figures/graph.png deleted file mode 100644 index b5465e3c221b1aa654eb446d355149e5264e028a..0000000000000000000000000000000000000000 Binary files a/Outils/figures/graph.png and /dev/null differ diff --git a/Outils/figures/hello_2ff.dot b/Outils/figures/hello_2ff.dot deleted file mode 100644 index 473efa3045360e4ee4a063b7345f81df6b371c2f..0000000000000000000000000000000000000000 --- a/Outils/figures/hello_2ff.dot +++ /dev/null @@ -1,17 +0,0 @@ -digraph "git history" { - "master" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="master"]; - "master" -> "c1f21"; - "pid" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="pid"]; - "pid" -> "c1f21"; - "universal" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="universal"]; - "universal" -> "c1f21"; - "HEAD" [shape="box",style="rounded,filled",color="lightgoldenrod3", fillcolor="khaki1", label="HEAD"]; - "HEAD" -> "universal"; - "c1f21" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c1f21\nAdd intro"]; - "c1f21" -> "b1485"; - "b1485" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="b1485\nAdd .gitignore"]; - "b1485" -> "bc620"; - "bc620" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="bc620\nAdd return"]; - "bc620" -> "76c16"; - "76c16" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="76c16\nFirst commit"]; -} diff --git a/Outils/figures/hello_2ff.png b/Outils/figures/hello_2ff.png deleted file mode 100644 index f52d94cb89008966f6eeca0e6c1d94229646403d..0000000000000000000000000000000000000000 Binary files a/Outils/figures/hello_2ff.png and /dev/null differ diff --git a/Outils/figures/hello_branches.dot b/Outils/figures/hello_branches.dot deleted file mode 100644 index 9e79052d61253e8154af5866f2998304ea7d4021..0000000000000000000000000000000000000000 --- a/Outils/figures/hello_branches.dot +++ /dev/null @@ -1,15 +0,0 @@ -digraph "git history" { - "master" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="master"]; - "master" -> "b1485"; - "pid" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="pid"]; - "pid" -> "b1485"; - "universal" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="universal"]; - "universal" -> "b1485"; - "HEAD" [shape="box",style="rounded,filled",color="lightgoldenrod3", fillcolor="khaki1", label="HEAD"]; - "HEAD" -> "master"; - "b1485" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="b1485\nAdd .gitignore"]; - "b1485" -> "bc620"; - "bc620" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="bc620\nAdd return"]; - "bc620" -> "76c16"; - "76c16" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="76c16\nFirst commit"]; -} diff --git a/Outils/figures/hello_branches.png b/Outils/figures/hello_branches.png deleted file mode 100644 index bbec70b0306b282838afe7e8378a21f32756ee5a..0000000000000000000000000000000000000000 Binary files a/Outils/figures/hello_branches.png and /dev/null differ diff --git a/Outils/figures/hello_dpid.dot b/Outils/figures/hello_dpid.dot deleted file mode 100644 index 35980d1e22d7153085dd78a89ef395ee86b03062..0000000000000000000000000000000000000000 --- a/Outils/figures/hello_dpid.dot +++ /dev/null @@ -1,24 +0,0 @@ -digraph "git history" { - "master" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="master"]; - "master" -> "eda36"; - "universal" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="universal"]; - "universal" -> "88d2c"; - "HEAD" [shape="box",style="rounded,filled",color="lightgoldenrod3", fillcolor="khaki1", label="HEAD"]; - "HEAD" -> "master"; - "eda36" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="eda36\nAdd pid/ppid info"]; - "eda36" -> "c35a8"; - "88d2c" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="88d2c\nMerge branch 'master' into universal"]; - "88d2c" -> "e0c31"; - "88d2c" -> "c35a8"; - "c35a8" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c35a8\nAdd Makefile"]; - "c35a8" -> "c1f21"; - "e0c31" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="e0c31\nMake it universal"]; - "e0c31" -> "c1f21"; - "c1f21" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c1f21\nAdd intro"]; - "c1f21" -> "b1485"; - "b1485" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="b1485\nAdd .gitignore"]; - "b1485" -> "bc620"; - "bc620" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="bc620\nAdd return"]; - "bc620" -> "76c16"; - "76c16" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="76c16\nFirst commit"]; -} diff --git a/Outils/figures/hello_dpid.png b/Outils/figures/hello_dpid.png deleted file mode 100644 index 1a3fb40d840b13a5aa488613599b21cc0ba3f3d2..0000000000000000000000000000000000000000 Binary files a/Outils/figures/hello_dpid.png and /dev/null differ diff --git a/Outils/figures/hello_fix.dot b/Outils/figures/hello_fix.dot deleted file mode 100644 index 424f3babea2bce03ab8e6f687303591ad0e75ec9..0000000000000000000000000000000000000000 --- a/Outils/figures/hello_fix.dot +++ /dev/null @@ -1,26 +0,0 @@ -digraph "git history" { - "master" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="master"]; - "master" -> "eda36"; - "universal" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="universal"]; - "universal" -> "6fd2e"; - "HEAD" [shape="box",style="rounded,filled",color="lightgoldenrod3", fillcolor="khaki1", label="HEAD"]; - "HEAD" -> "universal"; - "6fd2e" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="6fd2e\nFix SIGSEV without args"]; - "6fd2e" -> "88d2c"; - "eda36" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="eda36\nAdd pid/ppid info"]; - "eda36" -> "c35a8"; - "88d2c" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="88d2c\nMerge branch 'master' into universal"]; - "88d2c" -> "e0c31"; - "88d2c" -> "c35a8"; - "c35a8" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c35a8\nAdd Makefile"]; - "c35a8" -> "c1f21"; - "e0c31" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="e0c31\nMake it universal"]; - "e0c31" -> "c1f21"; - "c1f21" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c1f21\nAdd intro"]; - "c1f21" -> "b1485"; - "b1485" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="b1485\nAdd .gitignore"]; - "b1485" -> "bc620"; - "bc620" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="bc620\nAdd return"]; - "bc620" -> "76c16"; - "76c16" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="76c16\nFirst commit"]; -} diff --git a/Outils/figures/hello_fix.png b/Outils/figures/hello_fix.png deleted file mode 100644 index 33a304013a6d6deb6072ad4dc0f9cdbbb9da65e3..0000000000000000000000000000000000000000 Binary files a/Outils/figures/hello_fix.png and /dev/null differ diff --git a/Outils/figures/hello_intro.dot b/Outils/figures/hello_intro.dot deleted file mode 100644 index 896796101a4fef9ba935e30b5a0f1b3c2c4fa429..0000000000000000000000000000000000000000 --- a/Outils/figures/hello_intro.dot +++ /dev/null @@ -1,17 +0,0 @@ -digraph "git history" { - "master" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="master"]; - "master" -> "c1f21"; - "pid" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="pid"]; - "pid" -> "b1485"; - "universal" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="universal"]; - "universal" -> "b1485"; - "HEAD" [shape="box",style="rounded,filled",color="lightgoldenrod3", fillcolor="khaki1", label="HEAD"]; - "HEAD" -> "master"; - "c1f21" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c1f21\nAdd intro"]; - "c1f21" -> "b1485"; - "b1485" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="b1485\nAdd .gitignore"]; - "b1485" -> "bc620"; - "bc620" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="bc620\nAdd return"]; - "bc620" -> "76c16"; - "76c16" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="76c16\nFirst commit"]; -} diff --git a/Outils/figures/hello_intro.png b/Outils/figures/hello_intro.png deleted file mode 100644 index 6b3fe35366854d23d704f0f08511c63bdd5dcf61..0000000000000000000000000000000000000000 Binary files a/Outils/figures/hello_intro.png and /dev/null differ diff --git a/Outils/figures/hello_make_universal.dot b/Outils/figures/hello_make_universal.dot deleted file mode 100644 index 43f21b975127fbe6cbfdff5bc246adf967d14faa..0000000000000000000000000000000000000000 --- a/Outils/figures/hello_make_universal.dot +++ /dev/null @@ -1,19 +0,0 @@ -digraph "git history" { - "master" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="master"]; - "master" -> "c1f21"; - "pid" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="pid"]; - "pid" -> "c1f21"; - "universal" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="universal"]; - "universal" -> "e0c31"; - "HEAD" [shape="box",style="rounded,filled",color="lightgoldenrod3", fillcolor="khaki1", label="HEAD"]; - "HEAD" -> "universal"; - "e0c31" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="e0c31\nMake it universal"]; - "e0c31" -> "c1f21"; - "c1f21" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c1f21\nAdd intro"]; - "c1f21" -> "b1485"; - "b1485" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="b1485\nAdd .gitignore"]; - "b1485" -> "bc620"; - "bc620" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="bc620\nAdd return"]; - "bc620" -> "76c16"; - "76c16" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="76c16\nFirst commit"]; -} diff --git a/Outils/figures/hello_make_universal.png b/Outils/figures/hello_make_universal.png deleted file mode 100644 index 8e38f915584686defc73efb6fda3bcb63aa60156..0000000000000000000000000000000000000000 Binary files a/Outils/figures/hello_make_universal.png and /dev/null differ diff --git a/Outils/figures/hello_makefile.dot b/Outils/figures/hello_makefile.dot deleted file mode 100644 index 53b772ccd1d18838c005ed169076941d153513cc..0000000000000000000000000000000000000000 --- a/Outils/figures/hello_makefile.dot +++ /dev/null @@ -1,21 +0,0 @@ -digraph "git history" { - "master" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="master"]; - "master" -> "c35a8"; - "pid" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="pid"]; - "pid" -> "c1f21"; - "universal" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="universal"]; - "universal" -> "e0c31"; - "HEAD" [shape="box",style="rounded,filled",color="lightgoldenrod3", fillcolor="khaki1", label="HEAD"]; - "HEAD" -> "master"; - "c35a8" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c35a8\nAdd Makefile"]; - "c35a8" -> "c1f21"; - "e0c31" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="e0c31\nMake it universal"]; - "e0c31" -> "c1f21"; - "c1f21" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c1f21\nAdd intro"]; - "c1f21" -> "b1485"; - "b1485" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="b1485\nAdd .gitignore"]; - "b1485" -> "bc620"; - "bc620" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="bc620\nAdd return"]; - "bc620" -> "76c16"; - "76c16" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="76c16\nFirst commit"]; -} diff --git a/Outils/figures/hello_makefile.png b/Outils/figures/hello_makefile.png deleted file mode 100644 index 1216fc32a4334a393c717e6356b4a0f69437c13d..0000000000000000000000000000000000000000 Binary files a/Outils/figures/hello_makefile.png and /dev/null differ diff --git a/Outils/figures/hello_merge_universal.dot b/Outils/figures/hello_merge_universal.dot deleted file mode 100644 index 1572c2973cb3045ddbaae95d9010b245da2e6d27..0000000000000000000000000000000000000000 --- a/Outils/figures/hello_merge_universal.dot +++ /dev/null @@ -1,29 +0,0 @@ -digraph "git history" { - "master" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="master"]; - "master" -> "0dd6c"; - "universal" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="universal"]; - "universal" -> "6fd2e"; - "HEAD" [shape="box",style="rounded,filled",color="lightgoldenrod3", fillcolor="khaki1", label="HEAD"]; - "HEAD" -> "master"; - "0dd6c" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="0dd6c\nMerge branch 'universal'"]; - "0dd6c" -> "eda36"; - "0dd6c" -> "6fd2e"; - "6fd2e" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="6fd2e\nFix SIGSEV without args"]; - "6fd2e" -> "88d2c"; - "eda36" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="eda36\nAdd pid/ppid info"]; - "eda36" -> "c35a8"; - "88d2c" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="88d2c\nMerge branch 'master' into universal"]; - "88d2c" -> "e0c31"; - "88d2c" -> "c35a8"; - "c35a8" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c35a8\nAdd Makefile"]; - "c35a8" -> "c1f21"; - "e0c31" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="e0c31\nMake it universal"]; - "e0c31" -> "c1f21"; - "c1f21" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c1f21\nAdd intro"]; - "c1f21" -> "b1485"; - "b1485" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="b1485\nAdd .gitignore"]; - "b1485" -> "bc620"; - "bc620" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="bc620\nAdd return"]; - "bc620" -> "76c16"; - "76c16" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="76c16\nFirst commit"]; -} diff --git a/Outils/figures/hello_merge_universal.png b/Outils/figures/hello_merge_universal.png deleted file mode 100644 index 9b952cda0dfbfb69c75f56f57f8a1e1b40c17320..0000000000000000000000000000000000000000 Binary files a/Outils/figures/hello_merge_universal.png and /dev/null differ diff --git a/Outils/figures/hello_pid_makefile.dot b/Outils/figures/hello_pid_makefile.dot deleted file mode 100644 index 68e7f205e737906d384f8382678b54e9872c5e06..0000000000000000000000000000000000000000 --- a/Outils/figures/hello_pid_makefile.dot +++ /dev/null @@ -1,24 +0,0 @@ -digraph "git history" { - "master" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="master"]; - "master" -> "c35a8"; - "pid" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="pid"]; - "pid" -> "c35a8"; - "universal" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="universal"]; - "universal" -> "88d2c"; - "HEAD" [shape="box",style="rounded,filled",color="lightgoldenrod3", fillcolor="khaki1", label="HEAD"]; - "HEAD" -> "pid"; - "88d2c" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="88d2c\nMerge branch 'master' into universal"]; - "88d2c" -> "e0c31"; - "88d2c" -> "c35a8"; - "c35a8" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c35a8\nAdd Makefile"]; - "c35a8" -> "c1f21"; - "e0c31" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="e0c31\nMake it universal"]; - "e0c31" -> "c1f21"; - "c1f21" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c1f21\nAdd intro"]; - "c1f21" -> "b1485"; - "b1485" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="b1485\nAdd .gitignore"]; - "b1485" -> "bc620"; - "bc620" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="bc620\nAdd return"]; - "bc620" -> "76c16"; - "76c16" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="76c16\nFirst commit"]; -} diff --git a/Outils/figures/hello_pid_makefile.png b/Outils/figures/hello_pid_makefile.png deleted file mode 100644 index bde2bc1b3ac2bbff0ac939dd68a8ef1f57e88d12..0000000000000000000000000000000000000000 Binary files a/Outils/figures/hello_pid_makefile.png and /dev/null differ diff --git a/Outils/figures/hello_ppid.dot b/Outils/figures/hello_ppid.dot deleted file mode 100644 index 2d6e0eb367f8f82583880030a96501932afb3815..0000000000000000000000000000000000000000 --- a/Outils/figures/hello_ppid.dot +++ /dev/null @@ -1,26 +0,0 @@ -digraph "git history" { - "master" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="master"]; - "master" -> "c35a8"; - "pid" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="pid"]; - "pid" -> "eda36"; - "universal" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="universal"]; - "universal" -> "88d2c"; - "HEAD" [shape="box",style="rounded,filled",color="lightgoldenrod3", fillcolor="khaki1", label="HEAD"]; - "HEAD" -> "pid"; - "eda36" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="eda36\nAdd pid/ppid info"]; - "eda36" -> "c35a8"; - "88d2c" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="88d2c\nMerge branch 'master' into universal"]; - "88d2c" -> "e0c31"; - "88d2c" -> "c35a8"; - "c35a8" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c35a8\nAdd Makefile"]; - "c35a8" -> "c1f21"; - "e0c31" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="e0c31\nMake it universal"]; - "e0c31" -> "c1f21"; - "c1f21" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c1f21\nAdd intro"]; - "c1f21" -> "b1485"; - "b1485" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="b1485\nAdd .gitignore"]; - "b1485" -> "bc620"; - "bc620" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="bc620\nAdd return"]; - "bc620" -> "76c16"; - "76c16" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="76c16\nFirst commit"]; -} diff --git a/Outils/figures/hello_ppid.png b/Outils/figures/hello_ppid.png deleted file mode 100644 index 372c2b31bfce3f9d325a38288cce3116b8ac4e04..0000000000000000000000000000000000000000 Binary files a/Outils/figures/hello_ppid.png and /dev/null differ diff --git a/Outils/figures/hello_universal_makefile.dot b/Outils/figures/hello_universal_makefile.dot deleted file mode 100644 index 49380a39439980f840c5122ad4a4c959ad0a67eb..0000000000000000000000000000000000000000 --- a/Outils/figures/hello_universal_makefile.dot +++ /dev/null @@ -1,24 +0,0 @@ -digraph "git history" { - "master" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="master"]; - "master" -> "c35a8"; - "pid" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="pid"]; - "pid" -> "c1f21"; - "universal" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="universal"]; - "universal" -> "88d2c"; - "HEAD" [shape="box",style="rounded,filled",color="lightgoldenrod3", fillcolor="khaki1", label="HEAD"]; - "HEAD" -> "universal"; - "88d2c" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="88d2c\nMerge branch 'master' into universal"]; - "88d2c" -> "e0c31"; - "88d2c" -> "c35a8"; - "c35a8" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c35a8\nAdd Makefile"]; - "c35a8" -> "c1f21"; - "e0c31" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="e0c31\nMake it universal"]; - "e0c31" -> "c1f21"; - "c1f21" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="c1f21\nAdd intro"]; - "c1f21" -> "b1485"; - "b1485" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="b1485\nAdd .gitignore"]; - "b1485" -> "bc620"; - "bc620" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="bc620\nAdd return"]; - "bc620" -> "76c16"; - "76c16" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="76c16\nFirst commit"]; -} diff --git a/Outils/figures/hello_universal_makefile.png b/Outils/figures/hello_universal_makefile.png deleted file mode 100644 index 96568a7b841cc59e29c4ca7b0f7ecd6155b597d0..0000000000000000000000000000000000000000 Binary files a/Outils/figures/hello_universal_makefile.png and /dev/null differ diff --git a/Outils/figures/hello_with_gitignore.dot b/Outils/figures/hello_with_gitignore.dot deleted file mode 100644 index 7be88cadb28419795b346446200d790f5d60130c..0000000000000000000000000000000000000000 --- a/Outils/figures/hello_with_gitignore.dot +++ /dev/null @@ -1,13 +0,0 @@ -digraph "git history" { - "master" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="master"]; - "master" -> "b1485"; - "hello" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="hello"]; - "hello" -> "76c16"; - "HEAD" [shape="box",style="rounded,filled",color="lightgoldenrod3", fillcolor="khaki1", label="HEAD"]; - "HEAD" -> "master"; - "b1485" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="b1485\nAdd .gitignore"]; - "b1485" -> "bc620"; - "bc620" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="bc620\nAdd return"]; - "bc620" -> "76c16"; - "76c16" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="76c16\nFirst commit"]; -} diff --git a/Outils/figures/hello_with_gitignore.png b/Outils/figures/hello_with_gitignore.png deleted file mode 100644 index 43310c1db61a4c80c124f02da0c5ac12112bc335..0000000000000000000000000000000000000000 Binary files a/Outils/figures/hello_with_gitignore.png and /dev/null differ diff --git a/Outils/figures/hello_with_return.dot b/Outils/figures/hello_with_return.dot deleted file mode 100644 index c3483cad4f250703a470f25aeddf5d9db75c0765..0000000000000000000000000000000000000000 --- a/Outils/figures/hello_with_return.dot +++ /dev/null @@ -1,11 +0,0 @@ -digraph "git history" { - "master" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="master"]; - "master" -> "bc620"; - "hello" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="hello"]; - "hello" -> "76c16"; - "HEAD" [shape="box",style="rounded,filled",color="lightgoldenrod3", fillcolor="khaki1", label="HEAD"]; - "HEAD" -> "master"; - "bc620" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="bc620\nAdd return"]; - "bc620" -> "76c16"; - "76c16" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="76c16\nFirst commit"]; -} diff --git a/Outils/figures/hello_with_return.png b/Outils/figures/hello_with_return.png deleted file mode 100644 index 58fcd89e0c97ca00b8539a5eab92d94a333c16cd..0000000000000000000000000000000000000000 Binary files a/Outils/figures/hello_with_return.png and /dev/null differ diff --git a/Outils/figures/hello_without_return.dot b/Outils/figures/hello_without_return.dot deleted file mode 100644 index 056230591b3a05bd1dd8a5044590a3431985557e..0000000000000000000000000000000000000000 --- a/Outils/figures/hello_without_return.dot +++ /dev/null @@ -1,9 +0,0 @@ -digraph "git history" { - "master" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="master"]; - "master" -> "76c16"; - "hello" [shape="box",style="rounded,filled",color="indianred4", fillcolor="lightpink", label="hello"]; - "hello" -> "76c16"; - "HEAD" [shape="box",style="rounded,filled",color="lightgoldenrod3", fillcolor="khaki1", label="HEAD"]; - "HEAD" -> "master"; - "76c16" [shape="box",style="rounded,filled",color="skyblue4", fillcolor="slategray1", label="76c16\nFirst commit"]; -} diff --git a/Outils/figures/hello_without_return.png b/Outils/figures/hello_without_return.png deleted file mode 100644 index 3d87fbe8bcc1a97effc78380c605c556b4478e54..0000000000000000000000000000000000000000 Binary files a/Outils/figures/hello_without_return.png and /dev/null differ diff --git a/Outils/gcc.rst b/Outils/gcc.rst deleted file mode 100644 index 826d44c880c70e5a6e11a87883079808ef0c2699..0000000000000000000000000000000000000000 --- a/Outils/gcc.rst +++ /dev/null @@ -1,38 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_ et Nicolas Houtain -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - - -GCC ---- - - -Comme cela a déja été dit, le compilateur fonctionne selon 4 étapes distinctes: - * Appel du préprocesseur ``cpp``: Supprime les commentaires, inclus les #includes et évalue les macros - * Appel du compilateur ``cc1``: Génère un fichier assembleur (.as) - * Appel de l'assembleur ``as`` : Génère le fichier objet (.o) - * Appel du linkeur ``ld`` : Génère l'exécutable - - -Différentes options peuvent être utilisé avec gcc : - - * -E : Appelle uniquement le préprocesseur - * -S : Appelle uniquement le préprocesseur et le compilateur - * -C : Appelle le préprocesseur, le compilateur et l'assembleur - - * -o nom : Détermine le nom du fichier de sortie - * -g : Option nécessaire pour générer les informations symboliques de débogage avec gdb - * -On : Indique le niveau d'optimisation où n est compris entre 0 et 3 - * -Wall : Active tout les warnings - * -Werror : Considère tout les warnings comme des erreurs - - * --help - -Notons que les trois premières options ne présentent pas d'interêt pour ce cour. - - - - - - diff --git a/Outils/gdb.rst b/Outils/gdb.rst deleted file mode 100644 index 04a8df09f3f5f891e268516ea5d750667626a454..0000000000000000000000000000000000000000 --- a/Outils/gdb.rst +++ /dev/null @@ -1,214 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch, Grégory Detal et Nicolas Houtain -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. _gdb-ref: - -GDB -=== - -Liste des commandes -------------------- - -`gdb(1)`_ permet de débugger vos programmes plus facilement en permettant d'analyser l'état durant l'exécution. Pour pouvoir analyser votre exécutable avec `gdb(1)`_, vous devez ajouter les symboles de débuggage lors de la compilation en utilisant l'option ``-g`` de `gcc(1)`_: - - .. code-block:: console - - gcc -g gdb.c -o my_program - -L'option -g de `gcc(1)`_ place dans l'exécutable les informations sur les noms de variables, mais aussi tout le code source. - -Lancez gdb avec la commande ``gdb my_program``. Ceci va vous ouvrir la console de ``gdb`` qui vous permet de lancer, le programme et de l'analyser. Pour démarrer le programme, tapez ``run``. gdb va arrêter l'exécution au premier problème trouvé. Votre programme tourne encore pour l'instant. Arrètez-le avec la commande ``kill``. - -Breakpoint -^^^^^^^^^^ - -Pour analyser un programme, vous pouvez y placer des breakpoints. Un breakpoint permet de mettre en pause l'exécution d'un programme à un endroit donné pour pouvoir afficher l'état des variables et faire une exécution pas-à -pas. Pour mettre un breakpoint, vous avez plusieurs choix: - - * ``break [function]`` met en pause l'exécution à l'appel de la fonction passée en argument à la commande - * ``break [filename:linenumber]`` spécifie le fichier du code source et la ligne à laquelle l'exécution doit s'arrêter - * ``delete [numberbreakpoint]`` supprime le breakpoint spécifié - - Note : Chaque breakpoint est caractérisé par un numéro. Pour obtenir la liste des breakpoints utilisés ``info break`` - -Informations à extraire -^^^^^^^^^^^^^^^^^^^^^^^ - -Une fois un breakpoint placé, plusieurs informations peuvent être extraites via `gdb(1)`_ : - - * ``print [variablename]`` affiche la valeur de la variable dans son format de base. Il est possible de connaître la valeur pointée en utilisant ``*`` ainsi que l'adresse de la variable avec ``&``. - - .. code-block:: console - - Il est aussi possible de modifier une variable avec ``set variable [nom_variable] = [valeur]``. - De façon similaire avec ``print [nom_variable] = [valeur]``. - - * ``info reg [registre]`` affiche les informations sur tous les registres si aucun registre n'est explicitement spécifié. ``info reg eax`` donne le même résultat que ``print $eax``. - - .. code-block:: console - - Il est intéressant de noter qu'il est possible d'afficher une variable sous le format spécifié. Pour cela, remplacer ``print`` par : - * ``p/x`` - affiche en format hexadécimal la variable spécifiée - * ``p/d`` - en format entier signé - * ``p/f`` - en format floating point - * ``p/c`` - affiche un caractère. - - * ``backtrace`` ou ``bt`` affiche la pile des appels de fonctions. - - .. code-block:: console - - Il est possible de naviguer dans la pile des appels à l'aide de ``up`` et ``down``. Ces deux commandes montent et descendent respectivement dans la pile. C'est très utile car il est possible de modifier le contexte dans lequel on se trouve pour afficher les variables. - - * ``info frame`` donne des informations sur la frame actuelle. - - * ``list`` affiche les lignes de codes entourant le break. On peut donc facilement voir le code posant un problème ou analyser le code avant de faire une avancée pas à pas. - - * ``show args`` affiche les arguments passés au programme. - * ``info breakpoints`` affiche les breakpoints - * ``info diplays`` affiche les displays - * ``info func [fonctionname]`` affiche le prototype d'une fonction - -Avancement de l'exécution -^^^^^^^^^^^^^^^^^^^^^^^^^ - -Quand vous avez acquis suffisamment d'informations sur le programme, vous avez plusieurs choix pour continuer son exécution : - - * ``next`` exécute la prochaine instruction de votre code source, mais sans rentrer dans des fonctions externes. - * ``step`` exécute la prochaine instruction de votre code source, mais en entrant dans le code des fonctions appelées. - * ``continue`` continue le reste de l'exécution jusqu'au prochain breakpoint. - -Automatisation -^^^^^^^^^^^^^^ - -Lors d'un débuggage long et fastidieux, il est parfois nécessaire d'exécuter certaines commandes à chaque breakpoint. - - * ``commands [numerobreakpoint]`` definit une liste de commandes associées à un breakpoint. Celles ci seront exécutées quand on s'arrêtera sur ce breakpoint. Il suffit de taper les commandes à effectuer les unes après les autres et de terminer par ``end``. Si vous ne fournissez pas de numéro, les commandes sont assignées au dernier breakpoint créé. - * ``display [variablename]`` affiche la variable à chaque breakpoint. - -Gestion des Signaux -^^^^^^^^^^^^^^^^^^^ - -En plus des breakpoints, `gdb(1)`_ interrompt l'exécution du programme en cours lorsqu'il intercepte certains signaux d'erreurs comme les signaux ``SIGSEGV`` et ``SIGINT``. `gdb(1)`_ permettra alors de corriger plus facilement certaines erreurs comme les erreurs de segmentation ou les problèmes de deadlocks. - -Il est possible de gérer le comportement de `gdb(1)`_ lorsque des signaux sont interceptés. Tout d'abord, la commande ``info signals`` permet d'afficher la liste des signaux reconnus par `gdb(1)`_ ainsi que la façon dont il les traite (par exemple interrompre le programme en cours ou non). On peut changer la façon de traiter un signal avec la commande ``handle [SIGNAL] [HANDLING...]`` où ``[SIGNAL]`` est le signal à intercepter (son numéro ou son nom complet) et ``[HANDLING]`` la façon de traiter ce signal par `gdb(1)`_ [#fSigList]_. Par exemple, la commande ``handle SIGALRM stop print`` permet d'interrompre le programme et d'afficher un message quand gdb intercepte le signal ``SIGALRM``. - -Localiser un signal -""""""""""""""""""" - -Avec `gdb(1)`_, il est possible de localiser un signal et de débugguer certaines erreurs comme une erreur de segmentation. En effet, lorsque `gdb(1)`_ interrompt le programme en cours après l'interception d'un signal d'erreur comme ``SIGSEGV``, il est possible de trouver la ligne du programme à laquelle le signal a été intercepté en tapant le mot-clé ``where`` une fois le programme interrompu (il est cependant nécessaire d'avoir compilé le programme avec l'option ``-g`` de ``gcc`` pour trouver la ligne précise). Ensuite, grâce aux commandes expliquées plus tôt, il est possible de vérifier les valeurs des variables lors de l'interception du signal pour trouver l'origine du problème. - -En plus de localiser facilement les erreurs de segmentation dans un programme, vous pourrez annalyser plus aisément les problèmes de deadlock des threads. En effet, lorsque le programme est lancé sur le shell et que vous remarquez un deadlock, vous pouvez appuyer sur ``CTRL + C`` pour lancer le signal ``SIGINT`` au programme. Cela permettra de trouver les endroits où bloquent les différents threads du programme à l'aide des commandes décrites dans la section de débuggage des threads ci-dessous. - -Extraction de code assembleur -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - * ``disas`` affiche le code assembleur - * ``disas /m blah`` met en correspondance le code assembleur et le code source - -Pour arrêter la console de gdb, tappez ``quit``. - - -Illustration avec des exemples ------------------------------- - -.. A titre d'exemple, télécharger l'archive :download:`src/gdb.c`. L'archive contient un Makefile qui vous permettra de compiler plusieurs programmes. - -Premier programme -^^^^^^^^^^^^^^^^^ - - Le premier programme est :download:`src/calc.c`. Compilez-le et exécutez le pour vous apercevoir que le programme est erroné. A priori vous avez peu, ou pas, d'informations sur l'erreur. Lancez donc gdb à l'aide de ``gdb calc`` puis lancez le programme avec ``run``. - - .. code-block:: console - - Program received signal SIGFPE, Arithmetic exception. => Exception arithmetique - 0x0000000000400553 in calc (a=165, b=4) at calc.c:10 => Dans la fonction calc du fichier calc.c à la ligne 10 - - 10 res = (a*5 -10) / (b-i); => Affichage de la ligne problématique - - Le premier réflexe doit être ``list`` pour observer le code. Puisque le problème vient de la ligne 10 dans la boucle, nous allons nous arrêter à la ligne 10 avec ``break 10`` et relancer le programme. - Le programme va s'arrêter avant le début de la boucle. Utilisez ``print a`` et ``print b`` pour connaître les arguments reçus par calc. - - .. code-block:: console - - - Il est intéressant de noter une particularité du language C par rapport à java : une variable déclarée n'est pas initialisée à 0 par défaut, elle reprend juste la valeur de la mémoire avant son affectation. ``print i`` et ``print res`` vous donneront donc des résultats aléatoires. - - - Puisque le problème vient du calcul arithmétique, placez un break sur cette ligne pour pouvoir observer à chaque itération les variables. ``break 9`` puis ``commands`` qui permet d'automatiser des commandes. Nous rajouterons comme commandes : - - .. code-block:: none - - * ``echo i : `` - * ``print i`` - * ``echo b : `` - * ``print b`` - * ``echo numerateur : `` - * ``print a*5 -10`` - * ``echo denominateur : `` - * ``print b-i`` - * et enfin ``end`` pour terminer la liste de commandes. - - Il ne reste plus qu'à avancer avec ``continue`` pour aller de breakpoint en breakpoint et d'observer les variables pour comprendre le problème. On va pouvoir deviner que le problème vient d'un dénominateur nul. Pour résoudre ce problème, il faut passer une valeur plus grande que 6 à calc lors de son appel depuis la fonction main. ``list main`` suivi de plusieurs ``list`` permet de visualiser la main. On peut repérer l'appel de la fonction calc à la ligne 18. - - Supprimez les anciens break avec ``delete [numerobreakpoint]`` le numéro du breakpoint est connu via ``info break``. Rajoutez un break à la ligne 18, ``break 18`` et lancez le programme. ``set variable m = 10`` pour assigner la valeur 10 à la variable m. Puis continuez l'exécution du programme. Celui se terminera normalement puisque il n'y a plus de division par zéro. - - -Deuxième programme -^^^^^^^^^^^^^^^^^^ - - Le deuxième programme est appelé :download:`src/recursive.c`. Celui ne présente aucun bug et se déroulera normalement. Toutefois, il est intéressant d'utiliser `gdb(1)`_ pour bien comprendre les différents contextes au sein d'un programme. Mettez un break sur la fonction factTmp avec ``break factTmp`` et ajoutez automatiquement à ce breakpoint la commande ``backtrace``, via ``commands``. Ensuite, lancez le programme. - ``backtrace`` vous permet de visualiser les appels de fonction effectués. Nous pouvons voir que la fonction factTmp a été appellée par factTerminal, elle même appellée par la fonction main. - - .. code-block:: console - - #0 factTmp (acc=1, nbr=6) at recursive.c:8 - #1 0x000000000040057d in factTerminal (a=6) at recursive.c:17 - #2 0x0000000000400598 in main (argc=1, argv=0x7fffffffe1b8) at recursive.c:23 - - Essayez d'afficher les variable ``globalVar`` puis ``localVar``. Vous remarquerez qu'il n'est pas possible d'afficher ``localVar`` puisque cette variable ne fait pas partie de l'environement contextuel de factTmp. Pour afficher cette variable, il faut remonter la liste des appels. ``up`` permettra de remonter les appels pour pouvoir afficher ``localVar``. - Une fois la variable affichée, redescendez avec ``down`` et continuez 4 fois le programme après le breakpoint. Vous remarquerez que la liste des appels s'allonge à chaque appel récursif, ce qui est tout à fait normal. - - Naviguez dans les appels recursifs de factTmp en affichant les valeur de ``globalTmp``, ``tmp``, ``acc`` et ``nbr``. Il est important de bien comprendre que la variable statique ``globalTmp`` est commune à tous les appels de la fonction ``factTmp`` et un changement de cette variable dans un des appels récursifs modifie la variable des autres appels. A contrario, la variable local ainsi que les arguments sont propres à chaque appel. - - Vous pouvez maintenant terminer le programme. - - -Troisième programme -^^^^^^^^^^^^^^^^^^^ - - Le troisième programme est :download:`src/tab.c`. Compilez-le. Ce programme s'exécute correctement, et pourtant, il y contient une erreur. Lancez le programme avec gdb et mettez un breakpoint sur la première instruction, à savoir la ligne 9. Pour comprendre un problème sans savoir où commencer, il est utile de suivre l'évolution des variables. - - .. code-block:: console - - Il est important de savoir que ``print``, ainsi que ``display``, supportent les expressions telles que : - * tab[1], tab[i],... - * &i, *i,... - - Avancez instruction par instruction, avec ``step`` ou ``next`` et portez attention aux valeurs de tab[i] par rapport à i. Une fois le problème trouvé avec gdb, solutionnez le. - - - -Plus d'informations sur `gdb(1)`_ peuvent être trouvées sur: - - * http://www.cprogramming.com/gdb.html - * http://www.ibm.com/developerworks/library/l-gdb/ - * https://www.rocq.inria.fr/secret/Anne.Canteaut/COURS_C/gdb.html - - -Débuggage des threads avec GDB ------------------------------- - -`gdb(1)`_ est aussi utile pour débugger des programmes avec des threads. Il permet de faire les opérations suivantes sur les threads: - - * Etre notifié lors de la création d'un nouveau thread. - * Afficher la liste complète des threads avec ``info threads``. - * Placer un breakpoint dans un thread. En effet, si vous placez un breakpoint dans une certaine fonction, et un thread passe lors de son exécution à travers ce breakpoint, ``gdb`` va mettre l'exécution de tous les threads en pause et changer le contexte de la console `gdb(1)`_ vers ce thread. - * Lorsque les threads sont en pause, vous pouvez manuellement donner la main à un thread en faisant ``thread [thread_no]`` avec ``thread_no`` étant l'indice du thread comme indiqué par ``info threads`` - -D'autres commandes pour utiliser `gdb(1)`_ avec les threads: - * http://sourceware.org/gdb/current/onlinedocs/gdb/Threads.html - - -.. rubric:: Footnotes - -.. [#fSigList] Une liste plus complète des mots-clés utilisables pour modifier le comportement de gestion des signaux peut-être consultée ici : ftp://ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_38.html . diff --git a/Outils/git.rst b/Outils/git.rst deleted file mode 100644 index 43ae7eac4a41756e81336553c61e755c73655568..0000000000000000000000000000000000000000 --- a/Outils/git.rst +++ /dev/null @@ -1,2369 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2013 by Benoit Legat -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Git ---- - -Introduction -~~~~~~~~~~~~ - -`Git`_ a été développé initialement pour la gestion du code source du kernel Linux. -Il est aussi utilisé pour la gestion des sources de ce document -depuis https://github.com/obonaventure/SystemesInformatiques. -On l'utilise le plus souvent à l'aide de l'utilitaire `git(1)`_ mais il -existe aussi des -`applications graphiques <http://git-scm.com/downloads/guis>`_. - -Les différentes versions sont enregistrées dans des commits qui sont liées -au commit constituant la version précédente. -On sait ainsi facilement voir ce qui a changé entre deux versions -(pas spécialement, une version et la suivante) -et même restaurer l'état de certains fichiers à une version sauvegardée -dans un commit. -Du coup, si vous utilisez `Git`_ pour un projet, vous ne pouvez jamais -perdre plus que les changements que vous n'avez pas encore committé. -Toutes les versions du codes déjà committées sont sauvegardées et facilement -accessibles. -Cette garantie est extrêmement précieuse et constitue à elle seule une raison -suffisante d'utiliser `Git`_ pour tous vos projets. - -Contrairement à `subversion`_, il est décentralisé, c'est à dire que chaque -développeur a toute l'information nécessaire pour utiliser `Git`_, -il ne doit pas passer par un serveur où les données sont centralisées à -chaque commande. -Cela prend éventuellement plus d'espace disque mais comme on travaille -avec des documents de type texte, ce n'est pas critique. -Les avantages, par contre, sont nombreux. -On a pas besoin d'être connecté au serveur pour l'utiliser, -il est beaucoup plus rapide -et chaque développeur constitue un backup du code, ce qui est confortable. - -De plus, comme on va le voir, `Git`_ supporte une gestion des commits -très flexible avec un historique pas linéaire -mais composés de plusieurs branches et il -permet aux développeurs de ne pas avoir toutes les branches en local. - -Cette efficacité de `Git`_ et sa flexibilité sont ses arguments majeurs et -leur origine est évidente quand on sait qu'il a été créé pour gérer des projets -aussi complexes que le kernel Linux. -Il est parfois critiqué pour sa complexité mais c'est surtout dû au fait -qu'il a une façon assez différente de fonctionner des autres. - -.. FIXME je dis "historique" ou "arborescence" ? sur le wikipedia - français, ils disent "arborescence :/ (http://fr.wikipedia.org/wiki/Git) - Pour svn, historique est le bon terme mais pour Git... - Je dis "dépôt" ou "repository" ? - -Utilisation linéaire de Git -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -On peut utiliser `Git`_ à plusieurs niveaux. -On peut tout à fait avoir un historique linéaire tout en profitant pleinement -de `Git`_. -Pour ceux dont c'est la première fois qu'ils utilisent un système de contrôle -de version, -il vaut peut-être mieux commencer par ne lire que cette partie et -déjà l'utiliser de façon plus basique pour le premier projet et -lire les parties suivantes une fois que vous voulez consolider -votre connaissance et apprendre plus en détails comment ça fonctionne -sans toutefois voir toutes ses possibilités. -Toutefois, la lecture de cette partie n'est pas nécessaire pour comprendre -les parties suivantes donc si vous voulez juste parfaire votre -connaissance, vous pouvez la passer sans crainte. - -Créer un historique linéaire -############################ - -Un historique linéaire est un historique comme on l'imagine avec des versions -l'une après l'autre, chaque version étendant la précédente avec -certaines modifications. -On verra par après qu'il est possible d'avoir un historique non-linéaire -avec `Git`_ mais ce n'est pas indispensable. - -Sur `Git`_, on appelle une version un *commit*. -Chacun de ces commits est documenté en fournissant le nom de l'auteur, -son email, un commentaire et une description (optionnelle). -Pour ne pas devoir respécifier le nom et l'email à chaque fois, -on le stoque dans le fichier de configuration de `Git`_ ``~/.gitconfig``. -Bien qu'on peut l'éditer manuellement, on préfère le faire à l'aide de -la commande `git-config(1)`_. - -Pour spécifier le commentaire, -`git-commit(1)`_ ouvrira un éditeur de texte. -Pour entrer une description, laissez une ligne vide puis écrivez la. -L'éditeur de texte à ouvrir est déterminé par `Git`_ en fonction de la variable -``core.editor`` du fichier de configuration mentionné plus haut. -Vous pouvez aussi spécifier le commentaire à l'aide de l'option ``-m`` -de `git-commit(1)`_ comme on verra dans les exemples par après. - -Voici les commandes à exécuter pour configurer le nom, l'email et l'éditeur -de texte. -Vous devez bien entendu remplacer les valeurs par celles qui vous conviennent. - -.. code-block:: bash - - $ git config --global user.name "Jean Dupont" - $ git config --global user.email jean@dupont.com - $ git config --global core.editor gedit - -L'option ``--global`` spécifie qu'on veut que ces configurations s'appliquent -pour tous nos dépôts (`Git`_ éditera le fichier ``~/.gitconfig``). -Sinon, `git-config(1)`_ ne modifie que le fichier -``.git/config`` à l'intérieur du *git directory* du projet en cours. -Ce dernier prône bien entendu sur ``~/.gitconfig`` quand une variable -a des valeurs différentes dans ``~/.gitconfig`` et ``.git/config``. - -Vous voilà paré pour créer votre premier dépôt `Git`_ -mais avant de voir comment faire des nouveaux commits, -il est impératif de comprendre ce qu'est la *staging area*. - -Il y a 3 états dans lequel un fichier peut-être, - - il peut être dans le *working directory*, - c'est à dire que c'est le fichier tel qu'il est actuellement dans le code; - - il peut être dans la *staging area*, - c'est à dire que ses changements seront pris en compte dans le prochain - commit; - - et il peut être dans le *git directory*, c'est à dire sauvegardé dans - un commit à l'intérieur du dossier ``.git``. - -Pour committer des changements, on les mets d'abord dans la -*staging area* puis on commit. -Cette flexibilité permet de ne pas committer -tout les changements du *working directory*. - -Voyons tout ça avec un programme exemple qui affiche en LaTex -la somme des entiers de :math:`1` à :math:`n`. -On va utiliser les commandes - - * `git-init(1)`_ qui permet de transformer un projet en dépôt `Git`_ - (tout est stoqué dans le dossier ``.git``); - * `git-diff(1)`_ qui donne la différence entre l'état des fichiers dans le - *working directory* avec leur état dans le *git directory* - au commit actuel; - * `git-status(1)`_ qui affiche les fichiers modifiés et ceux qui vont être - commités; - * `git-add(1)`_ qui spécifie quels fichiers doivent faire partie du prochain - commit en les ajoutant à la *staging area*; - * `git-commit(1)`_ qui commit les fichiers dans la *staging area*; - * et `git-log(1)`_ qui montre tous les commits de l'historique. - -La première version sera la suivante - -.. code-block:: c - - #include <stdio.h> - #include <stdlib.h> - - int main (int argc, char *argv[]) { - long int sum = 0, i, n = 42; - for (i = 1; i <= n; i++) { - sum += i; - } - printf("\\sum_{i=1}^{%ld} i = %ld\n", n, sum); - return EXIT_SUCCESS; - } - -Ce programme fonctionne comme suit - -.. code-block:: bash - - $ gcc main.c - $ ./a.out - \sum_{i=1}^{42} i = 903 - -On va sauvegarder un premier commit contenant cette version de ``main.c`` - -`git-init(1)`_ permet d'initialiser le dépôt `Git`_. -`git-status(1)`_ analyse le contenu du répertoire. -Il indique que le fichier ``main.c`` n'est pas suivi par `Git`_ (`untracked`). -Ce fichier est ajouté avec la commande `git-add(1)`_. -`git-commit(1)`_ sauvegarde cette version du code dans un commit -dont le commentaire, spécifié avec l'option ``-m``, est *First commit*. - -.. code-block:: bash - - $ git init - Initialized empty Git repository in /path/to/project/.git/ - $ git status - # On branch master - # - # Initial commit - # - # Untracked files: - # (use "git add <file>..." to include in what will be committed) - # - # main.c - nothing added to commit but untracked files present (use "git add" to track) - $ git add main.c - $ git status - # On branch master - # - # Initial commit - # - # Changes to be committed: - # (use "git rm --cached <file>..." to unstage) - # - # new file: main.c - # - $ git commit -m "First commit" - [master (root-commit) 3d18efe] First commit - 1 file changed, 11 insertions(+) - create mode 100644 main.c - $ git log - commit 3d18efe4df441ebe7eb2b8d0b78832a3861dc05f - Author: Benoît Legat <benoit.legat@gmail.com> - Date: Sun Aug 25 15:32:42 2013 +0200 - - First commit - -Modifions maintenant le programme pour qu'il prenne la valeur de -:math:`n` dans ``argv``. -Si on compile le programme après modification, et qu'on exécute avec -en argument :math:`10` puis :math:`9.75`, on obtient ce qui suit - -.. code-block:: bash - - $ gcc main.c - $ ./a.out 10 - \sum_{i=1}^{10} i = 55 - $ ./a.out 9.75 - $ echo $? - 1 - -On peut maintenant voir avec `git-status(1)`_ que le fichier ``main.c`` -a été modifié - -.. code-block:: bash - - $ git status - # On branch master - # Changes not staged for commit: - # (use "git add <file>..." to update what will be committed) - # (use "git checkout -- <file>..." to discard changes in working directory) - # - # modified: main.c - # - no changes added to commit (use "git add" and/or "git commit -a") - -Avec `git-diff(1)`_, on peut voir quelles sont les lignes qui ont été -retirées (elles commencent par un ``-``) et celles qui ont été ajoutées -(elles commencent par un ``+``). - -.. code-block:: diff - - $ git diff - diff --git a/main.c b/main.c - index 86601ed..a9e4c4a 100644 - --- a/main.c - +++ b/main.c - @@ -2,7 +2,12 @@ - #include <stdlib.h> - - int main (int argc, char *argv[]) { - - long int sum = 0, i, n = 42; - + long int sum = 0, i, n; - + char *end = NULL; - + n = strtol(argv[1], &end, 10); - + if (*end != '\0') { - + return EXIT_FAILURE; - + } - for (i = 1; i <= n; i++) { - sum += i; - } - -Ajoutons ``main.c`` aux modifications à mettre dans le prochain commit puis -créons ce commit - -.. code-block:: bash - - $ git add main.c - $ git commit -m "Read n from argv" - [master 56ce59c] Read n from argv - 1 file changed, 6 insertions(+), 1 deletion(-) - -On peut maintenant voir le nouveau commit dans l'historique affiché par -`git-log(1)`_ - -.. code-block:: bash - - $ git log - commit 56ce59c54726399c18b3f87ee23a45cf0d7f015d - Author: Benoît Legat <benoit.legat@gmail.com> - Date: Sun Aug 25 15:37:51 2013 +0200 - - Read n from argv - - commit 3d18efe4df441ebe7eb2b8d0b78832a3861dc05f - Author: Benoît Legat <benoit.legat@gmail.com> - Date: Sun Aug 25 15:32:42 2013 +0200 - - First commit - -On va maintenant s'occuper d'un *segmentation fault* qui arrive -quand il n'y a pas d'argument. - -.. code-block:: bash - - $ gcc main.c - $ ./a.out - Segmentation fault (core dumped) - -Pour cela, on va simplement vérifier la valeur de ``argc`` et utiliser :math:`42` comme -valeur par défaut. -`git-diff(1)`_ nous permet de voir les changements qu'on a fait - -.. code-block:: diff - - $ git diff - diff --git a/main.c b/main.c - index a9e4c4a..e906ea1 100644 - --- a/main.c - +++ b/main.c - @@ -2,11 +2,13 @@ - #include <stdlib.h> - - int main (int argc, char *argv[]) { - - long int sum = 0, i, n; - + long int sum = 0, i, n = 42; - char *end = NULL; - - n = strtol(argv[1], &end, 10); - - if (*end != '\0') { - - return EXIT_FAILURE; - + if (argc > 1) { - + n = strtol(argv[1], &end, 10); - + if (*end != '\0') { - + return EXIT_FAILURE; - + } - } - for (i = 1; i <= n; i++) { - sum += i; - -On va maintenant committer ces changement -dans un commit au commentaire *Fix SIGSEV* - -.. code-block:: bash - - $ git add main.c - $ git commit -m "Fix SIGSEV" - [master 7a26c63] Fix SIGSEV - 1 file changed, 6 insertions(+), 4 deletions(-) - $ git log - commit 7a26c6338c38614ce1c4ff00ac0a6895b57f15cb - Author: Benoît Legat <benoit.legat@gmail.com> - Date: Sun Aug 25 15:39:49 2013 +0200 - - Fix SIGSEV - - commit 56ce59c54726399c18b3f87ee23a45cf0d7f015d - Author: Benoît Legat <benoit.legat@gmail.com> - Date: Sun Aug 25 15:37:51 2013 +0200 - - Read n from argv - - commit 3d18efe4df441ebe7eb2b8d0b78832a3861dc05f - Author: Benoît Legat <benoit.legat@gmail.com> - Date: Sun Aug 25 15:32:42 2013 +0200 - - First commit - -Travailler à plusieurs sur un même projet -######################################### - -`Git`_ est déjà un outil très pratique à utiliser seul mais c'est quand -on l'utilise pour se partager du code qu'il devient vraiment indispensable. -On se partage le code par l'intermédiaire de *remotes*. -Ce sont en pratique des serveurs auxquels on peut avoir l'accès lecture et/ou -écriture. -On va traiter ici le cas où deux développeurs, Alice et Bob, -ont l'accès lecture et écriture. - -Alice va créer le projet avec - -.. code-block:: bash - - $ git init - Initialized empty Git repository in /path/to/project/.git/ - -puis elle créera une *remote*, c'est à dire un autre dépôt `Git`_ que celui -qu'ils ont en local, avec lequel ils vont pouvoir synchroniser leur -historique. -Supposons qu'ils aient un projet *projectname* sur Github. -Vous pouvez créer le *remote* comme suit - -.. code-block:: bash - - $ git remote add https://github.com/alice/projectname.git - -Ensuite, vous pourrez obtenir les modifications de l'historique du *remote* -avec ``git pull origin master`` -et ajouter vos modifications avec ``git push origin master``. - -Si vous exécutez ``git pull origin master``, que vous faites quelques -commits et puis que vous essayer de mettre *origin* à jour avec -``git push origin master``, -il faut qu'aucun autre développeur n'ait pushé de modification entre temps. -S'il en a pushé, `Git`_ ne saura pas effectuer votre *push*. -Il vous faudra alors faire un *pull*. -`Git`_ tentera alors de fusionner vos changements avec ceux d'*origin*. -Si ces derniers sont à une même ligne d'un même fichier, il vous demandera -de résoudre le conflit vous-même. -Il est important pour cela que vous ayez commité vos changements avant -le *pull* sinon `Git`_ l'abandonnera car il ne sait que fusionner des commits. -C'est à dire que ce qu'il y a dans le *git directory*, -pas ce qu'il y a dans le *working directory* ni dans la *staging area*. - -Prenons un exemple où Bob *push* en premier puis Alice doit résoudre -un conflit. -Alice commence avec le fichier ``main.c`` suivant - -.. code-block:: c - - #include <stdio.h> - #include <stdlib.h> - - int main (int argc, char *argv[]) { - } - -Elle fait le premier commit du projet - -.. code-block:: bash - - $ git add main.c - $ git commit -m "Initial commit" - [master (root-commit) 80507e3] Initial commit - 1 file changed, 5 insertions(+) - create mode 100644 main.c - -et va maintenant le *pusher* sur le serveur - -.. code-block:: bash - - $ git push origin master - Counting objects: 3, done. - Delta compression using up to 4 threads. - Compressing objects: 100% (2/2), done. - Writing objects: 100% (3/3), 282 bytes, done. - Total 3 (delta 0), reused 0 (delta 0) - To https://github.com/alice/projectname.git - * [new branch] master -> master - -Bob clone alors le projet pour en avoir une copie en local -ainsi que tout l'historique et la remote *origin* déjà configurée - -.. code-block:: bash - - $ git clone https://github.com/alice/projectname.git - Cloning into 'projectname'... - remote: Counting objects: 3, done. - remote: Compressing objects: 100% (2/2), done. - remote: Total 3 (delta 0), reused 3 (delta 0) - Unpacking objects: 100% (3/3), done. - $ git remote -v - origin https://github.com/alice/projectname.git (fetch) - origin https://github.com/alice/projectname.git (push) - -Ensuite, il ajoute ses modifications - -.. code-block:: diff - - $ git diff - diff --git a/main.c b/main.c - index bf17640..0b0672a 100644 - --- a/main.c - +++ b/main.c - @@ -2,4 +2,5 @@ - #include <stdlib.h> - - int main (int argc, char *argv[]) { - + return 0; - } - -et les commit - -.. code-block:: bash - - $ git add main.c - $ git commit -m "Add a return statement" - [master 205842a] Add a return statement - 1 file changed, 1 insertion(+) - -et les push sur le serveur - -.. code-block:: bash - - $ git push origin master - Counting objects: 5, done. - Delta compression using up to 4 threads. - Compressing objects: 100% (2/2), done. - Writing objects: 100% (3/3), 291 bytes, done. - Total 3 (delta 1), reused 0 (delta 0) - To https://github.com/alice/projectname.git - 80507e3..205842a master -> master - -Pendant ce temps là , Alice ne se doute de rien et -fait ses propres modifications - -.. code-block:: diff - - $ git diff - diff --git a/main.c b/main.c - index bf17640..407cd8a 100644 - --- a/main.c - +++ b/main.c - @@ -2,4 +2,5 @@ - #include <stdlib.h> - - int main (int argc, char *argv[]) { - + return EXIT_SUCCESS; - } - -puis les commit - -.. code-block:: bash - - $ git add main.c - $ git commit -m "Add missing return statement" - [master 73c6a3a] Add missing return statement - 1 file changed, 1 insertion(+) - -puis essaie de les pusher - -.. code-block:: bash - - $ git push origin master - To https://github.com/alice/projectname.git - ! [rejected] master -> master (non-fast-forward) - error: failed to push some refs to 'https://github.com/alice/projectname.git' - hint: Updates were rejected because the tip of your current branch is behind - hint: its remote counterpart. Merge the remote changes (e.g. 'git pull') - hint: before pushing again. - hint: See the 'Note about fast-forwards' in 'git push --help' for details. - -mais `Git`_ lui fait bien comprendre que ce n'est pas possible. -En faisant le *pull*, on voit que `Git`_ fait de son mieux pour -fusionner les changements mais qu'il préfère nous laisser -choisir quelle ligne est la bonne - -.. code-block:: bash - - $ git pull origin master - remote: Counting objects: 5, done. - remote: Compressing objects: 100% (1/1), done. - remote: Total 3 (delta 1), reused 3 (delta 1) - Unpacking objects: 100% (3/3), done. - From https://github.com/alice/projectname - 80507e3..205842a master -> origin/master - Auto-merging main.c - CONFLICT (content): Merge conflict in main.c - Automatic merge failed; fix conflicts and then commit the result. - -Il marque dans ``main.c`` la ligne en conflit et ce qu'elle vaut -dans les deux commits - -.. code-block:: c - - #include <stdio.h> - #include <stdlib.h> - - int main (int argc, char *argv[]) { - <<<<<<< HEAD - return EXIT_SUCCESS; - ======= - return 0; - >>>>>>> 205842aa400e4b95413ff0ed21cfb1b090a9ef28 - } - -On peut retrouver les fichiers en conflits dans -``Unmerged paths`` - -.. code-block:: bash - - $ git status - # On branch master - # You have unmerged paths. - # (fix conflicts and run "git commit") - # - # Unmerged paths: - # (use "git add <file>..." to mark resolution) - # - # both modified: main.c - # - no changes added to commit (use "git add" and/or "git commit -a") - -Il nous suffit alors d'éditer le fichier pour lui donner le contenu -de la fusion - -.. code-block:: c - - #include <stdio.h> - #include <stdlib.h> - - int main (int argc, char *argv[]) { - return EXIT_SUCCESS; - } - -puis de le committer - -.. code-block:: bash - - $ git add main.c - $ git commit - [master eede1c8] Merge branch 'master' of https://github.com/alice/projectname - -On peut alors mettre le serveur à jour - -.. code-block:: bash - - $ git push origin master - Counting objects: 8, done. - Delta compression using up to 4 threads. - Compressing objects: 100% (3/3), done. - Writing objects: 100% (4/4), 478 bytes, done. - Total 4 (delta 2), reused 0 (delta 0) - To https://github.com/alice/projectname.git - 205842a..eede1c8 master -> master - -Paul peut alors récupérer les changements avec - -.. code-block:: bash - - $ git pull origin master - remote: Counting objects: 8, done. - remote: Compressing objects: 100% (1/1), done. - remote: Total 4 (delta 2), reused 4 (delta 2) - Unpacking objects: 100% (4/4), done. - From https://github.com/alice/projectname - 205842a..eede1c8 master -> origin/master - Updating 205842a..eede1c8 - Fast-forward - main.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -La plupart des fusions ne demande pas d'intervention manuelle mais -dans les cas comme celui-ci, -`Git`_ n'a pas d'autre choix que de nous demander notre avis. - -Contribuer au syllabus -###################### - -Dans le cas du syllabus, vous n'avez pas l'accès écriture. -La manière dont Github fonctionne pour règler ça c'est que vous *forkez* le -projet principal. -C'est à dire que vous en faites un copie indépendante à votre nom. -À celle là vous avez l'accès écriture. -Vous allez ensuite soumettre vos changements sur celle là puis les -proposer à travers l'interface de Github qu'on appelle *Pull request*. -Conventionnellement, on appelle la *remote* du dépôt principal *upstream* -et la votre *origin*. - -Commencez donc par vous connecter sur Github, allez à -l'`adresse du code du syllabus -<https://github.com/obonaventure/SystemesInformatiques/>`_ et cliquez -sur *Fork*. - -Vous pouvez maintenant obtenir le code du syllabus avec la commande -`git-clone(1)`_ -(remplacez ``username`` par votre nom d'utilisateur sur Github) - -.. code-block:: bash - - $ git clone https://github.com/username/SystemesInformatiques.git - -Vous pouvez alors faire les changements que vous désirez puis les committer -comme expliqué à la section précédente. -Il est utile de garder le code à jour avec *upstream*. -Pour cela, il faut commencer par ajouter la remote - -.. code-block:: bash - - $ git remote add upstream https://github.com/obonaventure/SystemesInformatiques.git - -À chaque fois que vous voudrez vous mettre à jour, utilisez `git-pull(1)`_ - -.. code-block:: bash - - $ git pull upstream master - -Une fois vos changements commités, vous pouvez les ajouter à *origin* avec -`git-push(1)`_ - -.. code-block:: bash - - $ git push origin master - -Votre amélioration devrait normalement être visible via -`https://github.com/obonaventure/SystemesInformatiques/network <https://github.com/obonaventure/SystemesInformatiques/network>`_. -Vous pouvez maintenant aller sur Github à la page de votre fork et -cliquer sur *Pull Requests* puis *New pull request* et expliquer -vos changements. - -Si plus tard vous voulez encore modifier le syllabus, -il vous suffira de mettre à jour le code en local - -.. code-block:: bash - - $ git pull upstream master - -committer vos changements, les ajouter à *origin* - -.. code-block:: bash - - $ git push origin master - -puis faire un nouveau pull request. - -Utilisation non-linéaire de Git -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -`Git`_ peut créer un historique non-linéaire semblable à celui ci-dessous. -C'est un exemple un peu exagéré de non-linéarité mais il est -pédagogiquement intéressant. - -Cet historique forme un graphe orienté, -c'est à dire que les arêtes ont une direction. - -Les noeuds sont de 3 types, - - en bleu, on a les commits, c'est comme un snapshot, c'est une - description complète de l'état de tous les fichiers pris en - charge par `Git`_ à un moment donné. - Ces commits sont - - - soit construits comme la version suivante d'un autre commit - dans lequel cas il y a une seul arête partant du noeud, - - soit construits comme la fusion de deux commits - dans lequel cas il y a deux arêtes partant du noeud. - - Ils sont référés par un hash unique dont le début est affiché - sur la première ligne dans l'image ci-dessous - et non par un nombre - comme pour beaucoup d'autres systèmes de gestion de code - partagé. - Ils ont aussi un commentaire qui est affiché sur la deuxième ligne, - une description (optionnelle), un auteur et une date; - - en rouge, on a les branches, le nom est un peu trompeur car - c'est juste un pointeur vers un commit. - On pourrait tout à fait avoir un graphe non-linéaire sans - utiliser de branches, - c'est juste plus facile de référer les commits par le nom - d'une branche qui y réfère plutôt que par un hash sans signification; - - en vert, ce sont les tags, un tag est comme une branche qui - ne bouge pas, c'est à dire qu'il réfère toujours vers le même - commit. - C'est utile par exemple pour spécifier des versions d'un projet. - - en jaune, on a ``HEAD``, c'est un pointeur vers la branche active. - -.. figure:: figures/graph.png - :align: center - - Exemple d'historique. - -Manipulation de l'historique à travers les commandes Git -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Pour initialiser un dépôt `Git`_, -il suffit d'utiliser la commande `git-init(1)`_ - -.. code-block:: bash - - $ git init - Initialized empty Git repository in /path/to/project/.git/ - -À ce moment, l'historique est vide. - -Staging area -############ - -Commençons par définir les 4 statuts qu'un fichier peut avoir - - il peut être non-traqué par `Git`_, c'est à dire qu'il n'est - ni dans le *git directory*, ni dans la *staging area*. - C'est un fichier que le autres développeurs peuvent ne même pas être - au courant que vous l'avez dans votre *working directory*. - C'est souvent le cas des fichiers qui sont générés automatiquement, - et dont leur changement n'a donc aucun intérêt à être suivit. - Dans le cas d'un projet en C, - on aura les fichiers résultant de la compilation comme les fichiers objets - ``*.o``; - - il peut être non-modifié, c'est à dire que son état dans le - *working directory* est le même que celui dans le *git directory* au - commit actif (référencé par la branche active, - celle référencée par ``HEAD``) ainsi que celui dans la *staging area* - s'il y est; - - il peut être modifié, c'est à dire que sont état est différent dans le - *working directory* que celui dans le *git directory* au commit actif - ainsi que celui dans la *staging area* si il y est. - - il peut être *staged*, c'est à dire qu'il est dans la *staging area* - -Par exemple, prenons un fichier non-modifié. -Après des modifications, il a le statut modifié. -Si on le place dans la *staging area*, il acquière le statut *staged*. -Si on le modifie à nouveau, il aura le statut modifié mais -son état avec uniquement les premières modifications aura le statut *staged*. - -Pour obtenir l'information sur le statut de tous les fichiers, -utilisez `git-status(1)`_ - -.. code-block:: bash - - $ git status - # On branch master - # Changes to be committed: - # (use "git reset HEAD <file>..." to unstage) - # - # modified: main.c - # new file: file.c - # - # Changes not staged for commit: - # (use "git add <file>..." to update what will be committed) - # (use "git checkout -- <file>..." to discard changes in working directory) - # - # modified: main.c - # modified: Makefile - # - # Untracked files: - # (use "git add <file>..." to include in what will be committed) - # - # main.o - # file.o - # a.out - -Dans la partie ``Changes to be committed``, -on a les fichiers au statut *staged*. -Dans la partie ``Changes not staged for commit``, -on a les fichiers au statut modifié. -Les fichiers au statut non-modifié ne sont pas affichés et ceux non-trackés -sont dans la partie ``Untracked files`` sauf si on a spécifiquement demandé -de les ignorer dans le fichier ``.gitignore``. -En effet, on peut s'imaginer que dans un gros projet, la partie -``Untracked files`` peut devenir assez imposante et on ne sait plus -distinguer les fichiers qu'il faut penser à ajouter de ceux qu'il faut -ignorer une fois de plus. - -Lorsque `Git`_ voit un fichier ``.gitignore`` dans un dossier, -il en prend compte pour tous ses fichiers ainsi que tous les fichiers des -sous-dossiers. -La syntaxe est très simple, on spécifie un fichier par ligne, -on utilise un ``*`` pour spécifier n'importe -quelle chaine de charactères, les commentaires commencent par un ``#`` -comme en Bash et si la ligne commence par un ``!``, -on demande de ne pas ignorer ce fichier à l'intérieur du dossier même -si un ``.gitignore`` d'un dossier parent dit le contraire. -Dans notre exemple, ``.gitignore`` aura le contenu suivant - -.. code-block:: bash - - # Object files - *.o - # Executable - a.out - -Pour faire passer un fichier du statut modifié au status *staged*, -il faut utiliser `git-add(1)`_. -Lorsqu'on lui donne en argument un fichier modifié, elle ajoute sa version -avec toutes les modifications dans la *staging area*. -Si on lui donne un dossier, -elle ajoute tous les fichiers au statut modifié ou -au statut non-traqué qui ne sont pas ignoré par `Git`_. - -.. code-block:: bash - - $ git add . - -On peut aussi donner l'option ``-p`` à `git-add(1)`_, -`Git`_ demandera alors pour chaque bloc de modification s'il faut le prendre -en compte puis ajoutera dans la *staging area* un fichier avec toutes -ces modifications. -C'est très utile si on a fait différents changements dans un fichier mais -qu'on ne veut pas tout committer ou qu'on veut les séparer en différents -commits parce qu'ils font des choses différentes. -Par exemple, si j'ai un fichier ``main.c`` dans lequel j'ai rajouté -un ``return EXIT_SUCCESS;`` et un commentaire en début de fichier -mais que je n'ai envie que de faire passer le ``return EXIT_SUCCESS;`` -dans la *staging area*, il me suffit de faire - -.. code-block:: diff - - $ git add -p main.c - diff --git a/main.c b/main.c - index 7402a78..8381ce0 100644 - --- a/main.c - +++ b/main.c - @@ -1,3 +1,7 @@ - +/* - + * Print 'Hello world!' - + */ - + - // includes - #include <stdio.h> - #include <stdlib.h> - Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? n - @@ -5,4 +9,5 @@ - // main function - int main () { - printf("Hello world!\n"); - + return EXIT_SUCCESS; - } - Stage this hunk [y,n,q,a,d,/,K,g,e,?]? y - -On peut aussi faire retirer des fichier de la *staging area* avec la commande -`git-reset(1)`_. -``git reset`` les retire tous, -``git reset main.c`` retire uniquement ``main.c`` et on a à nouveau -l'option ``-p`` pour ne sélectionner qu'une partie. -Par exemple, si dans l'exemple précédent j'avais mis ``main.c`` entièrement -dans la *staging area* mais que je veux comme précédemment uniquement -mettre le ``return EXIT_SUCCESS;``, je peux soit faire ``git reset main.c`` -et puis faire ``git add -p main.c`` comme tout à l'heure, soit faire - -.. code-block:: diff - - $ git reset -p main.c - diff --git a/main.c b/main.c - index 7402a78..8381ce0 100644 - --- a/main.c - +++ b/main.c - @@ -1,3 +1,7 @@ - +/* - + * Print 'Hello world!' - + */ - + - // includes - #include <stdio.h> - #include <stdlib.h> - Unstage this hunk [y,n,q,a,d,/,j,J,g,e,?]? y - @@ -5,4 +9,5 @@ - // main function - int main () { - printf("Hello world!\n"); - + return EXIT_SUCCESS; - } - Unstage this hunk [y,n,q,a,d,/,K,g,e,?]? n - -Avant d'utiliser `git-add(1)`_ et `git-reset(1)`_, -il est utile de vérifier plus précisément ce qu'on a changé dans -les fichiers que `git-status(1)`_ nous dit qu'on a modifié. -C'est une des utilités de la commande `git-diff(1)`_. -Par défaut, elle calcule les changements entre le *working directory* -et la *staging area*, mais on peut aussi lui demander de regarder les -changements entre deux commits. -Si on ne lui dit rien, elle donne les changements de tous les fichiers mais -on peut lui demander de se limiter à un fichier ou à un dossier spécifique. -Dans notre exemple, - -.. code-block:: diff - - $ git diff main.c - diff --git a/main.c b/main.c - index 07e26bf..8381ce0 100644 - --- a/main.c - +++ b/main.c - @@ -1,3 +1,7 @@ - +/* - + * Print 'Hello world!' - + */ - + - // includes - #include <stdio.h> - #include <stdlib.h> - -On peut aussi lui demander de générer un patch, -c'est à dire un fichier qui contient les informations nécessaires pour -appliquer ce changement chez un autre développeur. -Ce n'est pas la manière la plus pratique de se partager les changements -comme on verra avec les *remotes* mais c'est utilisé. - -Commit -###### - -Voyons à présent comment committer -les fichiers présents dans la *staging area*. -Comme vu précédemment, -il y a toujours un commit actif, -c'est comparativement à ce dernier que `Git`_ détermine si un fichier est -modifié ou pas. - -Lorqu'on choisit de committer ce qu'il y a dans la *staging area*, -un nouveau commit est créé avec le même état que le précédent plus les -modifications des fichiers au statut *staged*. -Ce nouveau commit a une référence vers le commit précédent. -La branche active change alors de référence et pointe alors vers le nouveau -commit. -Aucune autre branche ne bouge, même celle qui référençait l'ancien commit. -On peut retenir qu'*il n'y a toujours que la branche active qui est modifée*. - -Dans notre exemple, -l'historique était comme l'image ci-dessous - -.. figure:: figures/hello_without_return.png - :align: center - - Historique avant le commit - - -.. code-block:: bash - - $ git commit -m "Add return" - [master 6e2f599] Add return - 1 file changed, 1 insertion(+) - -Après le commit, il est comme l'image ci-dessous. -On voit que la branche active a avancé alors que les autres n'ont pas bougé. - -.. figure:: figures/hello_with_return.png - :align: center - - Historique après le commit - -Lorsqu'on fait ``gcc main.c`` un fichier ``a.out`` est généré. -Il est inutile de suivre ses changements à travers `Git`_ car ses modifications -ne sont que l'image des modifications de ``main.c``. -De plus, ce n'est pas un fichier texte donc `Git`_ ne verra pas ce qui -a changé, il fera comme si tout ``a.out`` avait changé. - -.. code-block:: bash - - $ echo "a.out" > .gitignore - $ git status - # On branch master - # Changes not staged for commit: - # (use "git add <file>..." to update what will be committed) - # (use "git checkout -- <file>..." to discard changes in working directory) - # - # modified: main.c - # - # Untracked files: - # (use "git add <file>..." to include in what will be committed) - # - # .gitignore - no changes added to commit (use "git add" and/or "git commit -a") - $ git add .gitignore - $ git commit -m "Add .gitignore" - [master b14855e] Add .gitignore - 1 file changed, 1 insertion(+) - create mode 100644 .gitignore - -.. figure:: figures/hello_with_gitignore.png - :align: center - - Historique l'ajout de .gitignore - -Souvent, on a envie de committer tous les fichiers au statut *modifié*. -Si on fait ``git add .``, on ajoutera aussi tous les fichiers non-traqués -qui ne sont pas ignorés, c'est à dire ceux affichés par ``git status`` -en dessous de ``Untracked files``. -Si ça pose problème, on peut utiliser l'option ``-a`` de `git-commit(1)`_ -qui inclut tous les fichiers au statut *modifié* en plus de ceux dans la -*staging area* pour le commit. -On verra des exemples d'utilisation par après. - -Branching -~~~~~~~~~ - -Lorsqu'on exécute ``git init``, une branche au nom de ``master`` est créée. -Beaucoup de petits projets se contentent de cette branche et n'en font pas -d'autre mais c'est passer à côté d'un des aspects les plus pratiques de `Git`_. - -Une utilisation classique des branches sont les *feature branches*. -C'est à dire qu'on a la branche principale ``master`` qui contient un code -de toutes les fonctionnalités terminées. -Quand on essaie d'ajouter une -fonctionnalité (*feature* en anglais), on crée une nouvelle branche qu'on -ne fusionne avec ``master`` que lorsque le code est terminé. -Ça permet de pouvoir implémenter plusieurs fonctionnalités en parallèle sans -être gêné par l'instabilité du code créé par les fonctionnalités -en développement. -Ceci est encore plus vrai quand on travaille à plusieurs sur un même code -et sur les même fonctionnalités. - -Par exemple, supposons que vous soyez à 2 à travailler sur un projet. -L'un travaille sur une fonctionnalité, l'autre sur une autre. -À la base, le code sans ces deux fonctionnalités marchait mais comme -vous êtes en train d'en implémenter une nouvelle chacun, le code ne marche -chez aucun des deux développeurs. - -Créer une branche -################# - -Pour créer une branche, on utilise la commande `git-branch(1)`_. -`git-branch(1)`_ sert aussi à montrer la liste des branches avec -le caractère ``*`` devant la branche active. - -Par exemple, supposons qu'on veuille ajouter à notre exemple la possibilité -de changer le message un caractère plus universel pour que le programme soit -utilisable pour tout citoyen de l'univers. -Mais qu'on veut aussi ajouter un aspect pratique en rajoutant le pid -du processus et du processus parent. - -On commencera par créer deux *feature branches*, ``pid`` et ``universal``. -On supprime la branche ``hello`` qui servait juste à montrer qu'elle ne bougeait -pas quand on committait car ce n'était pas la branche active. - -.. code-block:: bash - - $ git branch - hello - * master - $ git branch pid - $ git branch universal - $ git branch -d hello - Deleted branch hello (was 76c1677). - $ git branch - * master - pid - universal - -L'historique ressemble maintenant à la figure suivante. -On voit que `git-branch(1)`_ ne modifie pas la branche active. - -.. figure:: figures/hello_branches.png - :align: center - - Historique après la création de ``pid`` et ``universal`` et - la suppression de ``hello`` - -On va d'ailleurs finalement committer notre commentaire en début de fichier -dans ``master``. On obtient alors la figure suivante - -.. code-block:: bash - - $ git s - # On branch master - # Changes not staged for commit: - # (use "git add <file>..." to update what will be committed) - # (use "git checkout -- <file>..." to discard changes in working directory) - # - # modified: main.c - # - no changes added to commit (use "git add" and/or "git commit -a") - $ git commit -a -m "Add intro" - [master c1f2163] Add intro - 1 file changed, 4 insertions(+) - -.. figure:: figures/hello_intro.png - :align: center - - Historique après avoir ajouté un commentaire d'introduction - -Changer la branche active -######################### - -On va maintenant voir comment changer la branche active, -c'est à dire la branche vers laquelle ``HEAD`` pointe. -Pour faire cela, on utilise `git-checkout(1)`_. - -.. code-block:: bash - - $ git checkout pid - Switched to branch 'pid' - $ git branch - master - * pid - universal - -`git-checkout(1)`_ ne fait pas que changer la branche active, il modifie -aussi le *working directory* pour refléter le commit référencé par la nouvelle -branche active. -Après le *checkout*, le contenu de ``main.c`` vaut - -.. code-block:: c - - // includes - #include <stdio.h> - #include <stdlib.h> - - // main function - int main () { - printf("Hello world!\n"); - return EXIT_SUCCESS; - } - -S'il y a des fichiers modifiés au moment du `git-checkout(1)`_, -`Git`_ va faire du mieux qu'il peut pour changer de branche en gardant -vos modifications mais si le fichier modifié est justement un fichier -qui diffère entre l'ancienne branche active et la nouvelle branche active, -`Git`_ va abandonner le changement de branche car mettre ce fichier à -la version de la nouvelle branche écraserait les modifications. - -Les changements doivent alors soit être committés, -soit sauvegardés par `git-stash(1)`_ (détailllé plus loin), -soit abandonnés. -Pour abandonner des changements et revenir à la version du commit référencé -par la branche active, on utilise aussi `git-checkout(1)`_. -Avec `Git`_, pas mal de commandes ont de multiples usages. - -Dans notre exemple, si on change ``main.c``, cela pose problème car il -diffère entre ``master`` et ``pid`` mais -si on change ``.gitignore``, ça n'en pose pas. -Il nous montre d'ailleurs que ``.gitignore`` a des modifications et qu'il -les a laissées lorsqu'on exécute ``git checkout master`` - -.. code-block:: bash - - $ echo "42" >> main.c - $ echo "42" >> .gitignore - $ git checkout master - error: Your local changes to the following files would be overwritten by checkout: - main.c - Please, commit your changes or stash them before you can switch branches. - Aborting - $ git checkout main.c - $ git checkout master - M .gitignore - Switched to branch 'master' - $ git checkout .gitignore # Retirons ce "42", c'était juste pour l'exemple - -Fusionner des branches -###################### - -Lorsqu'on fusionne deux branches, -le rôle de chaque branche n'est pas le même. -Il y a la branche active et la branche qu'on veut fusionner. -Par la règle *il n'y a toujours que la branche active qui est modifée*, -on sait que la branche qu'on veut fusionner ne va pas bouger. -Le but de la fusion, c'est de déplacer la branche active vers un commit -contenant les modifications faites par le commit référencé par la branche -active ainsi que celles faites par celui référencé par la branche qu'on veut -fusionner. -Par "modification", j'entends, les modifications faites depuis le premier -commit parent commun entre les deux commits en question. -Deux cas peuvent se présenter - - - soit ce commit parent est le commit référencé par la branche active, - dans lequel cas, on dira que la fusion est *fast-forward*. - `Git`_ fera alors simplement la branche active pointer vers le commit - référencé par la branche qu'on veut fusionner; - - soit ce commit parent est le commit référencé par la branche qu'on veut - fusionner, dans lequel cas, `Git`_ ne fera rien car le commit référencé - par la branche active contient déjà les modifications de l'autre puisque - c'est un de ses commits parents; - - soit ce commit est différent des deux commits en question. - Dans ce cas, `Git`_ créera un commit ayant deux parents, les deux commits - en questions et tentera de fusionner toutes les modifications depuis - le commit parent commun. - Bien entendu, plus ce commit commun est loin, plus il y aura de modification - et plus ce sera difficile. - C'est pourquoi on conseille de souvent fusionner la branche principale - pour éviter que la fusion de la *feature branch* soit trop compliquée - lorsque la fonctionnalité sera terminée. - - Là encore, il y a deux cas - - - soit `Git`_ arrive à tout fusionner, c'est à dire que les modifications - sont soit dans des fichiers différents, soit à des endroits bien - distincts d'un même fichier; - - soit il n'y arrive pas. Il fusionnera alors le plus possible lui-même - et marquera dans le fichier les confits à gérer à la main. - Il faudra alors ouvrir le fichier et régler puis avertir à `Git`_ - qu'il peut terminer la fusion. - En peut aussi dire qu'on abandonne la fusion et `Git`_ retire tout - ce qu'il a fait pour la fusion. - - Dans les deux cas, si on abandonne pas, `Git`_ créera ce commit - de fusion et fera pointer la branche active vers ce dernier. - -Il est important de réinsister sur le fait que -la branche non-active n'a pas été modifiée par la fusion. -Par contre si on la rend active et -qu'on demande de la fusionner avec l'ancienne branche active, -ce sera nécessairement une fusion *fast-forward*. - -`git-merge(1)`_ s'occupe de fusionner les branches -(fusionner se dit *merge* en anglais), -on lui donne en argument la branche à fusionner et la branche active est -bien entendu celle référencée par ``HEAD`` qui a été définie par -les appels à `git-checkout(1)`_. - -Dans notre exemple, on peut faire avancer ``pid`` et ``universal`` au niveau -de ``master`` avec une fusion *fast-forward*. - -.. code-block:: bash - - $ git checkout pid - Switched to branch 'pid' - $ git merge master - Updating b14855e..c1f2163 - Fast-forward - main.c | 4 ++++ - 1 file changed, 4 insertions(+) - $ git checkout universal - Switched to branch 'universal' - $ git merge master - Updating b14855e..c1f2163 - Fast-forward - main.c | 4 ++++ - 1 file changed, 4 insertions(+) - -On a alors la figure suivante - -.. figure:: figures/hello_2ff.png - :align: center - - Historique après avoir mis ``pid`` et ``universal`` à jour - -Commençons maintenant à développer notre compatibilité -avec le reste de l'univers. -On va rajouter une option ``--alien`` qui transforme le ``Hello world!`` -en ``Hello universe!`` - -.. code-block:: diff - - $ git diff - diff --git a/main.c b/main.c - index 8381ce0..8ccfa11 100644 - --- a/main.c - +++ b/main.c - @@ -5,9 +5,14 @@ - // includes - #include <stdio.h> - #include <stdlib.h> - +#include <string.h> - - // main function - -int main () { - - printf("Hello world!\n"); - +int main (int argc, char *argv[]) { - + if (strncmp(argv[1], "--alien", 8) == 0) { - + printf("Hello universe!\n"); - + } else { - + printf("Hello world!\n"); - + } - return EXIT_SUCCESS; - } - -Mettons tous les changements des fichiers traqués avec ``-a`` - -.. code-block:: bash - - $ git commit -a -m "Make it universal" - [universal 6c743f6] Make it universal - 1 file changed, 7 insertions(+), 1 deletion(-) - -Ce qui donne l'historique suivant - -.. figure:: figures/hello_make_universal.png - :align: center - - Historique après avoir committé ``Make it universal`` - -On va maintenant ajouter un ``Makefile`` qui compile puis exécute le programme -lorsqu'on écrit ``make``. -Comme un ``Makefile`` exécute la première règle, il suffit de mettre la règle -qui exécute en premier - -.. code-block:: makefile - - run: a.out - ./a.out - a.out: main.c - gcc main.c - -Ainsi, à chaque fois qu'on exécute la commande ``make``, la règle ``run`` -sera exécutée mais avant, ses dépendances donc ``a.out`` sera exécutée -si la date de modification de ``main.c`` -est plus récente que celle de ``a.out``. -Committons cela - -.. code-block:: bash - - $ git checkout master - Switched to branch 'master' - $ git status - # On branch master - # Untracked files: - # (use "git add <file>..." to include in what will be committed) - # - # Makefile - nothing added to commit but untracked files present (use "git add" to track) - $ git add Makefile - $ git commit -m "Add Makefile" - [master c35a8c3] Add Makefile - 1 file changed, 5 insertions(+) - create mode 100644 Makefile - -.. figure:: figures/hello_makefile.png - :align: center - - Historique après avoir committé ``Add Makefile`` - -On voit ici que pour ``pid``, -fusionner ``master`` est *fast-forward* et pas pour *universal*. -C'est ce qu'on va vérifier - -.. code-block:: bash - - $ git checkout universal - Switched to branch 'universal' - $ git merge master - Merge made by the 'recursive' strategy. - Makefile | 5 +++++ - 1 file changed, 5 insertions(+) - create mode 100644 Makefile - -On voit que `Git`_ a su faire la fusion sans notre aide sans problème -car tous les changements étaient dans le ``Makefile`` qui n'existait pas -pour ``universal`` - -.. figure:: figures/hello_universal_makefile.png - :align: center - - Historique après avoir fusionné ``master`` dans ``universal`` - -.. code-block:: bash - - $ git checkout pid - Switched to branch 'pid' - $ git merge master - Updating c1f2163..c35a8c3 - Fast-forward - Makefile | 5 +++++ - 1 file changed, 5 insertions(+) - create mode 100644 Makefile - -`Git`_ nous confirme que c'est *fast-forward* - -.. figure:: figures/hello_pid_makefile.png - :align: center - - Historique après avoir fusionné ``master`` dans ``pid`` - -Tant qu'on est sur la branche ``pid``, -implémentons la fonctionnalité comme suit - -.. code-block:: diff - - $ git diff - diff --git a/main.c b/main.c - index 8381ce0..b9043af 100644 - --- a/main.c - +++ b/main.c - @@ -5,9 +5,11 @@ - // includes - #include <stdio.h> - #include <stdlib.h> - +#include <unistd.h> - - // main function - int main () { - + printf("pid: %u, ppid: %u\n", getpid(), getppid()); - printf("Hello world!\n"); - return EXIT_SUCCESS; - } - -et committons la - -.. code-block:: bash - - $ git commit -a -m "Add pid/ppid info" - [pid eda36d7] Add pid/ppid info - 1 file changed, 2 insertions(+) - -.. figure:: figures/hello_ppid.png - :align: center - - Historique après avoir implémenté ``pid`` - -On peut maintenant fusionner ``pid`` dans master et la supprimer car on -en a plus besoin - -.. code-block:: bash - - $ git checkout master - Switched to branch 'master' - $ git merge pid - Updating c35a8c3..eda36d7 - Fast-forward - main.c | 2 ++ - 1 file changed, 2 insertions(+) - $ git branch -d pid - Deleted branch pid (was eda36d7). - -.. figure:: figures/hello_dpid.png - :align: center - - Historique après avoir fusionné et supprimé ``pid`` - -Retournons sur notre branche ``universal`` et essayons notre ``Makefile`` - -.. code-block:: bash - - $ git checkout universal - Switched to branch 'universal' - $ make - gcc main.c - ./a.out - make: *** [run] Segmentation fault (core dumped) - -Les deux premières lignes sont simplement les commandes que `make(1)`_ exécute. -La troisième est plus inquiètante. -Elle nous avertit que le programme a été terminé par le signal ``SIGSEV``. -C'est dû au fait qu'on ne vérifie pas que ``argv`` ait au moins 2 éléments -avant d'essayer accéder au deuxième élément. - -.. code-block:: diff - - $ git diff - diff --git a/main.c b/main.c - index 8ccfa11..f90b795 100644 - --- a/main.c - +++ b/main.c - @@ -9,7 +9,7 @@ - - // main function - int main (int argc, char *argv[]) { - - if (strncmp(argv[1], "--alien", 8) == 0) { - + if (argc > 1 && strncmp(argv[1], "--alien", 8) == 0) { - printf("Hello universe!\n"); - } else { - printf("Hello world!\n"); - -Ça marche maintenant sans *Segmentation fault* - -.. code-block:: bash - - $ make - gcc main.c - $ ./a.out - Hello world! - $ ./a.out --alien - Hello universe! - $ git commit -a -m "Fix SIGSEV without args" - [universal 6fd2e9b] Fix SIGSEV without args - 1 file changed, 1 insertion(+), 1 deletion(-) - -.. figure:: figures/hello_fix.png - :align: center - - Historique après avoir réparé le ``Segmentation fault`` - -``universal`` est maintenant prêt à être mergée. - -.. code-block:: bash - - $ git checkout master - Switched to branch 'master' - $ git merge universal - Auto-merging main.c - CONFLICT (content): Merge conflict in main.c - Automatic merge failed; fix conflicts and then commit the result. - -Les conflits sont marqués dans ``main.c`` - -.. code-block:: c - - /* - * Print 'Hello world!' - */ - - // includes - #include <stdio.h> - #include <stdlib.h> - <<<<<<< HEAD - #include <unistd.h> - - // main function - int main () { - printf("pid: %u, ppid: %u\n", getpid(), getppid()); - printf("Hello world!\n"); - ======= - #include <string.h> - - // main function - int main (int argc, char *argv[]) { - if (argc > 1 && strncmp(argv[1], "--alien", 8) == 0) { - printf("Hello universe!\n"); - } else { - printf("Hello world!\n"); - } - >>>>>>> universal - return EXIT_SUCCESS; - } - -Il nous faut maintenant éditer ``main.c`` pour résoudre le conflit. -Il n'y a un conflit à un seul endroit du fichier mais le conflit est assez -large, `Git`_ nous montre ce qu'il y a pour ``HEAD`` c'est à dire -la branche active ``master`` et ce qu'il y a pour ``universal``. -On va devoir prendre un peu des deux. - -Si on fait `git-diff(1)`_ par la suite, `Git`_ met en début de ligne un -``+`` ou un ``-`` en premier caractère -si c'est une ligne qui vient de la branche qu'on veut fusionner, -en deuxième caractère si ça vient de la branche active et en premier et -deuxième caractère si ça vient d'aucune des deux pour le ``+``. - -.. code-block:: diff - - $ git diff - diff --cc main.c - index b9043af,f90b795..0000000 - --- a/main.c - +++ b/main.c - @@@ -5,11 -5,14 +5,17 @@@ - // includes - #include <stdio.h> - #include <stdlib.h> - +#include <unistd.h> - + #include <string.h> - - // main function - - int main () { - + int main (int argc, char *argv[]) { - + printf("pid: %u, ppid: %u\n", getpid(), getppid()); - - printf("Hello world!\n"); - ++ - + if (argc > 1 && strncmp(argv[1], "--alien", 8) == 0) { - + printf("Hello universe!\n"); - + } else { - + printf("Hello world!\n"); - + } - return EXIT_SUCCESS; - } - -Il n'y a pas besoin de spécifier de commentaire pour une fusion car -`Git`_ en génère un automatiquement - -.. code-block:: bash - - $ git commit -a - [master 0dd6cd7] Merge branch 'universal' - -.. figure:: figures/hello_merge_universal.png - :align: center - - Historique après avoir fusionné la branche ``universal`` - -On voit que la branche ``universal`` est restée à sa place car ce n'était -pas la branche active. -On peut d'ailleurs maintenant la supprimer - -.. code-block:: bash - - $ git branch -d - Deleted branch universal (was 6fd2e9b). - -Autres commandes utiles -~~~~~~~~~~~~~~~~~~~~~~~ - -Afficher l'historique -##################### - -Pour afficher l'historique, outre l'outil utilisé pour faire les -illustrations de ce cours que vous pouvez retrouver -`https://github.com/blegat/git-dot <https://github.com/blegat/git-dot>`_, -il existe la commande `git-log(1)`_. -Elle est très flexible comme on va le voir. -``git log`` affiche simplement l'historique à partir de ``HEAD`` - -.. code-block:: bash - - $ git log - commit 0dd6cd7e6ecf01b638cd631697bf9690baedcf20 - Merge: eda36d7 6fd2e9b - Author: Benoît Legat <benoit.legat@gmail.com> - Date: Sun Aug 18 15:29:53 2013 +0200 - - Merge branch 'universal' - - Conflicts: - main.c - - commit 6fd2e9bfa199fc3dbca4df87d225e35553d6cd79 - Author: Benoît Legat <benoit.legat@gmail.com> - Date: Sun Aug 18 15:06:14 2013 +0200 - - Fix SIGSEV without args - - commit eda36d79fd48561dce781328290d40990e74a758 - Author: Benoît Legat <benoit.legat@gmail.com> - Date: Sun Aug 18 14:58:29 2013 +0200 - - Add pid/ppid info - - ... - -Mais on peut aussi demander d'afficher les modifications pour chaque commit -avec l'option ``-p`` - -.. code-block:: diff - - $ git log -p - commit 0dd6cd7e6ecf01b638cd631697bf9690baedcf20 - Merge: eda36d7 6fd2e9b - Author: Benoît Legat <benoit.legat@gmail.com> - Date: Sun Aug 18 15:29:53 2013 +0200 - - Merge branch 'universal' - - Conflicts: - main.c - - commit 6fd2e9bfa199fc3dbca4df87d225e35553d6cd79 - Author: Benoît Legat <benoit.legat@gmail.com> - Date: Sun Aug 18 15:06:14 2013 +0200 - - Fix SIGSEV without args - - diff --git a/main.c b/main.c - index 8ccfa11..f90b795 100644 - --- a/main.c - +++ b/main.c - @@ -9,7 +9,7 @@ - - // main function - int main (int argc, char *argv[]) { - - // main function - int main (int argc, char *argv[]) { - - if (strncmp(argv[1], "--alien", 8) == 0) { - + if (argc > 1 && strncmp(argv[1], "--alien", 8) == 0) { - printf("Hello universe!\n"); - } else { - printf("Hello world!\n"); - - commit eda36d79fd48561dce781328290d40990e74a758 - Author: Benoît Legat <benoit.legat@gmail.com> - Date: Sun Aug 18 14:58:29 2013 +0200 - - Add pid/ppid info - - diff --git a/main.c b/main.c - index 8381ce0..b9043af 100644 - --- a/main.c - +++ b/main.c - @@ -5,9 +5,11 @@ - // includes - #include <stdio.h> - #include <stdlib.h> - +#include <unistd.h> - - // main function - int main () { - + printf("pid: %u, ppid: %u\n", getpid(), getppid()); - printf("Hello world!\n"); - return EXIT_SUCCESS; - } - -Il existe encore plein d'autres options comme ``--stat`` qui se contente -de lister les fichiers qui ont changés. -En les combinant on peut obtenir des résultats intéressants comme ci-dessous - -.. code-block:: bash - - $ git log --graph --decorate --oneline - * 0dd6cd7 (HEAD, master) Merge branch 'universal' - |\ - | * 6fd2e9b Fix SIGSEV without args - | * 88d2c61 Merge branch 'master' into universal - | |\ - | * | e0c317a Make it universal - * | | eda36d7 Add pid/ppid info - | |/ - |/| - * | c35a8c3 Add Makefile - |/ - * c1f2163 Add intro - * b14855e Add .gitignore - * bc620ce Add return - * 76c1677 First commit - -On ajoute d'ailleurs souvent un raccourci pour avoir ce graphe avec -``git lol``. - -.. code-block:: bash - - $ git config --global alias.lol "log --graph --decorate --oneline" - -.. TODO comparer différents commits - -Sauvegarder des modifications hors de l'historique -################################################## - -On a vu que certaines opérations comme `git-checkout(1)`_ nécessitent -de ne pas avoir de modifications en conflit avec l'opération. - -`git-stash(1)`_ permet de sauvegarder ces modifications pour qu'elles ne soient -plus dans le *working directory* mais qu'elles ne soient pas perdues. -On peut ensuite les réappliquer avec ``git stash apply`` puis les effacer -avec ``git stash drop``. - -Reprenons notre exemple de *Changer la branche active* illustré par la figure -suivante - -.. figure:: figures/hello_intro.png - :align: center - - Historique après avoir ajouté un commentaire d'introduction - -.. code-block:: bash - - $ git checkout pid - Switched to branch 'pid' - $ echo "42" >> main.c - $ echo "42" >> .gitignore - $ git stash - Saved working directory and index state WIP on pid: b14855e Add .gitignore - HEAD is now at b14855e Add .gitignore - $ git checkout master - Switched to branch 'master' - $ git stash apply - Auto-merging main.c - # On branch master - # Changes not staged for commit: - # (use "git add <file>..." to update what will be committed) - # (use "git checkout -- <file>..." to discard changes in working directory) - # - # modified: .gitignore - # modified: main.c - # - no changes added to commit (use "git add" and/or "git commit -a") - -On voit que les changements on été appliqués - -.. code-block:: diff - - $ git diff - diff --git a/.gitignore b/.gitignore - index cba7efc..5df1452 100644 - --- a/.gitignore - +++ b/.gitignore - @@ -1 +1,2 @@ - a.out - +42 - diff --git a/main.c b/main.c - index 8381ce0..eefabd7 100644 - --- a/main.c - +++ b/main.c - @@ -11,3 +11,4 @@ int main () { - printf("Hello world!\n"); - return EXIT_SUCCESS; - } - +42 - -On peut alors supprimer le *stash* - -.. code-block:: bash - - $ git stash drop - Dropped refs/stash@{0} (ae5b4fdeb8bd751449d73f955f7727f660708225) - -Modifier un commit récent -######################### - -Si on a oublié d'ajouter des modifications dans le dernier commit et -qu'on ne l'a pas encore *pushé*, on peut facilement les rajouter. -Il suffit de donner l'option ``--amend`` à `git-commit(1)`_. -Il ajoutera alors les modifications au commit actuel au lieu d'en créer un -nouveau. - -On peut aussi annuler le dernier commit avec ``git reset HEAD^``. -`Git`_ permet aussi de construire un commit qui a l'effet inverse d'un autre -avec `git-revert(1)`_. -Ce dernier construit un commit qui annulera l'effet d'un autre commit. -Voyons tout ça par un exemple qui pourrait être le code de *Deep Thought*. - -On a un fichier ``main.c`` contenant - -.. code-block:: c - - #include <stdio.h> - #include <stdlib.h> - - int main (int argc, char *argv[]) { - int *n = (int*) malloc(sizeof(int)); - *n = 42; - printf("%d\n", *n); - return EXIT_SUCCESS; - } - -un ``Makefile`` contenant - -.. code-block:: makefile - - run: answer - echo "The answer is `./answer`" - - answer: main.c - gcc -o answer main.c - -si bien qu'on a - -.. code-block:: bash - - $ make - gcc -o answer main.c - echo "The answer is `./answer`" - The answer is 42 - $ make - echo "The answer is `./answer`" - The answer is 42 - $ touch main.c - $ make - gcc -o answer main.c - echo "The answer is `./answer`" - The answer is 42 - -et un fichier ``.gitignore`` avec comme seul ligne ``answer``. - -Commençons par committer ``main.c`` et ``.gitignore`` en oubliant le -``Makefile``. - -.. code-block:: bash - - $ git init - Initialized empty Git repository in /path/to_project/.git/ - $ git status - # On branch master - # - # Initial commit - # - # Untracked files: - # (use "git add <file>..." to include in what will be committed) - # - # .gitignore - # Makefile - # main.c - nothing added to commit but untracked files present (use "git add" to track) - $ git add .gitignore main.c - $ git commit -m "First commit" - [master (root-commit) 54e48c9] First commit - 2 files changed, 10 insertions(+) - create mode 100644 .gitignore - create mode 100644 main.c - $ git log --stat --oneline - 54e48c9 First commit - .gitignore | 1 + - main.c | 9 +++++++++ - 2 files changed, 10 insertions(+) - $ git status - # On branch master - # Untracked files: - # (use "git add <file>..." to include in what will be committed) - # - # Makefile - nothing added to commit but untracked files present (use "git add" to track) - -On pourrait très bien faire un nouveau commit contenant le ``Makefile`` -mais si, pour une quelconque raison, -on aimerait l'ajouter dans le commit précédent, -on peut le faire comme suit - -.. code-block:: bash - - $ git add Makefile - $ git commit --amend - [master 1712853] First commit - 3 files changed, 15 insertions(+) - create mode 100644 .gitignore - create mode 100644 Makefile - create mode 100644 main.c - $ git log --stat --oneline - 1712853 First commit - .gitignore | 1 + - Makefile | 5 +++++ - main.c | 9 +++++++++ - 3 files changed, 15 insertions(+) - -On voit qu'aucun commit n'a été créé mais c'est le commit précédent qui -a été modifié. -Ajoutons maintenant un check de la valeur retournée par `malloc(3)`_ pour gérer -les cas limites - -.. code-block:: diff - - $ git diff - diff --git a/main.c b/main.c - index 39d64ac..4864e60 100644 - --- a/main.c - +++ b/main.c - @@ -3,6 +3,10 @@ - - int main (int argc, char *argv[]) { - int *n = (int*) malloc(sizeof(int)); - + if (*n == NULL) { - + perror("malloc"); - + return EXIT_FAILURE; - + } - *n = 42; - printf("%d\n", *n); - return EXIT_SUCCESS; - -et committons le - -.. code-block:: bash - - $ git add main.c - $ git commit -m "Check malloc output" - [master 9e45e79] Check malloc output - 1 file changed, 4 insertions(+) - $ git log --stat --oneline - 9e45e79 Check malloc output - main.c | 4 ++++ - 1 file changed, 4 insertions(+) - 1712853 First commit - .gitignore | 1 + - Makefile | 5 +++++ - main.c | 9 +++++++++ - 3 files changed, 15 insertions(+) - -Essayons maintenant de construire un commit qui retire les lignes qu'on -vient d'ajouter avec `git-revert(1)`_ - -.. code-block:: bash - - $ git revert 9e45e79 - [master 6c0f33e] Revert "Check malloc output" - 1 file changed, 4 deletions(-) - $ git log --stat --oneline - 6c0f33e Revert "Check malloc output" - main.c | 4 ---- - 1 file changed, 4 deletions(-) - 9e45e79 Check malloc output - main.c | 4 ++++ - 1 file changed, 4 insertions(+) - 1712853 First commit - .gitignore | 1 + - Makefile | 5 +++++ - main.c | 9 +++++++++ - 3 files changed, 15 insertions(+) - -Le contenu de ``main.c`` est alors - -.. code-block:: c - - #include <stdio.h> - #include <stdlib.h> - - int main (int argc, char *argv[]) { - int *n = (int*) malloc(sizeof(int)); - *n = 42; - printf("%d\n", *n); - return EXIT_SUCCESS; - } - -Comme c'est une bonne pratique de vérifier la valeur de retour de `malloc(3)`_, -supprimons ce dernier commit - -.. code-block:: bash - - $ git reset HEAD^ - Unstaged changes after reset: - M main.c - $ git log --oneline - 9e45e79 Check malloc output - 1712853 First commit - -Corriger des bugs grâce à Git -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Git permet de garder des traces des nombreux changements qui ont été effectué au -cours de l’évolution d’un programme. Il contient d’ailleurs un outil très -puissant vous permettant de retrouver la source de certaines erreurs, pourvu que -les changements soient faits par petits commits : `git-bisect(1)`_. - -Supposez que vous ayez introduit une fonctionnalité dans votre programme. Tout -allait alors pour le mieux. Quelques semaines plus tard, à votre grand dam, vous -vous rendez compte qu’elle ne fonctionne plus. Vous sillonnez tous les fichiers -qui pourraient interagir avec cette fonction, en vain. Dans le désespoir, à -l’approche de la deadline, vous succombez au nihilisme. - -Avant de tout abandonner, pourtant, vous réalisez quelque chose de très -important. Ce que vous cherchez, c’est la source de l’erreur ; cela fait, la -corriger sera sans l’ombre d’un doute une tâche aisée. Si seulement il était -possible de voir à partir de quel changement le bug a été introduit… - -C’est là que vous repensez à Git ! Git connaît tous les changements qui ont été -effectués, et vous permet facilement de revenir dans le passé pour vérifier si -le bug était présent à un moment donné. En outre, vous vous rappelez vos cours -d’algorithmiques et vous rendez compte que, puisque vous connaissez un point où -le bug était présent et un autre ou il ne l’était pas, vous pouvez à l’aide -d’une recherche binaire déterminer en un temps logarithmique (par rapport aux -nombres de révisions comprises dans l’intervalle) quelle révision a introduit -l’erreur. - -C’est exactement l’idée derrière `git-bisect(1)` : vous donnez un intervalle de -commits dans lequel vous êtes certains de pouvoir trouver le vilain commit -responsable de tous vos maux, pour ensuite le corriger. Vous pouvez même -entièrement automatiser cette tâche si vous pouvez, excellent programmeur que -vous êtes, écrire un script qui renvoie 1 si le bug est présent et 0 si tout va -bien. - -Pour vous montrez comme utiliser cette fonctionnalité, et vous convaincre que -cela marche vraiment, et pas seulement dans des exemples fabriqués uniquement -dans un but de démonstration, nous allons l’appliquer à un vrai programme C : -mruby, une implémentation d’un langage correspondant à un sous-ensemble de Ruby. - -Intéressons nous à `un des problèmes qui a été rapporté par un utilisateur -<https://github.com/mruby/mruby/issues/1583>`_. Si vous lisez cette page, vous -verrez qu’en plus de décrire le problème, il mentionne le commit à partir duquel -il rencontre l’erreur. Si vous regardez aussi le commit qui l’a corrigée, vous -verrez que le développeur a bien dû changer une ligne introduite dans le commit -qui avait été accusé par l’utilisateur. - -Mettons nous dans la peau de l’utilisateur qui a trouvé le bug, et tentons nous -aussi d’en trouver la cause, en utilisant Git. D’abord, il nous faut obtenir le -dépôt sur notre machine (vous aurez besoin de Ruby afin de pouvoir tester), -et revenir dans le passé puisque, depuis, l’erreur a été corrigée. - - .. code-block:: console - - $ git clone git@github.com:mruby/mruby.git - (...) - $ cd mruby - $ git checkout 5b51b119ca16fe42d63896da8395a5d05bfa9877~1 - (...) - -Sauvegardons aussi le fichier de test proposé, par exemple dans -``~/code/rb/test.rb`` : - - .. code-block:: ruby - - class A - def a - b - end - def b - c - end - def c - d - end - end - x = A.new.a - -Vous devriez maintenant être capable de vérifier que la méthode ``A.a`` n’est pas -incluse dans la backtrace : - - .. code-block:: console - - $ make && ./bin/mruby ~/code/rb/test.rb - (...) - trace: - [3] /home/kilian/code/rb/test.rb:9:in A.c - [2] /home/kilian/code/rb/test.rb:6:in A.b - [0] /home/kilian/code/rb/test.rb:13 - /home/kilian/code/rb/test.rb:9: undefined method 'd' for #<A:0xdf1000> (NoMethodError) - -C’est le moment de commencer. Il faut d’abord dire à Git que nous désirons -démarrer une bissection et que le commit actuel est « mauvais », c’est à dire -que le bug est présent. Ceci est fait en utilisant les deux lignes suivantes, -dans l’ordre : - - .. code-block:: console - - $ git bisect start - $ git bisect bad - -Regardons ce qu’il en était quelque mois auparavant (remarquez qu’il faut -utiliser ``make clean`` pour s’assurer de tout recompiler ici) : - - .. code-block:: console - - $ git checkout 3a27e9189aba3336a563f1d29d95ab53a034a6f5 - Previous HEAD position was 7ca2763... write_debug_record should dump info recursively; close #1581 - HEAD is now at 3a27e91... move (void) cast after declarations - $ make clean && make && ./bin/mruby ~/code/test.rb - (...) - trace: - [3] /home/kilian/code/rb/test.rb:9:in A.c - [2] /home/kilian/code/rb/test.rb:6:in A.b - [1] /home/kilian/code/rb/test.rb:3:in A.a - [0] /home/kilian/code/rb/test.rb:13 - /home/kilian/code/rb/test.rb:9: undefined method 'd' for #<A:0x165d2c0> (NoMethodError) - -Cette fois-ci, tout va bien. Nous pouvons donc en informer Git : - - .. code-block:: console - - $ git bisect good - Bisecting: 116 revisions left to test after this (roughly 7 steps) - [fe1f121640fbe94ad2e7fabf0b9cb8fdd4ae0e02] Merge pull request #1512 from wasabiz/eliminate-mrb-intern - -Ici, Git nous dit combien de révisions il reste à vérifier dans l’intervalle en -plus de nous donner une estimation du nombre d’étapes que cela prendra. Il nous -informe aussi de la révision vers laquelle il nous a déplacé. Nous pouvons donc -réitérer notre test et en communiquer le résultat à Git : - - .. code-block:: console - - $ make clean && make && ./bin/mruby ~/code/test.rb - (...) - trace: - [3] /home/kilian/code/rb/test.rb:9:in A.c - [2] /home/kilian/code/rb/test.rb:6:in A.b - [1] /home/kilian/code/rb/test.rb:3:in A.a - [0] /home/kilian/code/rb/test.rb:13 - /home/kilian/code/rb/test.rb:9: undefined method 'd' for #<A:0x165d2c0> (NoMethodError) - $ git bisect good - Bisecting: 58 revisions left to test after this (roughly 6 steps) - [af03812877c914de787e70735eb89084434b21f1] add mrb_ary_modify(mrb,a); you have to ensure mrb_value a to be an array; ref #1554 - -Si nous réessayons, nous allons nous rendre compte que notre teste échoue à -présent (il manque la ligne ``[1]``): nous somme allés trop loin dans le -futur. Il nous faudra donc dire à Git que la révision est mauvaise. - - .. code-block:: console - - $ make clean && make && ./bin/mruby ~/code/test.rb - (...) - trace: - [3] /home/kilian/code/rb/test.rb:9:in A.c - [2] /home/kilian/code/rb/test.rb:6:in A.b - [0] /home/kilian/code/rb/test.rb:13 - /home/kilian/code/rb/test.rb:9: undefined method 'd' for #<A:0x165d2c0> (NoMethodError) - $ git bisect bad - Bisecting: 28 revisions left to test after this (roughly 5 steps) - [9b2f4c4423ed11f12d6393ae1f0dd4fe3e51ffa0] move declarations to the beginning of blocks - -Si vous continuez à appliquer cette procédure, vous allez finir par trouver la -révision fautive, et Git nous donnera l’information que nous recherchions, comme -par magie : - - .. code-block:: console - - $ git bisect bad - Bisecting: 0 revisions left to test after this (roughly 0 steps) - [a7c9a71684fccf8121f16803f8e3d758f0dea001] better error position display - $ make clean && make && ./bin/mruby ~/code/rb/test.rb - (...) - trace: - [3] /home/kilian/code/rb/test.rb:9:in A.c - [2] /home/kilian/code/rb/test.rb:6:in A.b - [0] /home/kilian/code/rb/test.rb:13 - /home/kilian/code/rb/test.rb:9: undefined method 'd' for #<A:0x1088160> (NoMethodError) - $ git bisect bad - a7c9a71684fccf8121f16803f8e3d758f0dea001 is the first bad commit - commit a7c9a71684fccf8121f16803f8e3d758f0dea001 - Author: Yukihiro "Matz" Matsumoto <matz@ruby-lang.org> - Date: Tue Oct 15 12:49:41 2013 +0900 - - better error position display - - :040000 040000 67b00e2d4f6acadc0474e00fc0f5e6e13673c64a 036eb9c3b9960613bde3882b7a88ac6cabc56253 M include - :040000 040000 5040dd346fea4d8f476d26ad2ede0dc49ca368cd 903f2d954d8686e7bfa7bcf5d83b80b5beb4899f M src - -Maintenant que nous connaissons la source du problème, il ne faut pas oublier de -confirmer à Git que la recherche est bien terminée, et que nous désirons -remettre le dépôt dans son état normal. - - .. code-block:: console - - $ git bisect reset - Previous HEAD position was a7c9a71... better error position display - HEAD is now at 7ca2763... write_debug_record should dump info - recursively; close #1581 - -Automatisation de la procédure -############################## - -Exécuter ce test à la main est cependant répétitif, prône aux erreurs -d’inattention, et surtout très facile à automatiser. Écrivons donc un script qui -vérifie que la ligne mentionnant ``A.a`` est bien présente à chaque fois, -appelons le par exemple ``~/code/sh/Iznogoud.sh``. Il s’agit de renvoyer 0 -si tout se passe bien et une autre valeur s’il y a un problème. - - .. code-block:: bash - - #!/usr/bin/env bash - make clean && make && ./bin/mruby ~/code/rb/test.rb 2>&1 | grep A\.a - -Puisque ``grep`` renvoie 1 quand il ne trouve pas de ligne contenant le motif -qu’on lui passe en argument et 0 sinon, notre script renvoie bien 1 si la sortie -de mruby ne contient pas la ligne mentionnant ``A.a`` et 0 sinon. - -N’oubliez pas de changer les permissions du script pour en permettre l’exécution : - - .. code-block:: console - - $ chmod +x ~/code/sh/Iznogoud.sh - - -Ce test n’est en bien sûr pas infaillible, mais sera suffisant ici. Il faut -d’abord redonner à Git l’intervalle dans lequel se trouve la révision fautive. - - .. code-block:: console - - $ git bisect start - $ git bisect bad - $ git checkout 3a27e9189aba3336a563f1d29d95ab53a034a6f5 - Previous HEAD position was 7ca2763... write_debug_record should dump info recursively; close #1581 - HEAD is now at 3a27e91... move (void) cast after declarations - $ git bisect good - Bisecting: 116 revisions left to test after this (roughly 7 steps) - [fe1f121640fbe94ad2e7fabf0b9cb8fdd4ae0e02] Merge pull request #1512 from wasabiz/eliminate-mrb-intern - -Il suffit maintenant d’utiliser ``git bisect run`` avec le nom du script pour -l’utiliser. Il est possible de rajouter d’autres arguments après le nom du -script, qui seront passés au script lors de chaque exécution. Par exemple, si -vous avez dans votre Makefile une tâche test qui renvoie 0 si tous les tests -passent et 1 si certains échouent, alors ``git bisect run make test`` -permettrait de trouver à partir de quand les tests ont cessé de fonctionner. - -Si vous exécutez la ligne suivante, vous devriez bien trouver, après quelques -compilations, le même résultat qu’avant : - - .. code-block:: console - - $ git bisect run ~/code/sh/Iznogoud.sh - (...) - a7c9a71684fccf8121f16803f8e3d758f0dea001 is the first bad commit - commit a7c9a71684fccf8121f16803f8e3d758f0dea001 - Author: Yukihiro "Matz" Matsumoto <matz@ruby-lang.org> - Date: Tue Oct 15 12:49:41 2013 +0900 - - better error position display - - :040000 040000 67b00e2d4f6acadc0474e00fc0f5e6e13673c64a 036eb9c3b9960613bde3882b7a88ac6cabc56253 M include - :040000 040000 5040dd346fea4d8f476d26ad2ede0dc49ca368cd 903f2d954d8686e7bfa7bcf5d83b80b5beb4899f M src - bisect run success - -À nouveau, n’oubliez pas d’utiliser ``git bisect reset`` avant de continuer à -travailler sur le dépôt. - -Subversion ----------- - -`subversion`_ (ou abrégé `svn(1)`_) est un logiciel qui permet à plusieurs utilisateurs de travailler sur les mêmes documents de type texte. `Subversion`_ est fréquemment utilisé pour gérer du code source développé de façon collaborative, mais il peut aussi servir à gérer n'importe quel ensemble de fichiers (de préférence textes) manipulés par plusieurs personnes. - -.. Dans le cadre du cours SINF1252 vous devez vous inscrire à subversion dans le projet ``SINF1252_2012`` en suivant le lien et les instructions sur http://wiki.student.info.ucl.ac.be/index.php/Svn - -Pour commencer l'utilisation de `svn(1)`_ vous devriez faire d'abord un ``checkout`` du répertoire: - - .. code-block:: console - - $ svn checkout <url de votre répertoire> - Checked out revision 1. - -Ceci installe votre répertoire (ici, nommé ``my_rep``) dans le dossier courant. Vous pouvez vous déplacer dans le nouveau dossier et créer un nouveau dossier pour cet premier projet. Il faut explicitement ajouter ce dossier à svn avec la commande ``svn add [nom du dossier]``. Chaque fichier et dossier dont vous voulez qu'il fasse partie du contrôle de version doivent être ajoutés avec cette commande. - - .. code-block:: console - - $ cd my_rep - $ mkdir projet_S1 - $ svn add projet_S1 - A projet_S1 - -Ce dossier n'a pas encore été envoyé sur le serveur principal et n'est donc pas encore visible pour d'autres utilisateurs. Pour afficher l'état de votre répertoire utilisez ``svn status``. La lettre ``A`` indique que ceci est un nouveau dossier/fichier pas encore envoyé vers le serveur. ``?`` indique que les fichiers/dossiers ne font pas partie du répertoire svn (on peut les ajouter avec ``svn add``). ``M`` indique que les fichiers sont modifiés localement mais pas encore envoyés vers le serveur. Ces fichiers font partie du répertoire svn. - - .. code-block:: console - - $ svn status - A projet_S1 - $ svn commit -m "Projet S1: Initialisation" - Adding projet_S1 - Transmitting file data . - Committed revision 2. - -La commande ``svn commit`` permet de pousser les changements locaux et les nouveaux fichiers vers le serveur. La chaîne de charactères entre les ``"`` est le commentaire qu'il faut ajouter au commit. Il est important de commenter vos commits pour que vous puissiez vous retrouvez dans votre historique. L'historique de votre répertoire peut être affiché avec la commande ``svn log``. - -Les autres utilisateurs de votre répertoire (c'est-à -dire dans le cadre de ce cours: vôtre binôme du groupe) peuvent à partir de maintenant accéder à ce nouveau dossier en mettant à jour son répertoire local. -Pour mettre à jour le répertoire local, on utilise la commande ``svn update``. - - .. code-block:: console - - $ svn update - Updating '.': - A projet_S1 - Updated to revision 2. - -Il est recommandé de toujours faire un ``update`` avant de faire un ``commit``. Lors d'un update il est possible qu'un conflit se crée dans votre dossier local. Ceci peut arriver si vous avez modifié une ligne dans un fichier localement et que cette ligne a aussi été modifiée par le commit d'un autre utilisateur. Pour résoudre le conflit, vous devez éditer le fichier que svn a indiqué être en conflit en cherchant des lignes qui commencent par ``<<<``. Corrigez ce fichier et retournez dans la console et tapez ``r`` pour indiquer à svn que ce conflit a été résolu. - -Pour plus d'informations sur svn regardez les commandes ``svn help``, ``svn help [commande]`` ou http://svnbook.red-bean.com/. Une recherche sur Google vous aidera aussi pour résoudre vos problèmes avec subversion. diff --git a/Outils/gprof.rst b/Outils/gprof.rst deleted file mode 100644 index d6729663c41daf77bb51e55c604dcabfc6d4d7f4..0000000000000000000000000000000000000000 --- a/Outils/gprof.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. _gprof: - -Profiling de code ------------------ - - -Lorsque l'on cherche à optimiser les performances de programmes écrits en C, il est utile de les exécuter à travers un profiler tel que `gprof(1)`_. Ce profiler permet de collecter des statistiques sur les fonctions les plus utilisées à l'intérieur du programme. Ce sont les fonctions qu'il faudra optimiser pour améliorer les performances. De nombreux articles décrivent les principes de base de l'utilisation de `gprof(1)`_. Un bon article pour démarrer est [Honeyford2006]_. `oprofile <http://oprofile.sourceforge.net/>`_ est un profiler plus puissant que `gprof(1)`_ mais malheureusement plus difficile à utiliser. diff --git a/Outils/index.rst b/Outils/index.rst deleted file mode 100644 index 556a6a3ef219ac4b3e669e9b48d462ee14d72521..0000000000000000000000000000000000000000 --- a/Outils/index.rst +++ /dev/null @@ -1,36 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012-2014 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch, Grégory Detal et les étudiants du cours -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -############################### -Systèmes informatiques : Outils -############################### - - -.. only:: html - - Ce site web contient l'annexe relative aux outils informatiques pour le cours `SINF1252 <http://www.uclouvain.be/cours-2015-LSINF1252.html>`_ donné aux `étudiants en informatique <http://www.uclouvain.be/info.html>`_ à l'`Université catholique de Louvain <http://www.uclouvain.be>`_ (UCL). Les étudiants sont invités à ajouter leur commentaires en soumettant des patches via https://github.com/obonaventure/SystemesInformatiques - -.. La version HTML est la préférable car elle contient des liens hypertextes vers les pages de manuel Linux qui font partie de la matière. D'autres formats sont possibles pour ceux qui veulent lire le document hors ligne : - -.. - :download:`distrib/SINF1252.epub` en format epub lisible sur tablettes style iPad ou Galaxy Tab -.. - :download:`distrib/SINF1252.pdf` en format pdf pour lecture via les logiciels Adobe ou pour impression - - -.. toctree:: - :maxdepth: 2 - - intro-outils - git - make - ssh - cunit - processus - valgrind - gdb - gprof - shell - gcc - bib - diff --git a/Outils/intro-outils.rst b/Outils/intro-outils.rst deleted file mode 100644 index 244cfd856b3710e6d99e2dd95e562997914a89b6..0000000000000000000000000000000000000000 --- a/Outils/intro-outils.rst +++ /dev/null @@ -1,47 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Introduction -============ - -Outre des compétences théoriques qui sont abordées dans d'autres parties de ce document, la maitrise d'une système informatique implique également une excellente connaissance des outils informatiques qui sont inclus dans ce système. Cette connaissance se construit bien entendu en utilisant activement ces logiciels. Cette section comprend les informations de bases sur quelques logiciels importants qui sont utilisés dans le cadre du cours. Elle est volontairement réduite car de nombreux logiciels pourraient faire l'objet de livres complets. Les étudiants sont invités à proposer des améliorations à cette section sous la forme de patches via https://github.com/obonaventure/SystemesInformatiques - - -Editeurs -======== - -De nombreux éditeurs sont utilisables pour manipuler efficacement du code source en langage C. Chaque étudiant doit choisir l'éditeur qui lui convient le mieux. En voici quelques uns : - - - `vi(1)`_ est un des premiers éditeurs à avoir été écrit pour Unix. Il a fortement évolué, et reste un outil de choix pour de nombreux administrateurs systèmes. De nombreux tutoriels permettent d'apprendre rapidement `vi(1)`_, dont http://www.ibm.com/developerworks/linux/tutorials/l-vi/ - - `emacs <http://www.gnu.org/software/emacs/>`_ est un autre éditeur fréquemment utilisé sous Unix. Il existe de très nombreuses extensions à emacs qui lui permettent de faire tout ou presque, y compris de jouer à des jeux comme Tetris. Son extensibilité peut rebuter certains utilisateurs. De nombreux tutoriels sont disponibles sur Internet, dont http://www.gnu.org/software/emacs/tour/ - - `gedit <http://projects.gnome.org/gedit/>`_ est l'éditeur de base dans l'environnement graphique `GNOME <http://www.gnome.org>`_ utilisé dans les distributions Linux. - - `eclipse <http://www.eclipse.org>`_ est un environnement complet de développement écrit en Java pour supporter initialement ce langage. De nombreuses extensions à `eclipse <http://www.eclipse.org>`_ existent, dont `CDT <http://www.eclipse.org/cdt/>`_ qui permet la manipulation efficace de code source en langages C et C++. - - -.. _svn: - -Gestionnaires de code partagé -============================= - -Dans de nombreux projets informatiques, il est nécessaire d'utiliser des outils qui permettent d'organiser efficacement le partage du code source entre plusieurs développeurs. Les plus anciens gestionnaires de code sont `cvs <http://cvs.nongnu.org/>`_ ou `rcs <http://www.gnu.org/software/rcs/>`_. Ces logiciels ont été créés lorsque Unix était utilisé sur des mini-ordinateurs qui servaient tout un département. Aujourd'hui, les logiciels de gestion de code source s'utilisent en combinaison avec des serveurs Internet pour permettre un partage large du code source. Les plus connus sont : - - - `Git`_ qui est décrit ci-dessous - Il est aussi décrit dans plein d'autres ressources comme - `git-scm <http://git-scm.com/>`_ contenant le livre Pro Git, - `git-ref <http://git-ref.com/>`_ mais aussi une - `vidéo <http://www.youtube.com/watch?v=ZDR433b0HJY>`_ faite par le créateur - de ces deux sites et - `Try Git <http://try.github.io/levels/1/challenges/1>`_ qui permet - de découvrir `Git`_ en 15 minutes interactivement à travers le site. - - `subversion`_ qui est décrit ci-dessous également - - `mercurial <http://mercurial.selenic.com/>`_ - - `bazaar <http://bazaar.canonical.com/>`_ - - -Compilateurs -============ - -Le compilateur C utilisé dans de nombreuses distributions Linux est `gcc(1)`_. C'est un compilateur open-source développé activement dans le cadre du projet GNU par la `Free Software Foundation <http://www.fsf.org>`_. Nous utiliserons principalement `gcc(1)`_ dans le cadre de ce cours. - -Il existe des alternatives à `gcc(1)`_ comme llvm_ que nous utiliserons lorsque nous analyserons le code assembleur généré par un compilateur C. Les variantes commerciales de Unix utilisent généralement des compilateurs propriétaires, dont par exemple `Oracle Studio <http://www.oracle.com/technetwork/server-storage/solarisstudio/overview/index.html>`_ ou la `suite de compilateurs <http://software.intel.com/en-us/c-compilers>`_ développée par intel_. diff --git a/Outils/make.rst b/Outils/make.rst deleted file mode 100644 index b07aafff86a93e847dcd1e64a4e27dbfea52fa23..0000000000000000000000000000000000000000 --- a/Outils/make.rst +++ /dev/null @@ -1,228 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. _make: - -Introduction aux Makefiles --------------------------- - -Les Makefiles sont des fichiers utilisés par le programme `make(1)`_ afin d'automatiser un ensemble d'actions permettant la génération de fichiers, la plupart du temps résultant d'une compilation. - -Un Makefile est composé d'un ensemble de règles de la forme: - - .. code-block:: make - - target [target ...]: [component ...] - [command] - ... - [command] - -Chaque règle commence par une ligne de dépendance qui définit une ou plusieurs cibles (``target``) suivies par le caractère ``:`` et éventuellement une liste de composants (``components``) dont dépend la cible. Une cible ou un composant peut être un fichier ou un simple label. - -Il est important de se rendre compte que l'espacement derrière les ``command`` -doit impérativement commencer par une *tabulation*. -Ça ne peut pas commencer par des espaces. -Il ne faut pas non plus confondre la touche tabulation du clavier -qui est souvent interprétée par les éditeurs de texte -par une indentation et le caractère de tabulation -(souvent écrit ``\t`` comme en C ou en bash) qui sont souvent affichés -avec 2, 3, 4 ou 8 espacements en fonction des préférences de l'utilisateur. -On parle bien ici du caractère de tabulation. -Heureusement, bien que beaucoup de gens configurent -leur éditeur de texte pour indenter avec des espaces, -la plupart des bons éditeurs reconnaissent que c'est -un Makefile et indentent avec des tabulations. - -Le fichier suivant reprend un exemple de règle où la cible et le composant sont des fichiers. - - .. code-block:: make - - text.txt: name.txt - echo "Salut, " > text.txt - cat name.txt >> text.txt - -Lorsque ``make`` est exécuté en utilisant ce Makefile, on obtient: - - .. code-block:: console - - $ make - make: *** No rule to make target `name.txt', needed by `text.txt'. Stop. - -Comme ``text.txt`` dépend de ``name.txt``, il faut que ce dernier soit défini comme cible dans le Makefile ou existe en tant que fichier. Si nous créons le fichier ``name.txt`` contenant ``Tintin`` et que ``make`` est ré-exécuté, on obtient la sortie suivante : - - .. code-block:: console - - $ make - echo "Salut, " > text.txt - cat name.txt >> text.txt - $ cat text.txt - Salut, - Tintin - -Lorsqu'une dépendance change, ``make`` le détecte et ré-exécute les commandes associées à la cible. Dans le cas suivant, le fichier ``name.txt`` est modifié, ce qui force la regénération du fichier ``text.txt``. - - .. code-block:: console - - $ make - make: `text.txt' is up to date. - $ echo Milou > name.txt - $ make - echo "Salut, " > text.txt - cat name.txt >> text.txt - $ cat text.txt - Salut, - Milou - -Comme spécifié précédemment, les Makefiles sont principalement utilisés pour automatiser la compilation de projets. Si un projet dépend d'un fichier source ``test.c``, le Makefile permettant d'automatiser sa compilation peut s'écrire de la façon suivante: - - .. code-block:: make - - test: test.c - gcc -o test test.c - -Ce Makefile permettra de générer un binaire ``test`` à chaque fois que le fichier source aura changé. - -Les variables -~~~~~~~~~~~~~ - -.. sectionauthor:: Alexis Nootens <alexis.nootens@student.uclouvain.be> - -Il est possible d'utiliser des variables dans un fichier Makefile. Celles-ci sont généralement définies au début du fichier, une par ligne comme : - - .. code-block:: make - - CC = GCC - OPT = -ansi - VARIABLE_AU_NOM_TRES_LONG = 1 - -Notez que les noms sont écrits en majuscule par convention. Leur appel est semblable à celui en script shell (bash) excepté les parenthèses après le symbole $. -On écrit par exemple ``$(CC)``, ``$(CFLAGS)``, ``$(VARIABLE_AU_NOM_TRES_LONG)``. Make autorise de remplacer les parenthèses par des accolades mais cette pratique est moins répandue. - - .. code-block:: make - - CC = GCC - CFLAGS = -ansi - - build: - $(CC) $(CFLAGS) foo.c -o foo - -Vous aurez compris qu'ici, la cible ``build`` effectue la commande ``gcc -ansi foo.c -o foo``. -Il est très intéressant de savoir que toutes les variables d’environnement présentes lors de l’appel au Makefile sont également disponibles avec la même notation. -Vous pouvez donc très bien utiliser la variable ``$(HOME)`` indiquant le répertoire attribué à l'utilisateur sans la définir. - -Il existe six différentes manières d'assigner une valeur à une variable. Nous ne nous intéresserons qu'à quatre d'entre elles. - - .. code-block:: make - - VARIABLE = value - VARIABLE := value - VARIABLE ?= value - VARIABLE += value - -- La première permet de lier la variable à une valeur (ici value). Mais celle-ci ne sera évaluée qu'à son appel. -- La seconde permet de déclarer une variable et de l'évaluer directement en même temps. -- La troisième permet d'assigner une valeur à la variable uniquement si celle-ci n'en a pas encore. -- La quatrième permet d'ajouter une valeur à une autre déjà déclarée. - -Une description détaillée de ces méthodes d'assignation et des deux autres restantes se trouve à l'adresse suivante `<http://www.gnu.org/software/make/manual/make.html#Setting>`_ - -Les conditions -~~~~~~~~~~~~~~ - -Les variables ne servent pas uniquement à éviter la redondance d'écriture dans votre fichier. On peut aussi les utiliser pour -réaliser des opérations conditionnelles comme : - - .. code-block:: make - - DEBUG = 1 - - build: - ifeq ($(DEBUG), 1) - gcc -Wall -Werror -o foo foo.c - else - gcc -o foo foo.c - endif - -Ici ``ifeq`` permet de tester un "si égal". Il existe aussi l'opération opposée ``ifneq`` pour "si non-égal". Remarquez que les conditions ne doivent pas être tabulées au risque d'obtenir une erreur -de syntaxe incompréhensible. Les conditions peuvent avoir différentes syntaxes. Vous pouvez les trouver sur cette page http://www.gnu.org/software/make/manual/make.html#Conditional-Syntax - -Avec les sections précédentes et la suivante nous allons pouvoir nous aventurer dans la création de Makefiles plus complexes. -On peut vouloir effectuer des compilations différentes suivant l'environnement de l'utilisateur comme son OS, son matériel ou juste son nom. -Encore une fois Make nous gâte en nous offrant la possibilité d'exécuter des commandes shell dans nos Makefiles. -Imaginez avoir besoin d'options de compilation supplémentaires à cause de votre OS que seul vous avez besoin. Vous pouvez effectuer une compilation -conditionnelle sur votre nom. - - .. code-block:: make - - USER := $(shell whoami) - - build: - ifeq ($(USER), sfeldman) - gcc -I($HOME)/local/include -o foo foo.c - else - gcc -o foo foo.c - endif - -Ici ``$(shell whoami)`` est un appel à la fonction shell (de Make) qui nous permet d'assigner à la variable ``USER``, en évaluant immédiatement l'appel, le résultat de la commande shell (bash) ``whoami`` renvoyant le -nom de l'utilisateur actuel. Cela ne fonctionnera que si la commande ``whoami`` est disponible dans le shell évidemment. - -La cible .PHONY -~~~~~~~~~~~~~~~ - -Make compare les dates de modification des fichiers produits avec les dates de leur(s) source(s) pour savoir si celles-ci ont été modifiées depuis leur dernière compilation. Cela lui permet de ne pas devoir recompiler des fichiers qui n'auraient pas changé d'un appel à -l'autre. Malheureusement ce comportement qui peut sembler avantageux amène aussi des problèmes, en l’occurrence pour des règles ne produisant aucun fichier. -Une solution pour pallier le problème consiste à indiquer que la règle ne crée rien. Pour faire cela il existe une cible spéciale ``.PHONY`` permettant de définir -quelles règles doivent toujours être exécutées à nouveau. Ainsi une règle ``.PHONY`` ne rencontrera jamais le problème d'être déjà à jour. -Une bonne pratique est de déclarer dans ``.PHONY`` toutes les règles de nettoyage de votre projet. - - .. code-block:: make - - build: - gcc -o foo foo.c - - .PHONY: clean - - clean: - rm -f *.o - -Cela est aussi pratique pour forcer une re-compilation. - - .. code-block:: make - - build: - gcc -o foo foo.c - - .PHONY: clean rebuild - - clean: - rm -f *.o foo - - rebuild: clean build - -Compléments -~~~~~~~~~~~ - -Afin de rendre vos Makefiles plus lisibles, vous pouvez y insérer des commentaires en plaçant un croisillon en début de ligne. -Cette syntaxe est semblable au script shell. - - .. code-block:: make - - # Commentaire sur - # plusieurs lignes - build: - gcc -o foo foo.c # commentaire en fin de ligne - -Débugger les erreurs de vos Makefiles peut sembler difficile lorsque vous êtes baignés dans un flux d'instructions. Vous pouvez néanmoins régler leur verbosité. -Il est possible de rendre silencieuse une commande en plaçant une arobase devant. Ceci indique juste à Make de ne pas imprimer la ligne de commande. La sortie -standard de cette commande restera visible. - - .. code-block:: make - - build: - @echo "Building foo" - @gcc -o foo foo.c - -Pour plus d'informations en français sur l'écriture ou utilisation des Makefiles voir [DeveloppezMake]_. - -Documentation complète en anglais sur le site officiel [GNUMake]_. diff --git a/Outils/processus.rst b/Outils/processus.rst deleted file mode 100644 index 84c3031159555df8eaf9c8b74c79d34f7e0f1977..0000000000000000000000000000000000000000 --- a/Outils/processus.rst +++ /dev/null @@ -1,107 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Gestion des processus -===================== - -Les systèmes d'exploitation de type Unix sont multitâches et multi-utilisateurs. Cela signifie qu'il est possible d'exécuter simultanément plusieurs programmes qui appartiennent potentiellement à différents utilisateurs. Sous Unix, l'unité d'exécution d'un programme est appelée un :term:`processus`. Lorsque vous exécutez un programme C que vous avez compilé depuis la ligne de commande, le shell lance un nouveau :term:`processus`. Chaque processus est identifié par le système d'exploitation via son :term:`pid` ou :term:`process identifier`. Ce :term:`pid` est alloué par le système d'exploitation au moment de la création du processus. À tout instant, le système d'exploitation maintient une :term:`table des processus` qui contient la liste de tous les processus qui sont en cours d'exécution. Comme nous aurons l'occasion de nous en rendre compte plus tard, cette table contient énormément d'informations qui sont utiles au système. À ce stade, l'information importante qui se trouve dans la table des processus est le :term:`pid` de chaque processus et l'utilisateur qui possède le processus. La commande `ps(1)`_ permet de consulter de façon détaillée la table des processus sur un système Unix. Voici un exemple d'utilisation de cette commande sur un système Linux. - -.. code-block:: console - - $ ps u - USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND - obo 16272 0.0 0.0 110464 1884 pts/1 Ss 11:35 0:00 -bash - obo 16353 0.0 0.0 110184 1136 pts/1 R+ 11:43 0:00 ps u - - -Dans cet exemple, l'utilisateur ``obo`` possède actuellement deux processus. Le premier est l'interpréteur de commande `bash(1)`_ et le second le processus `ps(1)`_. L'interpréteur de commande a ``16272`` comme :term:`pid` tandis que le :term:`pid` de `ps(1)`_ est 16353. - -`ps(1)`_ n'est pas la seule commande permettant de consulter la table des processus. Parmi les autres commandes utiles, on peut mentionner `top(1)`_ qui permet de visualiser les processus qui s'exécutent actuellement et le temps CPU qu'ils consomment ou `pstree(1)`_ qui présente les processus sous la forme d'un arbre. Sous Linux, le répertoire ``/proc``, qui est documenté dans `proc(5)`_ contient de nombreux pseudos fichiers avec énormément d'informations relatives aux processus qui sont en cours d'exécution. Parcourir le répertoire ``/proc`` et visualiser avec ``less(1)`` les fichiers qui s'y trouvent est une autre façon de consulter la table des processus sous Linux. - -Pour comprendre le fonctionnement des processus, il est intéressant d'expérimenter avec le processus ci-dessous. Celui-ci utilise l'appel système `getpid(2)`_ pour récupérer son :term:`pid`, l'affiche et utilise la fonction `sleep(3)`_ de la librairie pour se mettre en veille pendant trente secondes avant de se terminer. - -.. literalinclude:: src/getpid.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - -Ce programme peut être compilé avec `gcc(1)`_ pour produire un exécutable. - -.. code-block:: console - - $ ls -l getpid* - -rw-r--r-- 1 obo obo 608 10 fév 12:11 getpid.c - $ gcc -Wall -o getpid getpid.c - $ ls -l getpid* - -rwxr-xr-x 1 obo obo 8800 10 fév 12:12 getpid - -rw-r--r-- 1 obo obo 608 10 fév 12:11 getpid.c - -Cet exemple utilise la commande `ls(1)`_ pour lister le contenu d'un répertoire. L'argument ``-l`` permet de d'obtenir pour chaque fichier son nom, sa date de modification, sa taille, l'utilisateur et le groupe auquel il appartient ainsi que ses permissions. Sous Unix, les permissions associées à un fichier sont divisées en trois blocs. Le premier bloc correspond aux permissions qui sont applicables à l'utilisateur qui possède le fichier. Pour l'exécutable ``getpid``, les permissions du propriétaire sont ``rwx``. Elles indiquent que le propriétaire peut lire le fichier (permission ``r``), l'écrire ou l'effacer (permission ``w``) et l'exécuter (permission ``x``). Sous Unix, seuls les fichiers qui possèdent la permission à l'exécution peuvent être lancés depuis l'interpréteur. Ces permissions peuvent être modifiées en utilisant la commande `chmod(1)`_. Les deux autres blocs de permissions sont relatifs aux membres du même groupe que le propriétaire et à un utilisateur quelconque. Nous y reviendrons plus en détail lorsque nous abordons les systèmes de fichiers. En pratique, il est important de savoir qu'un fichier shell ou un fichier compilé qui n'a pas le bit de permission ``x`` ne peut pas être exécuté par le système. Ceci est illustré par l'exemple ci-dessous. - -.. code-block:: console - - $ chmod -x getpid - $ ls -l getpid* - -rw-r--r-- 1 obo obo 8800 10 fév 12:12 getpid - -rwxr-xr-x 1 obo obo 8800 10 fév 12:11 getpid.o - $ ./getpid - -bash: ./getpid: Permission denied - $ chmod +x getpid - $ ./getpid - Processus : 11147 - -L'interpréteur de commande `bash(1)`_ permet lancer plusieurs processus en tâche de fond. Cela se fait en suffixant la commande avec ``&``. Des détails complémentaires sont disponibles dans la section ``JOB CONTROL`` du manuel de `bash(1)`_. Lorsqu'un processus est lancé en tâche de fond, il est détaché et n'a plus accès à l'entrée standard. Par contre, il continue à pouvoir écrire sur la sortie standard et la sortie d'erreur standard. L'exemple ci-dessous illustre l'exécution de deux instances de ``getpid``. - -.. code-block:: console - - $ ./getpid & - [1] 10975 - $ Processus : 10975 - [pid=10975] Sleep : 30 secondes - $ ./getpid & - [2] 10976 - $ Processus : 10976 - [pid=10976] Sleep : 30 secondes - ps u - USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND - obo 8361 0,0 0,0 2435548 208 s003 S+ 9:24 0:00.14 -bash - obo 10975 0,0 0,0 2434832 340 s000 S 12:05 0:00.00 ./getpid - obo 10976 0,0 0,0 2434832 340 s000 S 12:05 0:00.00 ./getpid - [pid=10975] Fin du processus - [pid=10976] Fin du processus - [1]- Done ./getpid - [2]+ Done ./getpid - -Ces deux instances partagent la même sortie standard. En pratique, lorsque l'on lance un processus en tâche de fond, il est préférable de rediriger sa sortie et son erreur standard. Lorsque l'on développe de premiers programmes en C, il arrive que celui-ci se lance dans une boucle infinie. Deux techniques sont possibles pour interrompre un tel processus qui consomme inutilement les ressources de la machine et peut dans certains cas la surcharger fortement. - -Si le programme a été lancé depuis un shell, il suffit généralement de taper sur `Ctrl-C` pour interrompre son exécution, comme dans l'exemple ci-dessous. - -.. code-block:: console - - $ ./getpid - Processus : 11281 - [pid=11281] Sleep : 30 secondes - ^C - - -Parfois cependant `Ctrl-C` n'est pas suffisant. C'est le cas notamment lorsqu'un processus a été lancé en tâche de fond. Dans ce cas, la meilleure technique est d'utiliser `ps(1)`_ pour trouver l'identifiant du processus et l'interrompre via la commande `kill(1)`_. Cette commande permet d'envoyer un :term:`signal` au processus. Nous verrons plus tard le fonctionnement des signaux sous Unix. À ce stade, le signal permettant de terminer avec certitude un processus est le signal ``KILL``. C'est celui qui est utilisé dans l'exemple ci-dessous. - -.. code-block:: console - - $ ./getpid & - [1] 11285 - $ Processus : 11285 - [pid=11285] Sleep : 30 secondes - ps - PID TTY TIME CMD - 384 ttys000 0:00.32 -bash - 11285 ttys000 0:00.00 ./getpid - $ kill -KILL 11285 - $ ps - PID TTY TIME CMD - 384 ttys000 0:00.33 -bash - [1]+ Terminated ./getpid - - - diff --git a/Outils/shell.rst b/Outils/shell.rst deleted file mode 100644 index b294e803332b3d27cf5c6bc964a14c77188ba1c0..0000000000000000000000000000000000000000 --- a/Outils/shell.rst +++ /dev/null @@ -1,997 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by Nicolas Houtain for shell and Maxime De Mol for bash -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -Shell -===== - -L'interpréteur de commande, ou shell, est l'interface de communication entre l'utilisateur et le système d'exploitation. C'est un exécutable chargé d'interpréter les commandes écrites par l'utilisateur et de les exécuter. - -Dans le cadre de ce cours nous utiliserons l'interpréteur `bash(1)`_. Cet exécutable est généralement placé dans le fichier ``/bin/bash``. - -Le shell est un outil très puissant. Il permet d'effectuer de nombreuses opérations qui peuvent difficilement être réalisées manuellement ou via une interface graphique. - - -.. note:: Astuce : utilisez la complétion - - Lors de la frappe d'un nom de fichier, d'un chemin d'accès ou même d'une commande tapez sur la touche ``<tab>`` pour "compléter" le mot que vous écrivez. Si rien ne se passe tapez deux fois <tab> pour obtenir la liste des possibilités. - -.. note:: Chemin absolu et relatif - - Pour écrire la position d'un fichier (son chemin), il y a deux manières de faire : - - * Le chemin absolu : il fait référence au chemin qu'il faut parcourir dans le système de fichier en démarrant de la racine, représenté par le caractère ``/``. - - * Le chemin relatif: il fait référence au chemin à parcourir depuis le dossier courant. - - -Expressions régulières ----------------------- - -Avant de commencer à voir les commandes utiles avec le shell, il est important de définir ce qu'est une expression régulière (`regex(3)`). Les expressions régulières caractérisent des chaînes de caractères et elles sont utiles pour de nombreuses commandes. Nous l'utiliserons notamment pour faire une recherche dans un fichier. - -Dans une regex, certains caractères ont une signification particulière : - - ============= ==================================== ==================================================== - Expression Explication Exemple - ============= ==================================== ==================================================== - ``\`` Caractère d'échappement ``[\.]`` contient un "." - ``^`` Début de ligne ``^b`` commence par b - ``.`` N'importe quel caractère ``^.$`` contient un seul caractère - ``$`` Fin de ligne ``er$`` finit par "er" - ``|`` Alternative ``^(a|A)`` commence par a ou A - ``( )`` Groupement ``^((a)|(er))`` commence par a ou er - ``-`` Intervalle de caractères ``^[a-d]`` commence par a,b,c ou d - ``[ ]`` Ensemble de caractères ``[0-9]`` contient un chiffre - ``[^]`` Tout sauf un ensemble de caractères ``^[^a]`` ne commence pas par a - ``+`` 1 fois ou plus ``^(a)+`` commence par un ou plusieurs a - ``?`` 0 ou 1 fois ``^(a)?`` commence ou non par un a - ``*`` 0 fois ou plus ``^(a)*`` peut ou non commencer par a - ``{x}`` x fois exactement ``a{2}`` deux fois "a" - ``{x,}`` x fois au moins ``a{2,}`` deux fois "a" au moins - ``{x, y}`` x fois minimum, y maximum ``a{2,4}`` deux, trois ou quatre fois "a" - ============= ==================================== ==================================================== - -Notes : - - - ``^b$`` = contient uniquement le caractère ``b`` - - ``^$`` = la ligne est vide - -Nous verrons plus en détail leur utilisation avec les commandes plus complexes. - - -Manipulation des répertoires ----------------------------- - -Chaque processus travaille dans un répertoire dit courant. C'est le répertoire dans lequel le processus accède pour lire ou écrire des fichiers lorsque le processus utilise un nom relatif. La commande `pwd(1)`_ affiche le chemin du répertoire courant. - -Il est possible de changer le répertoire courant du processus ou du shell en utilisant la commande `cd(1posix)`_. Exemples : - - - `cd(1posix)`_ `chemin` : change le répertoire courant par celui de "chemin". - - `cd(1posix)`_ : change le répertoire courant par le répertoire de login de l'utilisateur courant. - - `cd(1posix)`_ .. : remonte dans le répertoire prédécesseur dans l'arborescence des fichiers. - -La commande `mkdir(1)`_ permet de créer un répertoire. Elle prend comme argument le nom du répertoire à créer. -La commande `rmdir(1)`_ supprime un répertoire qui doit être vide. Pour effacer un répertoire et tous les fichiers qu'il contient, il faut utiliser la commande `rm(1)`_ avec l'option ``-r``. Ainsi, ``rm -r /tmp/t`` supprime le répertoire ``/tmp/t`` ainsi que tous les fichiers et sous-répertoires se trouvant dans ce répertoire. - -La commande `ls(1)`_ permet de connaître l'ensemble des fichiers et répertoires contenus dans le répertoire courant. Elle supporte plusieurs options dont les plus utiles sont : - - * ``-F`` : Positionne à la fin des noms de fichier un ``/`` pour les répertoires et ``*`` pour les fichiers exécutables - * ``-a`` : Affiche tous les fichiers, y compris les fichiers cachés (ceux qui commencent par le caractère ``.`` ) - * ``-d`` : Evite de lister le contenu d'un répertoire : si `rep` est un répertoire, ``ls -l`` `rep` listera le contenu du répertoire `rep`, alors que ``ls -ld`` `rep` listera la description du répertoire - * ``-l`` : Description complète du contenu d'un répertoire (une ligne par fichier) - -Avec l'option ``-l``, le premier caractère de la ligne indique le type du fichier. Le caractère ``-`` correspond à un fichier standard et ``d`` à un répertoire. Il est aussi possible de connaître le contenu d'un autre répertoire que le répertoire courant en fournissant le nom de ce répertoire comme argument à la commande ``ls``. - - .. code-block:: console - - /repertoiretest $ ls - file.txt repertoiresoustest/ - - /repertoiretest $ l repertoiresoustest/ - first.txt log.log second.txt - - -Manipulation de fichiers ------------------------- - -Créer et détruire -^^^^^^^^^^^^^^^^^ - - * > filename crée un fichier vide. - * `touch(1)`_ filename crée un fichier vide. - * `echo(1)`_ mon_texte > filename crée un fichier avec "mon_texte" dedans. - - `rm(1)`_ [-irf] files efface les fichiers - * -i : intéractif, demande une confirmation sur chaque fichier - * -f : force la suppression du fichier - * -r : efface un répertoire et son contenu - -Visualiser -^^^^^^^^^^ - - * `cat(1)`_ [-opt] f1 f2 concatène et affiche les deux fichiers. - * `cat(1)`_ [-opt] file affiche le fichier sur la sortie standard. - - * -v : convertit les caractères spéciaux en caractères affichables - * -n : numérote les lignes - * -b : numérote seulement les lignes non vides - * -E : affiche le symbôle $ à la fin de chaque ligne - * -T : affiche les caractères de tabulation comme ^I - * -A : équivalent à -vET - * -e : équivalent à -vE - * -t : équivalent à -vT - - Avec cat, il est possible d'écrire depuis la console dans un fichier. - Appuyez sur ctrl+D au début d'une ligne pour terminer la saisie - - .. code-block:: console - - $ cat > monfichier.txt - En faisant ceci je remplace le texte dans - monfichier.txt - $ - - $ cat >> monfichier.txt - et je rajoute ceci à la fin - $ - - $ cat monfichier.txt - En faisant ceci je remplace le texte dans - monfichier.txt - et je rajoute ceci à la fin - - -`nl(1)`_ [-opt] file affiche le contenu d'un fichier et en numérote les lignes. - * -bt : numérote les lignes non vides (par défaut) - * -ba : numérote toutes les lignes - * -bpXXX : numérote seulement les lignes qui contiennent la chaîne de caractères XXX - * -sX   : supprime le décalage dû à la numérotation et utilise le séparateur X - * -s'XXX' : supprime le décalage dû à la numérotation et utilise la chaîne 'XXX' - -`paste(1)`_ [-opt] f1 f2 concatène horizontalement et affiche les deux fichiers. - * -s : copie les lignes d'un fichier sur une ligne - -`more(1)`_ file visualise le contenu du ou des fichiers par page. - Si il contient plus d'une page : - * q ou Q : pour terminer la visualisation - * RETURN : pour visualiser une ligne supplémentaire - * ESPACE : pour visualiser la page suivante - * h : pour obtenir de l'aide - -Modifier -^^^^^^^^ - -`touch(1)`_ filename met à jour les dates d'accès et de modification du fichier. Crée le fichier si il n'existe pas. - * -c : empêche la création du fichier si celui ci n'existe pas - * -m : change uniquement la date de modification du fichier - * -a : change uniquement la date d'accès du fichier - -`split(1)`_ [-opt] file [out] coupe le fichier en plusieurs petites parties - * -b nbr : decoupe selon un nombre d'octets - * -n nbr : decoupe selon un nombre de lignes - -Extraction de données -^^^^^^^^^^^^^^^^^^^^^ - -`grep(1)`_ [-opt] regex file recherche l'expression dans les fichiers. - * -i : ignore la casse - * -v : affiche les lignes ne contenant pas l'expression. - * -c : compte les lignes ne contenant pas la chaine - * -n : numérote chaque ligne contenant la chaîne - * -x : affiche les lignes correspondant exactement à la chaine - -`uniq(1)`_ [-opt] filename affiche le fichier en supprimant les lignes qui se répètent successivement. - * -u : Affiche seulement les lignes n'apparaissant qu'une seule fois - * -d : Affiche seulement les lignes répétées - * -c : En plus de l'affichage standard, chaque ligne est précédée du nombre de répétitions - Si cette option est utilisée, alors les options -u et -d sont ignorées. - * -i : ignore la casse - * -s N : ne compare pas les N premiers caractères de chaque ligne - * -w N : ne compare pas plus de N caractères de chaque ligne - -`sort(1)`_ [-opt] filename trie les lignes par ordre alphabétique. - * -f : ignore la casse - * -r : inverse l'ordre de tri - * -o : modifie la sortie standard - * -t : modifie le caractère séparateur. Par défaut c'est une chaîne de blancs - * -n : compare selon la valeur arithmétique - * -k : spécifie la colonne utilisée pour le tri - - uniq et sort sont souvent utilisés ensemble. Par exemple, cette commande trie les lignes de file.txt selon leur nombre d'apparitions. - - .. code-block:: console - - $ cat file.txt - une fois - deux fois - deux fois - trois fois - encore une fois - trois fois - toujours une fois - trois fois - - $ sort file.txt | uniq -c | sort -n - 1 encore une fois - 1 toujours une fois - 1 une fois - 2 deux fois - 3 trois fois - - Une autre utilisation possible est de pouvoir trier un fichier, par exemple CSV, sur une colonne particulière. Tout d'abord, il faut modifier le séparateur de colonne avec -t, puis spécifier la colonne - - .. code-block:: console - - $ cat file.txt - pcr,01,3 - pcr,1,3 - pcr,04,5 - pcr,03,6 - alex,03,6 - zorro,01,20 - zorro,5,4 - - $ cat file.txt | sort -t, -k2n - zorro,01,20 - pcr,01,3 - pcr,1,3 - alex,03,6 - pcr,03,6 - pcr,04,5 - zorro,5,4 - -`diff(1)`_ [-opt] f1 f2 compare le contenu de deux fichiers. - * -i : ignore la casse - * -c : rapport plus clair - * -q : indique uniquement si les fichiers sont différents - * -b : ignore les différences dues à des espaces blancs - * -B : ignore les différences dues à des lignes blanches - - .. code-block:: console - - $ cat test.txt - premiere ligne similaire - - deuxieme differente - et moi pareil - troisieme comme la deuxieme - - et enfin la quatrieme est la meme! - $ cat testbis.txt - premiere ligne similaire - en effet, je ne lui ressemble pas.. - et moi pareil - moi non plus, tres cher. - - et enfin la quatrieme est la meme! - - $ diff test.txt testbis.txt - 2,3c2 = Les lignes 2,3 du premier fichier et 2 du second sont différentes - < _ - < deuxieme differente \ - --- > Affichage des lignes différentes - > en effet, je ne lui ressemble pas.. _/ - 5c4 _ - < troisieme comme la deuxieme \ - --- > Même réflexion - > moi non plus, tres cher. _/ - - -Obtenir des informations -^^^^^^^^^^^^^^^^^^^^^^^^ - -`wc(1)`_ [-opt] filename donne sur stdout des informations au sujet de l'entrée standard ou d'une liste de fichiers. - Première colonne est le nombre de lignes, deuxième le nombre de mots et en dernier le nombre d'octets. - * -l : nombre de lignes - * -c : nombre d'octets - * -m : nombre de caractères - * -L : la longueur de la plus longue ligne - * -w : le nombre de mots - -Manipulations communes aux répertoires et fichiers --------------------------------------------------- - -Copier -^^^^^^ - -`cp(1)`_ [-opt] src dst copie la src dans le fichier dst. - Si dst n'existe pas, il est créé. Sinon, si c'est un fichier, son contenu est écrasé. - * -r : spécifie la copie d'un répertoire - * -u : copie uniquement si src est plus récent que dst ou si il est manquant dans dst - - Note : Si la destination est un répertoire, alors la source peut être une liste de fichiers. - - .. code-block:: console - - $ cp test.txt ./testbis/ - $ cp test.txt btest.txt ../ - $ cp -r repertoire ../repertoirebis - -Déplacer ou renomer -^^^^^^^^^^^^^^^^^^^ - -`mv(1)`_ [-opt] src dst renomme ou déplace src en dst. - * -f : écrase les fichiers existants - * -i : demande confirmation avant d'écraser un fichier existant - * -n : n'écrase aucun fichier déja existant - - Note : Si la destination est un répertoire, alors la source peut être une liste de fichiers. - - .. code-block:: console - - $ mv test.txt testrename.txt - $ mv test.txt ./testbis/ - $ mv repertoire ./repertoirebis - -Rechercher -^^^^^^^^^^ - -Pour les critères de recherche : - * critère1 critère2 = et logique - * !critère = non logique - * critère1 -a critère2 = ou logique - -`find(1)`_ chemin regex recherche les fichiers/répertoires caractérisés par nom, à partir du répertoire rep et affiche le résultat. - * -name : sur le nom du fichier - * -perm : sur les droits d'accès du fichier - * -links : sur le nombre de liens du fichier - * -user : sur le propriétaire du fichier - * -group : sur le groupe auquel appartient le fichier - * -type : sur le type (d=répertoire, c=caractère, f=fichier normal) - * -size : sur la taille du fichier en nombre de blocs (1 bloc=512octets) - * -atime : par date de dernier accès en lecture du fichier - * -mtime : par date de dernière modification du fichier - * -ctime : par date de création du fichier - * -print : affiche les fichiers sur stdout - - .. code-block:: console - - $ find ./ -name "*fi*" -print = contenant fi - $ find ./ -mtime "3" -print = modifié dans les trois derniers jours - $ find ./ -name "*s*" -a -name "f*" = contenant s et commençant par f - - Note : "./" représente le répertoire courant - - - Il y a trois remarques à faire sur la commande find : - - * Il est parfois nécessaire de mettre -print dans la commande pour afficher le résultat - - * Lors de larges recherches, il peut y avoir un message d'erreur pour chaque tentative d'accès à un fichier où vous n'avez pas d'autorisation d'accès, par exemple des fichiers système. Pour éviter que ces messages d'erreur ne polluent la recherche, il faut rediriger la sortie d'erreur standard dans "un puits sans fond". Pour cela, rajoutez 2>/dev/null - - * Il est parfois très utile de pouvoir exécuter une commande sur les fichiers trouvés. La solution la plus légère est de rediriger la sortie et de lui attribuer une commande. Pour cela, il faut faire : "find rep -name expr| xargs commande". Cette commande est expliquée dans la section "Commandes plus complexes". - - - Pour cet exemple, le résultat est tous les fichiers dont le nom contient "mon test", et donc le fichier contient "supertab". - .. code-block:: console - - $ find /testdirectory -name *mon test* -type f | xargs grep supertab - - -Création de lien -^^^^^^^^^^^^^^^^ - -`ln(1)`_ [-opt] src dst création d'un lien (raccourci) sur un fichier ou un répertoire. Attention un lien n'est pas une copie. - Il existe deux sortes de liens: - * le lien physique : uniquement des fichiers - * le lien symbolique (avec l'option -s) : fichiers et répertoires - - "SHEMA" - -Dans le cas de lien physique, on supprime le fichier en supprimant tous les liens qui pointent sur ce fichier. -Par contre pour des liens symboliques, vous pouvez effacer le fichier sans effacer les liens, mais alors ceux-ci seront invalides. - -Archivage et compression -^^^^^^^^^^^^^^^^^^^^^^^^ - -Il est important de noter qu'une archive n'est pas forcément compressée. - -`tar(1)`_ [-opt] tarname.tar files crée une archive à partir d'une liste de fichiers ou de répertoires. - * f : argument obligatoire, sauf si l'on veut lire ou écrire vers/depuis un lecteur de bande - * c : crée une archive - * z : compresse l'archive créée, en utilisant gzip. (Attention, l'extension doit être "tar.gz") - * j : compresse mieux l'archive mais prend plus de temps. (Attention, l'extension doit être "tar.bz2") - * x : désarchive - * t : inspection de l'archive - - .. code-block:: none - - $ tar cf monarchive.tar firstfile.c secondfile.c = crée une archive contenant deux fichiers - $ tar cfz monarchive.tar.gz firstfile.c secondfile.c = crée une archive compressée - $ tar tf monarchive.tar = inspecte l'archive créée - firstfile.c - secondfile.c - $ tar xf monarchive.tar.gz = désarchive - $ tar xf monarchive.tar -C /home = désarchive monarchive.tar dans /home - - -`gzip(1)`_ file compresse un fichier ou une archive - * -c : la compression est effectuée sur la sortie standard au lieu du fichier lui-même - * -c1 : compression plus rapide - * -c9 : meilleur compression - - .. code-block:: console - - $ gzip secondfile.c = compresse un fichier et produit un fichier .gz - $ gzip monarchive.tar = compresse une archive - - $ ls - monarchive.tar = compresse monarchive.tar vers monarchive.tar.gz - $ gzip monarchive.tar - ls - monarchive.tar monarchive.tar.gz - -Permissions -^^^^^^^^^^^ - -Pour chaque fichier, il y a trois classes d'utilisateurs - * user : le propriétaire du fichier - * groupe : le groupe auquel appartient le fichier - * autre : tous les autres - -Les permissions accordées à ces trois classes sont : - * r : lecture - * w : écriture - * x : exécution (Un fichier peut être executé et un répertoire peut devenir répertoire courant) - - -`chmod(1)`_ mode files change les permissions du ou des fichiers/répertoires. - - .. code-block:: console - - user group other - mode désiré : rwxr-xr-- rwx r-x r-- - 111 101 100 (en binaire) - 7 5 4 (en hexadecimal) - - d'où la commande ``chmod 754 fichier`` - - -`chown(1)`_ owner files change le propriétaire du fichier. - -`chgrp(1)`_ grp files change le groupe du fichier. - -Obtenir des informations -^^^^^^^^^^^^^^^^^^^^^^^^ - -`stat(1)`_ [-opt] filename donne des informations sur les métadonnées associées au fichier - * -f : affiche l'état du système de fichiers plutôt que celui du fichier - * -L : suit les liens du fichier - * -t : affiche les informations de façon concise - * --format=FORMAT : affiche les informations selon le format choisi - - .. code-block:: console - - Séquences de format valables pour les fichiers : - %a droits d'accès en octal - %A droits d'accès dans un format lisible par un humain - %b nombre de blocs alloués (voir << %B >>) - %B taille, en octets, de chaque bloc rapporté par %b - %d numéro de péripherique en décimal - %D numéro de péripherique en hexadécimal - %f mode brut en hexadécimal - %F type de fichier - %g identifiant de groupe du propriétaire - %G nom de groupe du propriétaire - %h nombre de liens directs (<< hard >>) - %i numéro d'inode - %m point de montage - %n nom de fichier - %N nom du fichier cité, déréférencé s'il s'agit d'un lien symbolique - %o taille de bloc d'entrée/sortie - %s taille totale, en octets - %u identifiant du propriétaire - %U nom d'utilisateur du propriétaire - %w date de création au format lisible, ou << - >> si elle n'est pas connue - %x date du dernier accés au format lisible - %y date de la dernière modification au format lisible - %z date du dernier changement au format lisible - - Séquences de format valables pour les systèmes de fichiers : - %a nombre de blocs libres disponibles pour les utilisateurs normaux - %b nombre total de blocs de données dans le système de fichiers - %c nombre total d'inodes dans le système de fichiers - %d nombre d'inodes libres dans le système de fichiers - %f nombre de blocs libres dans le système de fichiers - %i identifiant du système de fichier en hexadécimal - %l longueur maximale des noms de fichier - %n nom de fichier - %s taille des blocs (pour des transferts plus rapides) - %S taille fondamentale des blocs (pour le décompte des blocs) - %t type en hexadecimal - %T type dans un format lisible par un humain - - -Gestion des processus ---------------------- - -`top(1)`_ affiche les processus en cours d'exécution. -`pstree(1)`_ affiche l'arbre des processus. - -`strace(1)`_ [-opt] cmd trace les appels systèmes et la création de signaux effectués par une commande - * -c : collecte quelques statistiques de base concernant les appels système tracés - * -o : redirige la sortie standard - * -p : avec cette option, cmd est remplacé par le PID d'un processus, et celui ci est tracé - * -T : indique le temps passé dans chaque appel système - * -t : indique l'heure au début de chaque ligne. -tt comprend les microsecondes - * -r : donne le temps entre deux appels systèmes successifs - - .. code-block:: console - - $ strace -c ./monexecutable -o fichierRecoltantLesInformations.log - - -`lsof(8)`_ [-opt] affiche les fichiers ouverts. - * -p PID : uniquement les fichiers ouverts du processus - * -i : affiche les connexions réseau ouvertes - - .. code-block:: console - - $ lsof -i -p 2735 = Les connexions ouvertes ET les fichiers ouverts par le processus 2735 - $ lsof -i -a -p 2735 = Les connexions ouvertes par le processus 2735 - - -`kill(1)`_ pid supprime le processus specifié. Si malgré la commande, le processus n'est pas détruit, essayez kill -9 pid. - - -Symboles utiles ---------------- - -Redirection de l'entrée, sortie et erreur standard -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Lors de l'exécution d'une commande, un processus est créé et celui-ci va ouvrir trois flux : l'entrée, la sortie et l'erreur standard. Par défaut lorsque l'on exécute un programme, les données sont donc lues à partir du clavier et le programme envoie sa sortie et ses erreurs sur l'écran. toutefois, il est possible de rediriger ces flux. - - * < l'entrée standard est lue à partir d'un fichier - * > La sortie standard est redirigée dans un fichier. Si le fichier existe, il est vidé avant d'écrire. - * >> La sortie standard est redirigée dans un fichier. Si le fichier existe, la sortie standard est ajoutée à la fin de celui ci. - * 2> La sortie d'erreur standard est redirigée - * cmd1 | cmd2 La sortie standard de cmd1 devient l'entrée standard de cmd2 - -Symboles pour les commandes -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - * ``?`` caractère joker remplaçant un seul caractère - * ``!`` inverse le sens d’un test ou l’état de sortie d’une commande. - - * ``*`` caractère joker remplaçant une chaîne de caractères - * ``&`` exécute une commande en arrière-plan - * ``;`` sépare des instructions sur une seule ligne - - * ``cmd1 && cmd 2`` cmd2 n'est exécuté que si cmd1 réussit - * ``cmd1 || cmd 2`` cmd2 n'est exécuté que si cmd1 échoue - - * ``\`` annule l'effet du caractère spécial suivant - * ``" "`` annule l'effet de tous les caractères spéciaux entre les guillemets, sauf ``$`` et ``\`` - - -Commandes utiles ----------------- - -Pour effectuer des chaînes -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -`xargs(1)`_ permet d'appliquer une commande à l'entrée standard. - - Pour cet exemple, le résultat est tous les fichiers dont le nom contient "mon test", et dont le fichier contient "supertab". - - .. code-block:: console - - $ find /testdirectory -name *mon test* -type f | xargs grep supertab - -`tee(1)`_ file lit depuis l'entrée standard, écrit dans la sortie standard et dans le fichier. Elle est utilisée pour continuer une chaîne tout en faisant une sauvegarde des informations. - - .. code-block:: console - - % echo "Les tubes sont un mécanisme puissant." | tee fichier.txt | wc - 1 6 39 - % cat fichier.txt - Les tubes sont un mécanisme puissant. - - On peut voir que le texte a bien été relayé vers la commande "wc" et qu'en même temps, ce texte a été écrit dans fichier.txt - - -Informations générales -^^^^^^^^^^^^^^^^^^^^^^ - -`su(1)`_ passe en mode "root", c'est à dire administrateur - -`whatis(1)`_ cmd explique briévement l'utilité d'une commande - -`apropos(1)`_ [-opt] motclé recherche dans les man pages les commandes correspondants aux mots clés. - * -a : Affiche seulement les résultats répondant à tout les mots clés. - L'inverse est le fonctionnement par défault - -`date(1)`_ donne l'heure, selon l'horloge de votre ordinateur - -`cal(1)`_ affiche un calendrier du mois courant - -`halt(8)`_ éteint l'ordinateur. - -`reboot(8)`_ redémarre l'ordinateur - -Informations système -^^^^^^^^^^^^^^^^^^^^ - -`time(1posix)`_ programme permet de calculer le temps d'exécution d'un programme - -`df(1)`_ [-opt] [file] indique l'espace disque utilisé et disponible sur tous les systèmes de fichiers. - Si des fichiers sont passés en argument, seul les systèmes de fichiers contenant un des fichiers sont montrés. - - * -h Imprime les dimensions dans un format lisible par l’utilisateur - * -H Idem que -h, mais il utilise des puissances de 1000 au lieu de 1024 - * -i Affiche l’information i-node au lieu de l’utilisation des blocs - * -l Limite l’affichage aux systèmes de fichiers locaux - * -P Utilise le format de résultat POSIX - * -T Imprime le type de système de fichiers - - -Maniement des jobs -^^^^^^^^^^^^^^^^^^ - -La plupart des commandes en console sont exécutées rapidement, mais ce n'est pas le cas de toutes. Certaines commandes, que l'on va appeler `jobs`, prennent plus de temps (comme par exemple copier un très gros fichier), et d'autres encore tournent indéfiniment. - -Évidemment, quand un job est en cours d'exécution à la console, plus aucune action ne peut être faite sur celle-ci. Unix nous vient en aide dans ce cas-là avec le raccourci ``Ctrl+z`` et les commandes `jobs(1)`_, `bg(1)`_ et `fg(1)`_. - - * ``Ctrl+z`` : Le job passe dans l'état ``suspended``. Il est en pause, et placé en background. - * ``jobs`` : Affiche à la console la liste des jobs présents en background - * ``bg`` : Passe un job mis en background de l'état ``suspended`` à l'état ``running``. Le job reste en background, mais il continue à s'exécuter - * ``fg`` : Passe un job du background à l'avant-plan - -Exemples : - - .. code-block:: none - - $ yes > \dev\null - #nous lançons la commande yes - - ^Z - #nous la suspendons avec Ctrl+z - [1]+ Stopped yes > \dev\null - #elle est placée en arrière-plan - - $ jobs - #nous regardons la liste des jobs en arrière plan - [1]+ Stopped yes > \dev\null - #chaque job à un numéro qui lui est attribué. ici 1 - - $ bg 1 - #nous relançons yes en arrière-plan. On peut utiliser son nom comme son numéro avec la commande bg et fg - [1]+ yes > \dev\null & - #yes s'est remis en route - - $ jobs - #nous vérifions le statut de yes avec jobs - [1]+ Running yes > \dev\null & - #il est en cours d'exécution - - $ fg yes - #nous remettons yes en avant-plan - yes > \dev\null - - ^Z - #nous le suspendons à nouveau - [1]+ Stopped yes > \dev\null - - $ kill %1 - #nous terminons yes avec la commande kill %[numJob] - [1]+ Stopped yes > \dev\null - - $ jobs - #nous vérifions les jobs - [1]+ Terminated: 15 yes > \dev\null - #yes est marqué Terminated - - $ jobs - #un deuxième appel à jobs nous affiche une liste vide - - -.. _`jobs(1)`: http://www.manpagez.com/man/1/jobs/ -.. _`bg(1)`: http://linux.die.net/man/1/bg -.. _`fg(1)`: http://linux.die.net/man/1/fg - - -Commandes complexes -------------------- - -Modification d'un fichier -^^^^^^^^^^^^^^^^^^^^^^^^^ - - - -`sed(1)`_ [-n] [-e 'prog'] [-f cmdfile] [file] applique des commandes de 'prog' sur un fichier - - * -n : n'affiche aucune ligne, sauf celle spécifiée avec la commande p - * -e : specifie les commandes à appliquer sur le fichier - Note : Il vaut mieux encadrer la commande avec des ' ou des " - * -f : les commandes sont lues à partir d'un fichier - -Pour bien comprendre la puissance de sed, il est important de comprendre son fonctionnement. sed fonctionne en 4 étapes : - - * Lecture d'une ligne sur le flux d'entrée, et stockage dans l'espace de travail - * Exécute les commandes sur l'espace de travail - * Envoie la ligne au flux de sortie en lui rajoutant un '\n' - * Recommence avec la ligne suivante ... - - -Une commande d'un 'prog' est constituée d'un adressage, c-à -d les lignes sur lesquelles la commande est appliquée, et de l'action à exécuter. - -1) L'adressage est décomposé en deux catégories. - - * : toutes les lignes - * num : la ligne "num". La dernière ligne est symbolisée par $ - * num1, num2 : les lignes entre num1 et num2 - - * /regex/ : les lignes correspondant à l'expression régulière regex - * /regex1/, /regex2/ : les lignes entre la première ligne correspondant à regex1 et la première ligne correspondant à regex2 - Si regex2 est vide, la commande sera appliquée jusqu'à la fin du fichier. - - Note : Le ! représente la négation. Mettez le après votre spécification des lignes pour prendre la négation - - RAPPEL sur les regex : - - - ============= ==================================== ==================================================== - Expression Explication Exemple - ============= ==================================== ==================================================== - ``\`` Caractère d'échappement ``[\.]`` contient un "." - ``^`` Début de ligne ``^b`` commence par b - ``.`` N'importe quel caractère ``^.$`` contient un seul caractère - ``$`` Fin de ligne ``er$`` finit par "er" - ``|`` Alternative ``^(a|A)`` commence par a ou A - ``( )`` Groupement ``^((a)|(er))`` commence par a ou er - ``-`` Intervalle de caractères ``^[a-d]`` commence par a,b,c ou d - ``[ ]`` Ensemble de caractères ``[0-9]`` contient un chiffre - ``[^]`` Tout sauf un ensemble de caractères ``^[^a]`` ne commence pas par a - ``+`` 1 fois ou plus ``^(a)+`` commence par un ou plusieurs a - ``?`` 0 ou 1 fois ``^(a)?`` commence ou non par un a - ``*`` 0 fois ou plus ``^(a)*`` peut ou non commencer par a - ``{x}`` x fois exactement ``a{2}`` deux fois "a" - ``{x,}`` x fois au moins ``a{2,}`` deux fois "a" au moins - ``{x, y}`` x fois minimum, y maximum ``a{2,4}`` deux, trois ou quatre fois "a" - ============= ==================================== ==================================================== - - - Notes : - - - ``^b$`` = contient uniquement le caractère ``b`` - - ``^$`` = la ligne est vide - -2) Les actions - - * p : affiche les lignes - * d : supprime les lignes - * y/l1/l2 : remplace les caractères de la première liste par les caractères de la seconde - * s/mtf/sbst/ : substitue le mtf par le sbst - Note : Par défaut seule la première occurrence est remplacée. - * Pour toutes les remplacer : /s/motif/substitut/g - * Pour en remplacer 4 : /s/motif/substitut/4 - - * N : charge une ligne supplémentaire dans l'espace de travail - * D : efface l'espace de travail jusqu'au premier saut de ligne incorporé - * b : revient - - Pour faire des commandes groupées, placez vos commandes entre {} séparées par ";". - - Quelques illustrations basiques : - - .. code-block:: none - - $ sed '' test.txt = Le script est vide, il renvoie simplement le fichier - - $ sed -n '/Ici/p' test.txt = Affiche les lignes contenant Ici - $ sed 'p' test.txt = Double toutes les lignes - - $ sed -e '4d; 7d' test.txt = Supprime les lignes 4 et 7 - $ sed -e '4,7d' test.txt = Supprime les lignes entre 4 et 7 - - $ sed '/^#/ d' test.txt = Supprime les lignes commencant par # - $ sed '/e$/ d' test.txt = Supprime les lignes se terminant par e - $ sed '/#/,/@/d' test.txt = Supprime les lignes comprises entre le premier # et le premier @ - - $ sed -e 's/^#//' test.txt = Supprime le commentaire en début de ligne, puisqu'il - est remplacé par '' - - $ sed -e 'y/éèê/eee/' test.txt = Retire les accents, puisqu'ils sont remplacés par 'e' - - $ sed -e ' 4,7 {y/éèê/eee/;s/e/[]/} test.txt = Remplace les accents, puis remplace les "e" par "[]" - - $ sed -e '/^$/ {N; D}' test.txt = Supprime les sauts de ligne - - - Explication : Pour les lignes vides, on charge la ligne suivante, on envoie ce qui se trouve dans l'espace de travail jusqu'au premier '\n', puis on continue le traitement du texte. Pour continuer le traitement, une nouvelle ligne est chargée et va donc "écraser" les '\n' qui sont toujours présents dans l'espace de travail. - - -Lors du remplacement d'un mot par un autre, il peut survenir un problème de taille. En effet, le remplacement n'est effectué que sur le premier mot de la ligne trouvé. - - .. code-block:: console - - $ sed -e ' s/[oe]/[/' test.txt - B[njour, - - C[ci est un fichier de test. - Ici la lign[ numéro 4. - - # c[ci pourrait être un commentaire - Ici la lign[ numéro 7.I - - Au r[voir - - On remarque que tout les 'e' et 'o' n'ont pas été remplacés... - -Pour contrecarrer ce problème, il est possible de placer dans le script un label et de revenir dessus, comme un goto en C. Pour effectuer ce retour utilisez la commande 'b'. - - .. code-block:: console - - $ sed -re ':start {s/[eo]/[/g; /[eo]/ b start}' test.txt - B[nj[ur, - - C[ci [st un fichi[r d[ t[st. - Ici la lign[ numér[ 4. - - # c[ci p[urrait êtr[ un c[mm[ntair[ - Ici la lign[ numér[ 7.I - - Au r[v[ir - - Explication : Un label est placé au début des commandes. La première commande remplace le premier [eo] trouvé. La seconde retourne au label si il reste encore un [eo] dans la ligne. Une fois qu'il n'y a plus de [eo], la ligne suivante est chargée. - - -Appliquer des actions à un fichier -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -`awk(1)`_ [-Fs] [-v variable] [-f fichier de commandes] 'program' fichier - * -F : Spécifie les séparateurs de champ - * -v : Définit une variable utilisée à l'intérieur du programme. - * -f : Les commandes sont lues à partir d'un fichier. - -Note : awk est une commande extrêmement puissante, elle permet d'effectuer une multitude d'opérations. Son utilisation est complexe et elle est bien détaillée sur ce site : http://www.shellunix.com/awk.html. Je vous encourage à le lire. - - -Redirection nommée -^^^^^^^^^^^^^^^^^^ - -`mkfifo(1)`_ nom crée un tube nommé - - .. code-block:: console - - ls | less est donc similaire à mkfifo /tmp/tempfifo - ls > /tmp/tempfifo - less < /tmp/tempfifo - - - - - - -.. _bash: - -Bash ----- - -Taper des commandes dans la console est inévitable lors d'opérations avancées sur un système Unix, et peut devenir très vite répétitif et fastidieux pour l'utilisateur. Le Bash est justement là pour éviter ces répétitions et automatiser certaines tâches à l'aide de scripts, qui sont des fichiers texte composés de différentes commandes Unix, lus, interprétés et exécutés par Bash. - - -Premier script -^^^^^^^^^^^^^^ - -Nous allons écrire un premier script bash pour présenter la manière générale de procéder avec un tel outil. Les scripts commencent toujours par la ligne ``#!/bin/bash`` qui indique à l'exécution qu'il s'agit d'un script et avec quel interpréteur le lire (ici bash). - - .. code-block:: bash - - #!/bin/bash - echo "Hello, 1252" - -Nous allons enregistrer ce texte sous le nom `hello.sh <https://raw.github.com/HappyRave/SystInfo1/master/valgrind/hello.sh>`_, puis changer ses permissions pour le rendre exécutable. - - .. code-block:: console - - $ chmod 700 hello.sh - -Après il ne reste plus qu'à l'exécuter et observer le résultat. - - .. code-block:: console - - $ ./hello.sh - Hello, 1252 - -Les variables -^^^^^^^^^^^^^ - -Bash permet l'utilisation de variables dans les scripts. Il peut s'agir de simples variables ou de tableaux. Bash n'est pas un langage typé, les Int ou les String n'existent pas, toutes les variables sont traitées de la même façon. Pour illustrer ceci nous allons écrire le script `variables.sh <https://raw.github.com/HappyRave/SystInfo1/master/valgrind/variables.sh>`_ - - .. code-block:: bash - - #!/bin/bash - - bonjour='Hello, ' - #il est important de ne pas mettre d'espaces autour du = - nombre[0]=12 - nombre[1]=52 - - echo $bonjour${nombre[0]}${nombre[1]} - #on accède à une variable simple avec un $ devant son nom - #on accède à un élément d'un tableau avec un $ devant et des {} autour - echo $bonjour${nombre[*]} - #le caractère * indique qu'on veut utiliser tous les éléments du tableau (séparés - #par un espace à chaque fois) - -Ce script produit comme résultat - - .. code-block:: console - - $ ./variables.sh - Hello,1252 - Hello,12 52 - -Il est interressant de visiter cette page : http://michel.mauny.net/sii/variables-shell.html - -Les structures de contrôle -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Comme dans chaque langage de programmation, bash offre les structures de contrôle habituelles telles que les boucles if, for ou encore while que nous allons démontrer maintenant. - -Comme dit précédemment, il n'y a pas de type en bash, true et false n'existent pas. Les conditions que les boucles vont utiliser seront les valeurs renvoyées par l'exécution d'une commande. Un 0 renvoyé correspond à un true, tandis que tout le reste est considéré comme un false. - -Dans le but de tester ces boucles nous utiliserons un petit programme en C, `return.c <https://raw.github.com/HappyRave/SystInfo1/master/valgrind/return.c>`_, qui va renvoyer la valeur qu'il reçoit en argument. Le script de test est `structures.sh <https://raw.github.com/HappyRave/SystInfo1/master/valgrind/structures.sh>`_. - - .. code-block:: bash - - #!/bin/bash - - if ./return 0; then - #la valeur de renvoi sera 0 quand la boucle aura été exécutée - echo "Hello" - fi - - if ./return 1; then - #ici c'est la condition else qui sera remplie - echo "Hello" - else - echo "Bye" - fi - - for i in 1 2 5 2 - #les boucles for peuvent s'écrire de cette façon - do - echo $i - done - - echo Hello again! - - for (( j=1; j<=5; j++)) - #ou encore utiliser la synthaxe classique comme en C ou Java - do - echo $j - done - - k=4 - while ((k>0)) - do - echo $k - k=$((k-1)) - done - -Le résultat à l'exécution est - - .. code-block:: console - - $ ./structures.sh - Hello - Bye - 1 - 2 - 5 - 2 - Hello again! - 1 - 2 - 3 - 4 - 5 - 4 - 3 - 2 - 1 diff --git a/Outils/src/calc.c b/Outils/src/calc.c deleted file mode 100644 index 3110bfef4e8612c5bd1c5a292902066a1a571f70..0000000000000000000000000000000000000000 --- a/Outils/src/calc.c +++ /dev/null @@ -1,21 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> - - -void calc(int a, int b) { - double res; - int i; - - for(i=0; i<6; i++) { - res += (a*5 -10) / (b-i); - printf("(%d * 5 - 17 ) / %d = %f\n", a, (b-i), res); - } -} - -int main(int argc, char *argv[]){ - int n = 165, m = 4; - - calc(n, m); - - return EXIT_SUCCESS; -} diff --git a/Outils/src/cunit.c b/Outils/src/cunit.c deleted file mode 100644 index b330f6c123f42d13e5a68047a3e32dd665b0ec50..0000000000000000000000000000000000000000 --- a/Outils/src/cunit.c +++ /dev/null @@ -1,65 +0,0 @@ -#include <stdlib.h> -#include <stdbool.h> -#include <limits.h> - -#include "CUnit/Basic.h" - -void test_assert_true(void) -{ - CU_ASSERT(true); -} - -void test_assert_2_not_equal_minus_1(void) -{ - CU_ASSERT_NOT_EQUAL(2, -1); -} - -void test_string_equals(void) -{ - CU_ASSERT_STRING_EQUAL("string #1", "string #1"); -} - -void test_failure(void) -{ - CU_ASSERT(false); -} - -void test_string_equals_failure(void) -{ - CU_ASSERT_STRING_EQUAL("string #1", "string #2"); -} - -int setup(void) { return 0; } -int teardown(void) { return 0; } - -int main() -{ - CU_pSuite pSuite = NULL; - if (CUE_SUCCESS != CU_initialize_registry()) - return CU_get_error(); - - pSuite = CU_add_suite("ma_suite", setup, teardown); - if (NULL == pSuite) { - CU_cleanup_registry(); - return CU_get_error(); - } - - if ((NULL == CU_add_test(pSuite, "Test assert true", test_assert_true)) || - (NULL == CU_add_test(pSuite, "Test assert 2 not equal -1", test_assert_2_not_equal_minus_1)) || - (NULL == CU_add_test(pSuite, "Test string equals", test_string_equals)) || - (NULL == CU_add_test(pSuite, "Test failure", test_failure)) || - (NULL == CU_add_test(pSuite, "Test string equals failure", test_string_equals_failure))) - { - CU_cleanup_registry(); - return CU_get_error(); - } - -// CU_basic_set_mode(CU_BRM_VERBOSE); - CU_basic_run_tests(); - printf("\n"); - CU_basic_show_failures(CU_get_failure_list()); - printf("\n\n"); - - CU_cleanup_registry(); - return CU_get_error(); -} \ No newline at end of file diff --git a/Outils/src/getopt.c b/Outils/src/getopt.c deleted file mode 100644 index 6d95c88a08d7e0dfbdfb79f987e6092eff8f2d8c..0000000000000000000000000000000000000000 --- a/Outils/src/getopt.c +++ /dev/null @@ -1,64 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -/* Definition et declaration de la structure des arguments*/ - -struct globalArgs_t { - int nbrThreads; /* Le nombre de threads lancés durant l'exécution*/ - char lettre; /* La lettre de réference*/ - int numInputFiles; /* Le nombre de fichiers qui vont être lus*/ - char **inputFiles; /* Les différents fichiers passés en arguments*/ -} globalArgs; - -static const char *optString = "t:l:h"; /* Les différentes options valables*/ - - -int main(int argc, char *argv[]){ - - int opt=0; - - /* Initialisation de globalArgs avant de commencer*/ - - globalArgs.nbrThreads=1; /* Le nombre de threads à exécuter par défaut est 1"*/ - globalArgs.lettre='a'; /* La lettre de réference par défaut est 'a' */ - globalArgs.numInputFiles=1; /* Il doit y avoir au minimum toujours 1 fichier input */ - globalArgs.inputFiles=NULL; - - opt=getopt(argc, argv, optString); /* On récupert la première option */ - - while(opt != -1){ /*Tant que l'option est valable (fait donc partie de optString)*/ - switch(opt){ - case 't': - globalArgs.nbrThreads=atoi(optarg); - break; - - case 'l': - globalArgs.lettre=optarg[0]; - break; - - case '?': - printf("Erreur : option non reconnue\n"); - exit(EXIT_FAILURE); - - case 'h': /*Display help*/ - - default: - /* On arrivera jamais ici*/ - break; - } - opt=getopt(argc, argv, optString); /* Prochaine option*/ - } - globalArgs.inputFiles=argv + optind; - globalArgs.numInputFiles=argc - optind; - - printf("Threads : %d , lettre : %c , nombre de fichiers : %d , nom des fichiers : ", globalArgs.nbrThreads, globalArgs.lettre, globalArgs.numInputFiles); - - int j; - for(j=0; j<globalArgs.numInputFiles; j++){ - printf(" %s ",globalArgs.inputFiles[j]); - } - printf("\n"); - - return EXIT_SUCCESS; -} diff --git a/Outils/src/getpid.c b/Outils/src/getpid.c deleted file mode 100644 index 15f24818f4d7a632cd1d54b5039ad31e87faf62f..0000000000000000000000000000000000000000 --- a/Outils/src/getpid.c +++ /dev/null @@ -1,28 +0,0 @@ -/************************************** - * getpid.c - * - * Programme d'exemple pour getpid - * - **************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -int main(int argc, char *argv[]) { - - unsigned int sec=30; - int pid=(int) getpid(); - - printf("Processus : %d\n",pid); - printf("[pid=%d] Sleep : %d secondes\n",pid, sec); - sec=sleep(sec); - if(sec==0) { - printf("[pid=%d] Fin du processus\n",pid ); - return(EXIT_SUCCESS); - } - else { - printf("[pid=%d] Interrompu alors qu'il restait %d secondes\n",pid,sec); - return(EXIT_FAILURE); - } -} diff --git a/Outils/src/malloc.c b/Outils/src/malloc.c deleted file mode 100644 index 9637bde6cbb5baf68609984998423c6e78f1617c..0000000000000000000000000000000000000000 Binary files a/Outils/src/malloc.c and /dev/null differ diff --git a/Outils/src/nofree.c b/Outils/src/nofree.c deleted file mode 100644 index 490d9d9d88f55af9d18f232c93faf54cc4c6120c..0000000000000000000000000000000000000000 --- a/Outils/src/nofree.c +++ /dev/null @@ -1,9 +0,0 @@ -#include <stdlib.h> - -int main(int argc, char * argv[]) -{ - char *ptrChars = (char *)malloc(6 * sizeof(char)); - ptrChars[0]= 'H'; - - return 0; -} diff --git a/Outils/src/outofbounds.c b/Outils/src/outofbounds.c deleted file mode 100644 index f1554c7237801c4a47bd02574a8d0db06ef13421..0000000000000000000000000000000000000000 --- a/Outils/src/outofbounds.c +++ /dev/null @@ -1,11 +0,0 @@ -#include <stdlib.h> - -int main(int argc, char * argv[]) -{ - char *ptrChars = (char *)malloc(6 * sizeof(char)); - ptrChars[0]= 'H'; - ptrChars[12]= 'W'; - free(ptrChars); - - return 0; -} \ No newline at end of file diff --git a/Outils/src/recursive.c b/Outils/src/recursive.c deleted file mode 100644 index 7355315c9a7fc12e6a67e60dc4c027d3d72cde04..0000000000000000000000000000000000000000 --- a/Outils/src/recursive.c +++ /dev/null @@ -1,29 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> - -int globalVar = 5; - -int factTmp(int acc, int nbr) { - static int globalTmp =0; - globalTmp++; - - int tmp =0; - tmp++; - - if(nbr<=1) return acc; - else return factTmp(acc*nbr, nbr-1); -} - - -int factTerminal(int a) { - int localVar = 3; - return factTmp(1, a); -} - - -int main(int argc, char *argv[]){ - - printf("La factorielle de 6 est : %d\n", factTerminal(6)); - - return EXIT_SUCCESS; -} diff --git a/Outils/src/tab.c b/Outils/src/tab.c deleted file mode 100644 index 7dddcd7f73bd0b0bbc9c62d015ac848af987bc8c..0000000000000000000000000000000000000000 --- a/Outils/src/tab.c +++ /dev/null @@ -1,31 +0,0 @@ -#include <stdio.h> - -void calc (int *tab, int i, int num) -{ - tab[i] = num / i; -} - -void iter (int *tab, int num) -{ - int i; - printf("Iterating\n"); - for (i = 0; i <= 10; i++) { - calc(tab, i, num); - } -} - -int main (int argc, char * argv[]) -{ - int *tab = NULL; - int num = 20; - int i; - - iter(tab, num); - - for (i = 0; i < 10; i++) { - printf("%d ", tab[i]); - } - printf("\n"); - - return 0; -} \ No newline at end of file diff --git a/Outils/src/thread_crash.c b/Outils/src/thread_crash.c deleted file mode 100644 index d22a2e8846854dcf926455d117806f59595ce8c7..0000000000000000000000000000000000000000 --- a/Outils/src/thread_crash.c +++ /dev/null @@ -1,34 +0,0 @@ -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> - -#define N_THREADS 3 - -pthread_mutex_t global_mutex; - -static void *thread_work(void *arg) -{ - pthread_mutex_lock(&global_mutex); - - /* Do some work here */ - - pthread_exit(NULL); - pthread_mutex_unlock(&global_mutex); -} - - -int main (int argc, char const *argv[]) -{ - int i; - pthread_t threads[N_THREADS]; - - pthread_mutex_init(&global_mutex, NULL); - - for (i = 0; i < N_THREADS; ++i) - pthread_create(&threads[i], NULL, thread_work, NULL); - - for (i = 0; i < N_THREADS; ++i) - pthread_join(threads[i], NULL); - - return 0; -} \ No newline at end of file diff --git a/Outils/src/twofree.c b/Outils/src/twofree.c deleted file mode 100644 index 384757aae21eb35514ca860f4e81e66e5dc066d8..0000000000000000000000000000000000000000 --- a/Outils/src/twofree.c +++ /dev/null @@ -1,11 +0,0 @@ -#include <stdlib.h> - -int main(int argc, char * argv[]) -{ - char *ptrChars = (char *)malloc(6 * sizeof(char)); - ptrChars[0]= 'H'; - free(ptrChars); - free(ptrChars); - - return 0; -} \ No newline at end of file diff --git a/Outils/ssh.rst b/Outils/ssh.rst deleted file mode 100644 index 1409ebac7ebabed68e2ab5dcaccdb85cdc8dbf24..0000000000000000000000000000000000000000 --- a/Outils/ssh.rst +++ /dev/null @@ -1,92 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch, Grégory Detal et Maxime De Mol -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -.. _ssh: - -SSH ---- - -`ssh(1)`_ est un outil qui permet de se connecter depuis l'Internet à la console d'une autre machine et donc d'y exécuter des commandes. Dans l'infrastructure INGI vous pouvez vous connecter via ssh aux différents machines des salles en utilisant votre login et mot de passe INGI. Pour savoir les noms de machines, visitez le `student-wiki <http://wiki.student.info.ucl.ac.be/Matériel/Matériel>`_. - -Depuis l'extérieur vous devez passer via ``sirius.info.ucl.ac.be`` pour ensuite pouvoir vous connecter sur les machines des salles. - -Quelques exemples d'utilisation de `ssh(1)`_ qui vous seront utiles: - - * ``ssh [username]@[hostname]``: Avec ceci vous pouvez vous connecter à la machine ``hostname``. Exemple: ``ssh myUserName@yunaska.info.ucl.ac.be`` pour vous connecter à la machine ``yunaska`` de la salle intel. Il faut d'abord se connecter à sirius avant de se connecter aux machines des salles. - * ``ssh -X [username]@[hostname]``: L'option ``-X`` vous permet d'exécuter des programmes sur la machine distante mais en voyant l'interface graphique en local sur votre machine (pour autant qu'elle supporte :term:`X11`). Exemple: ``ssh -X myUserName@yunaska.info.ucl.ac.be`` et ensuite dans le terminal ``gedit test.c`` pour ouvrir l'éditeur de texte. - * ``ssh [username]@[hostname] [commande]``: Pour exécuter la commande sur la machine distante. Exemple: ``ssh myUserName@sirius.info.ucl.ac.be cc test.c -o test`` pour exécuter ``cc test.c -o test`` sur sirius. - * ``scp [local_file] [username]@[hostname]:[path]``: `scp(1)`_ permet de copier des fichiers locaux vers un répertoire distant (et l'inverse). Exemple: ``scp test.c myUserName@sirius.info.ucl.ac.be:SINF1252/projet_S2/`` copie test.c vers le dossier ``SINF1252/projet_S2/`` de la machine sirius. - -Le site `Getting started with SSH <http://www.ibm.com/developerworks/aix/library/au-sshsecurity/>`_ contient une bonne description de l'utilisation de ssh. Notamment l'`utilisation de ssh sur des machines UNIX/Linux <http://www.ibm.com/developerworks/aix/library/au-sshsecurity/#SSH_for_UNIX>`_. Si vous utilisez Windows, il existe des clients `ssh(1)`_ comme `putty <http://www.putty.org/>`_ - -Authentification par clé -^^^^^^^^^^^^^^^^^^^^^^^^ - -Face à la faiblesse au niveau sécurité de l'authentification par mot de passe, l'authentification par clé se révèle être un moyen nettement plus efficace. - -L'authentification par clé consiste en un premier temps à générer une paire de clés et son mot de passe: - - * la ``clé publique`` que l'on exporte vers chaque hôte sur lequel on veut se connecter - * la ``clé privée`` que l'on garde précieusement sur notre ordinateur, et qui sert à prouver à l'hôte notre identité - * le ``mot de passe`` permet de sécuriser sa clé privée - -Le mot de passe ne servant à rien sans les clé et vice versa, on devine aisément que le niveau de sécurité d'une telle connexion est largement accru par rapport à une simple authentification par mot de passe. - -Pour générer ces clés et choisir votre mot de passe, il suffit d'entrer la commande - - .. code-block:: none - - $ ssh-keygen -t rsa -C "login" - # remplacer "login" par votre nom d'utilisateur - - Generating public/private rsa key pair. - Enter file in which to save the key (~/.ssh/id_rsa): - Enter passphrase (empty for no passphrase): - Enter same passphrase again: - Your identification has been saved in ~/.ssh/id_rsa. - Your public key has been saved in ~/.ssh/id_rsa.pub. - The key fingerprint is: - 17:bc:98:ab:39:f6:a2:db:1d:07:9a:63:d7:c7:9b:e0 "login" - -Maintenant que les clés ont été crées, il faut communiquer votre clé publique à l'hôte sur lequel vous voulez vous connecter. Pour cela, le plus simple est d'utiliser la commande suivante - - .. code-block:: console - - $ cat ~/.ssh/id_rsa.pub | ssh [username]@[hostname] "cat - >> ~/.ssh/authorized_keys" - -Cette commande va récupérer votre clé publique dans votre dossier ``~/.ssh``, se connecter en ssh à l'hôte et va placer votre clé dans son répertoire de clés autorisées. Maintenant nous pouvons utilisez en toute sérénité votre connexion ssh sécurisée! - -Petit mot sur les permissions du dossier ``~/.ssh`` où sont stockées les clés: - - .. code-block:: console - - .ssh user$ ls -ld - drwx------ 6 user staff 204 22 aoû 10:29 . - - -Les bits de permissions sont définis comme ``drwx------`` ce qui fait du propriétaire de ce dossier la seul personne capable de lire, d'écrire et d'exécuter le contenu de se dossier. La clé privée est donc belle et bien privée! - -Synchronisation de fichiers entre ordinateurs -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Quand nous avons besoin de synchroniser des fichiers entre 2 ordinateurs différents, Unix nous vient en aide avec l'utilitaire `rsync <http://linux.about.com/library/cmd/blcmdl1_rsync.htm>`_. - -L'utilisation la plus basique de `rsync <http://linux.about.com/library/cmd/blcmdl1_rsync.htm>`_ est: - - .. code-block:: console - - rsync *.c [hostname]:src/ - -`rsync <http://linux.about.com/library/cmd/blcmdl1_rsync.htm>`_ va copier tout les fichiers qui correspondent au pattern ``*.c`` du répertoire courant vers le dossier ``src/`` sur la machine hôte. De plus, si certains ou tout les fichiers sont déjà présents chez l'hôte, `rsync <http://linux.about.com/library/cmd/blcmdl1_rsync.htm>`_ va procéder à une mise à jour différentielle de ces fichiers (seuls les changements sont transférés). - -L'ajout du drapeau ``-avz`` permet de synchroniser les fichiers en mode archive. Cela veut dire que tous les liens, permissions, propriétaires, etc de ces fichiers seront préservés durant le transfert. - -Nous pouvons aussi utiliser `rsync <http://linux.about.com/library/cmd/blcmdl1_rsync.htm>`_ dans l'autre sens: - - .. code-block:: console - - rsync -avz [hostname]:src/bar /data/tmp - -Maintenant tout les fichiers de la machine hôte, dans le dossier src/bar vont être copiés vers le répertoire local /data/tmp. diff --git a/Outils/valgrind.rst b/Outils/valgrind.rst deleted file mode 100644 index 52d50993006de9b2e97c395c2d44b2135a54c169..0000000000000000000000000000000000000000 --- a/Outils/valgrind.rst +++ /dev/null @@ -1,238 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch, Grégory Detal et Maxime De Mol -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. _valgrind-ref: - -Valgrind --------- - -Plusieurs outils en informatique peuvent vous aider à localiser des bugs dans vos programmes. Parmi ceux-ci, voici deux outils particulièrement utiles pour les problèmes liés à la mémoire : - - * `valgrind(1)`_ vous permet de détecter des erreurs liés à la gestion de la mémoire (`malloc(3)`_, `free(3)`_,...) - * `gdb(1)`_ permet de voir ce qui se passe "à l'intérieur" de votre programme et comment les variables évoluent. - -Le site http://www.cprogramming.com/debugging/ vous donne des techniques de débuggage plus détaillées et explique `valgrind(1)`_ et `gdb(1)`_ plus en détails. - -Valgrind permet de détecter des erreurs liées à la gestion de la mémoire dans vos programmes. Pour utiliser valgrind, lancez la commande `valgrind(1)`_ avec votre exécutable comme argument: - - .. code-block:: console - - valgrind --leak-check=yes [my binary] - -Parmi les erreurs que valgrind est capable de détecter nous avons: - - * Mémoire non-désallouée: Lors d'un appel à `malloc(3)`_, vous obtenez un pointeur vers une zone de mémoire allouée. Si vous "perdez" la valeur de ce pointeur, vous n'avez plus le moyen de libérer cette zone de mémoire. Essayez `valgrind(1)`_ avec le petit programme :download:`src/nofree.c` - * Désallouer deux fois la même zone de mémoire: Si vous appelez deux fois `free(3)`_ sur la même zone de mémoire, `valgrind(1)`_ va détecter cette erreur. Essayez-le avec le petit programme :download:`src/twofree.c` - * Accès en dehors des limites d'une zone mémoire: Si vous allouez une zone de mémoire d'une certaine taille (par exemple un table de 10 chars) et que vous accèdez à une adresse qui excède cette zone (par exemple vous accèdez au 11ième élément) vous aurez probablement une ``Segmentation fault``. Valgrind permet de détecter ces erreurs et indique l'endroit dans votre code où vous faites cet accès. Essayez-le avec le petit programme :download:`src/outofbounds.c` - -On vous encourage à lancer `valgrind(1)`_ sur votre projet pour vérifier que vous n'avez pas introduit de memory-leaks sans le vouloir. `valgrind(1)`_ ne remplace pas une écriture attentive du code mais peut permettre de détecter rapidement certaines erreurs courantes. Vous trouverez plus de détails sur les liens suivants: - - * http://www.cprogramming.com/debugging/valgrind.html - * http://valgrind.org - -Les bases de ``valgrind`` -^^^^^^^^^^^^^^^^^^^^^^^^^ - -Commençons par le programme le plus simple possible que nous allons tester à l'aide de `valgrind(1)`_: - - .. code-block:: c - - #include <stdio.h> - #include <stdlib.h> - - int main(void) - { - printf("Hello, 1252 !\n"); - return EXIT_SUCCESS; - } - -Après compilation et l'exécutions avec `valgrind(1)`_ nous obtenons : - - - .. code-block:: console - - $ gcc -o hello hello.c - $ ./hello - Hello, 1252 ! - $ valgrind ./hello - ==13415== Memcheck, a memory error detector - ==13415== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. - ==13415== Using Valgrind-3.6.0 and LibVEX; rerun with -h for copyright info - ==13415== Command: ./hello - ==13415== - Hello, 1252 ! - ==13415== - ==13415== HEAP SUMMARY: - ==13415== in use at exit: 0 bytes in 0 blocks - ==13415== total heap usage: 0 allocs, 0 frees, 0 bytes allocated - ==13415== - ==13415== All heap blocks were freed -- no leaks are possible - ==13415== - ==13415== For counts of detected and suppressed errors, rerun with: -v - ==13415== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6) - -Nous pouvons lire dans ce rapport plusieurs informations importante comme le ``HEAP SUMMARY`` qui résume l'utilisation du tas. Dans notre cas particulier, on peut voir que rien n'a été alloué (en effet, il n'y a pas eu de malloc) et rien n'a été libéré. - -L' ``ERROR SUMMARY`` indique le nombre d'erreurs détectées. - -La phrase que nous voulons voir après chaque exécution de `valgrind(1)`_ est: - - .. code-block:: console - - All heap blocks were freed -- no leaks are possible - -Ce qui indique qu'aucun memory leak ne peut avoir lieu dans notre programme. - -Detecter les memory leaks -^^^^^^^^^^^^^^^^^^^^^^^^^ - -A présent nous allons montrer comment détecter des fuites de mémoire dans un programme à l'aide de `valgrind(1)`_. Testons le programme :download:`src/nofree.c`: - - .. code-block:: console - - $ gcc -o nofree nofree.c - $ valgrind ./nofree - ==13791== Memcheck, a memory error detector - ==13791== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. - ==13791== Using Valgrind-3.6.0 and LibVEX; rerun with -h for copyright info - ==13791== Command: ./nofree - ==13791== - ==13791== - ==13791== HEAP SUMMARY: - ==13791== in use at exit: 6 bytes in 1 blocks - ==13791== total heap usage: 1 allocs, 0 frees, 6 bytes allocated - ==13791== - ==13791== LEAK SUMMARY: - ==13791== definitely lost: 6 bytes in 1 blocks - ==13791== indirectly lost: 0 bytes in 0 blocks - ==13791== possibly lost: 0 bytes in 0 blocks - ==13791== still reachable: 0 bytes in 0 blocks - ==13791== suppressed: 0 bytes in 0 blocks - ==13791== Rerun with --leak-check=full to see details of leaked memory - ==13791== - ==13791== For counts of detected and suppressed errors, rerun with: -v - ==13791== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6) - -Nous remarquons directement que cette fois ci des leaks ont été trouvés par `valgrind(1)`_. Celui ci indique en effet la perte de 6 bytes de mémoire sur le tas qui ont été alloués par 1 `malloc(3)`_ et qui n'ont pas été libérés avant le ``return``. - -Maintenant nous savons que nous avons un memory leak, mais `valgrind(1)`_ peut faire plus que seulement les détecter, il peut aussi trouver où ont ils lieu. Nous remarquons dans le rapport qu'il conseil de relancer le test avec cette fois ci l'option ``--leak-check=full`` pour avoir plus de détails sur notre fuite. Nous avons dés lors de nouvelles informations dans ``HEAP SUMMARY`` : - - .. code-block:: console - - ==13818== 6 bytes in 1 blocks are definitely lost in loss record 1 of 1 - ==13818== at 0x4A05FDE: malloc (vg_replace_malloc.c:236) - ==13818== by 0x4004DC: main (nofree.c:5) - -La fuite a donc lieu à la ligne 5 de notre programme qui correspond à : - - .. code-block:: c - - char *ptrChars = (char *)malloc(6 * sizeof(char)); - -On sait maintenant quel est le `malloc(3)`_ responsable du leak, et il est facile de l'éviter en écrivant ``free(ptrChars);`` avant le ``return``. - -Double free -^^^^^^^^^^^ - -`valgrind(1)`_ ne se contente pas seulement de trouver des memory leaks, il est aussi capable de détecter des doubles free qui peuvent engendrer des corruptions de mémoire. -Pour montrer cette fonction de `valgrind(1)`_ nous utilisons le petit programme :download:`src/twofree.c`. - - .. code-block:: console - - $ valgrind ./twofree - ==13962== Memcheck, a memory error detector - ==13962== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. - ==13962== Using Valgrind-3.6.0 and LibVEX; rerun with -h for copyright info - ==13962== Command: ./twofree - ==13962== - ==13962== Invalid free() / delete / delete[] - ==13962== at 0x4A0595D: free (vg_replace_malloc.c:366) - ==13962== by 0x40053F: main (in twofree.c:8) - ==13962== Address 0x4c2d040 is 0 bytes inside a block of size 6 free'd - ==13962== at 0x4A0595D: free (vg_replace_malloc.c:366) - ==13962== by 0x400533: main (in twofree.c:8) - ==13962== - ==13962== - ==13962== HEAP SUMMARY: - ==13962== in use at exit: 0 bytes in 0 blocks - ==13962== total heap usage: 1 allocs, 2 frees, 6 bytes allocated - ==13962== - ==13962== All heap blocks were freed -- no leaks are possible - ==13962== - ==13962== For counts of detected and suppressed errors, rerun with: -v - ==13962== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6) - -Ici `valgrind(1)`_ nous indique qu'il a trouver une erreur et qu'il s'agit d'un ``Invalid free()`` à la ligne 8 de notre programme. Facilement trouvé et corrigé! - -Segmentation Fault -^^^^^^^^^^^^^^^^^^ - -Les segmentation faults sont des erreurs courantes lors de la programmation en C/C++. Elles ont lieu lors de l'accès à des zones de mémoire non-allouées. `valgrind(1)`_ permet de facilement trouver l'origine des segfaults et de les corriger. Démonstration avec :download:`src/outofbounds.c`: - - .. code-block:: console - - $ gcc -g -o outofbounds outofbounds.c - -Il est important de compiler avec le drapeau -g pour dire au compilateur de garder les informations de débuggage. - - .. code-block:: console - - $ ./outofbounds - Segmentation fault - $ gcc -g -o outofbounds outofbounds.c - $ ./outofbounds - $ valgrind ./outofbounds - ==14236== Memcheck, a memory error detector - ==14236== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al. - ==14236== Using Valgrind-3.6.0 and LibVEX; rerun with -h for copyright info - ==14236== Command: ./outofbounds - ==14236== - ==14236== Invalid write of size 1 - ==14236== at 0x400530: main (outofbounds.c:7) - ==14236== Address 0x4c2d04c is 6 bytes after a block of size 6 alloc'd - ==14236== at 0x4A05FDE: malloc (vg_replace_malloc.c:236) - ==14236== by 0x40051C: main (outofbounds.c:5) - ==14236== - ==14236== - ==14236== HEAP SUMMARY: - ==14236== in use at exit: 0 bytes in 0 blocks - ==14236== total heap usage: 1 allocs, 1 frees, 6 bytes allocated - ==14236== - ==14236== All heap blocks were freed -- no leaks are possible - ==14236== - ==14236== For counts of detected and suppressed errors, rerun with: -v - ==14236== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 6 from 6) - -`valgrind(1)`_ trouve bien une erreur, à la ligne 7 de notre petit programme. - -.. _helgrind-ref: - -Détecter les deadlocks avec ``valgrind`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -`valgrind(1)`_ contient des outils qui vont au-delà des simples tests de l'allocation de la mémoire. Notamment l'outil ``helgrind`` permet de détecter des deadlocks. Utilisez ``helgrind`` sur le petit programme :download:`/src/thread_crash.c` en faisant: - - .. code-block:: console - - $ valgrind --tool=helgrind [my binary] - - ==24314== Helgrind, a thread error detector - ==24314== Copyright (C) 2007-2010, and GNU GPL'd, by OpenWorks LLP et al. - ==24314== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright info - ==24314== Command: ./thread_crash - ==24314== - ==24314== Thread #2 was created - ==24314== at 0x512E85E: clone (clone.S:77) - ==24314== by 0x4E36E7F: do_clone.constprop.3 (createthread.c:75) - ==24314== by 0x4E38604: pthread_create@@GLIBC_2.2.5 (createthread.c:256) - ==24314== by 0x4C29B23: pthread_create_WRK (hg_intercepts.c:257) - ==24314== by 0x4C29CA7: pthread_create@* (hg_intercepts.c:288) - ==24314== by 0x400715: main (in /home/christoph/workspace/SINF1252/SINF1252/2012/S6/src/thread_crash) - ==24314== - ==24314== Thread #2: Exiting thread still holds 1 lock - ==24314== at 0x4E37FB6: start_thread (pthread_create.c:430) - ==24314== by 0x512E89C: clone (clone.S:112) - -Plus d'informations sur: - * http://valgrind.org/docs/manual/hg-manual.html diff --git a/Theorie/.gitkeep b/Theorie/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/Theorie/Assembleur/fig/figures-memoire-001-c.png b/Theorie/Assembleur/fig/figures-memoire-001-c.png deleted file mode 100644 index 1a2e2df92415468ae99eaba43807df7d884d3861..0000000000000000000000000000000000000000 Binary files a/Theorie/Assembleur/fig/figures-memoire-001-c.png and /dev/null differ diff --git a/Theorie/Assembleur/fig/figures-memoire-002-c.png b/Theorie/Assembleur/fig/figures-memoire-002-c.png deleted file mode 100644 index 473e57aa9dc829e41d0d875c80dff27d4a8e8cb4..0000000000000000000000000000000000000000 Binary files a/Theorie/Assembleur/fig/figures-memoire-002-c.png and /dev/null differ diff --git a/Theorie/Assembleur/fig/figures-memoire-003-c.png b/Theorie/Assembleur/fig/figures-memoire-003-c.png deleted file mode 100644 index 8f2fd4dcbb953aeaec2a29df42523981009b90b9..0000000000000000000000000000000000000000 Binary files a/Theorie/Assembleur/fig/figures-memoire-003-c.png and /dev/null differ diff --git a/Theorie/Assembleur/fig/figures-memoire-004-c.png b/Theorie/Assembleur/fig/figures-memoire-004-c.png deleted file mode 100644 index e5a7c4a668b49921ad9ea32b3f5b92d63d478a5d..0000000000000000000000000000000000000000 Binary files a/Theorie/Assembleur/fig/figures-memoire-004-c.png and /dev/null differ diff --git a/Theorie/Assembleur/fig/figures-memoire-005-c.png b/Theorie/Assembleur/fig/figures-memoire-005-c.png deleted file mode 100644 index bdcaa2c5fd0e8ee78cbcabceca572979e9db6417..0000000000000000000000000000000000000000 Binary files a/Theorie/Assembleur/fig/figures-memoire-005-c.png and /dev/null differ diff --git a/Theorie/Assembleur/fig/figures-memoire-006-c.png b/Theorie/Assembleur/fig/figures-memoire-006-c.png deleted file mode 100644 index 9c8f66ce9ff71af85e01130ae2918beb2127292b..0000000000000000000000000000000000000000 Binary files a/Theorie/Assembleur/fig/figures-memoire-006-c.png and /dev/null differ diff --git a/Theorie/Assembleur/fig/figures-memoire-007-c.png b/Theorie/Assembleur/fig/figures-memoire-007-c.png deleted file mode 100644 index f26df4feb8bef7f4134d3e69fe511a345c110cb9..0000000000000000000000000000000000000000 Binary files a/Theorie/Assembleur/fig/figures-memoire-007-c.png and /dev/null differ diff --git a/Theorie/Assembleur/memory.rst b/Theorie/Assembleur/memory.rst deleted file mode 100644 index 455a53c526bbc21c1efe230037e50cc6a8349d59..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/memory.rst +++ /dev/null @@ -1,753 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. _ordinateurs: - - -Organisation des ordinateurs -============================ - -Pour bien comprendre la façon dont les programmes s'exécutent sur un ordinateur, il est nécessaire de connaitre quelques principes de base sur l'architecture des ordinateurs et de leur organisation. - -Un des premiers principes fondateurs est le modèle d'architecture de :term:`von Neumann`. Ce modèle d'architecture a été introduit durant le développement des premiers ordinateurs pendant la seconde guerre mondiale mais reste tout à fait valide aujourd'hui [Krakowiak2011]_. La partie la plus intéressante de ce modèle concerne les fonctions de calcul d'un ordinateur. Il postule qu'un ordinateur est organisé autour de deux types de dispositifs : - - - L'unité centrale ou :term:`processeur`. Cette unité centrale peut être décomposée en deux parties : l'unité de commande et l'unité arithmétique et logique. L'unité arithmétique et logique regroupe les circuits électroniques qui permettent d'effectuer les opérations arithmétiques (addition, soustraction, division, ...) et logiques. C'est cette unité qui réalise les calculs proprement dits. L'unité de commande permet quant à elle de charger, décoder et exécuter les instructions du programme qui sont stockées en mémoire. - - La :term:`mémoire`. Celle-ci joue un double rôle. Elle stocke à la fois les données qui sont traitées par le programme mais aussi les instructions qui composent celui-ci. Cette utilisation de la mémoire pour stocker les données et une représentation binaire du programme à exécuter sont un des principes fondamentaux du fonctionnement des ordinateurs actuels. - -La figure ci-dessous illustre les principaux éléments du modèle de von Neumann. - - -.. figure:: /Assembleur/fig/figures-memoire-001-c.png - :align: center - - Modèle de von Neumann - - -Les technologies utilisées pour construire les processeurs et la mémoire ont fortement évolué depuis les premiers ordinateurs, mais les principes fondamentaux restent applicables. En première approximation, on peut considérer la mémoire comme étant un dispositif qui permet de stocker des données binaires. La mémoire est découpée en blocs d'un octet. Chacun de ces blocs est identifié par une adresse, qui est elle aussi représentée sous la forme d'un nombre binaire. Une mémoire qui permet de stocker :math:`2^k` bytes de données utilisera au minimum `k` bits pour représenter l'adresse d'une zone mémoire. Ainsi, une mémoire pouvant stocker 64 millions de bytes doit utiliser au moins 26 bits d'adresse. En pratique, les processeurs des ordinateurs de bureau utilisent 32 ou 64 bits pour représenter les adresses en mémoire. D'anciens processeurs utilisaient 16 ou 20 bits d'adresse. Le nombre de bits utilisés pour représenter une adresse en mémoire limite la capacité totale de mémoire adressable par un processeur. Ainsi, un processeur qui utilise des adresses sur 32 bits n'est pas capable physiquement d'adresser plus de 4 GBytes de mémoire. - -En pratique, l'organisation physique d'un ordinateur actuel est plus complexe que le modèle de von Neumann. Schématiquement, on peut considérer l'organisation présentée dans la figure ci-dessous. Le processeur est directement connecté à la mémoire via un :term:`bus` de communication rapide. Ce bus permet des échanges de données et d'instructions efficaces entre la mémoire et le processeur. Outre le processeur et la mémoire, un troisième dispositif, souvent baptisé -adaptateur de bus est connecté au bus processeur-mémoire. Cet adaptateur permet au processeur d'accéder aux dispositifs de stockage ou aux dispositifs d'entrées-sorties tels que le clavier, la souris ou les cartes réseau. En pratique, cela se réalise en connectant les différents dispositifs à un autre bus de communication (PCI, SCSI, ...) et en utilisant un adaptateur de bus qui est capable de traduire les commandes venant du processeur. - -.. figure:: /Assembleur/fig/figures-memoire-002-c.png - :align: center - - Architecture d'un ordinateur actuel - -Différentes technologies ont été mises en oeuvre pour construire les mémoires utilisées dans les ordinateurs. Aujourd'hui, les technologies les plus courantes sont les mémoires de type :term:`SRAM` et les mémoires de type :term:`DRAM`. Dans une :term:`SRAM`, l'information est stockée sous la forme d'un courant électrique qui passe ou ne passe pas à un endroit donné. L'avantage de cette technologie est que le temps d'accès à une donnée stockée en :term:`SRAM` est assez faible. Malheureusement, leur inconvénient majeur est leur grande consommation électrique qui empêche de développer des mémoires de grande capacité. Aujourd'hui, les :term:`SRAM` les plus grandes ont une capacité de seulement 12 MBytes [HennessyPatterson]_. - -Les :term:`DRAM` sont totalement différentes des :term:`SRAM` d'un point de vue électronique. Dans une mémoire de type :term:`DRAM`, c'est la présence ou l'absence d'une charge (de quelques électrons à quelques dizaines d'électrons) dans un condensateur qui représente la valeur ``0`` ou ``1``. Il est possible de construire des :term:`DRAM` de très grande taille, jusqu'à 1 GByte par chip [HennessyPatterson]_. C'est la raison pour laquelle on retrouve très largement des mémoires de type :term:`DRAM` dans les ordinateurs. Malheureusement, leurs performances sont nettement moins bonnes que les mémoires de type :term:`SRAM`. En pratique, une mémoire :term:`DRAM` actuelle peut être vue comme étant équivalente à une grille [Drepper2007]_. Les adresses peuvent être vues comme étant composées d'un numéro de colonne et d'un numéro de ligne. Pour lire ou écrire une donnée en mémoire :term:`DRAM`, le processeur doit d'abord indiquer la ligne qu'il souhaite lire et ensuite la colonne. Ces deux opérations sont successives. Lorsque la mémoire a reçu la ligne et la colonne demandées, elle peut commencer le transfert de la donnée. En pratique, les mémoires :term:`DRAM` sont optimisées pour fournir un débit de transfert élevé, mais elles ont une latence élevée. Cela implique que dans une mémoire :term:`DRAM`, il est plus rapide de lire ou d'écrire un bloc de 128 bits successifs que quatre blocs de 32 bits à des endroits différents en mémoire. A titre d'exemple, le tableau ci-dessous, extrait de [HP]_ fournit le taux de transfert maximum de différentes technologies de :term:`DRAM`. - - ============ ================ ================ - Technologie Fréquence [MHz] Débit [MB/sec] - ============ ================ ================ - SDRAM 200 1064 - RDRAM 400 1600 - DDR-1 266 2656 - DDR-2 333 5328 - DDR-2 400 6400 - DDR-3 400 6400 - DDR-3 533 8500 - DDR-3 667 10600 - ============ ================ ================ - - -Le processeur interagit en permanence avec la mémoire, que ce soit pour charger des données à traiter ou pour charger les instructions à exécuter. Tant les données que les instructions sont représentées sous la forme de nombres en notation binaire. Certains processeurs utilisent des instructions de taille fixe. Par exemple, chaque instruction est encodée sous la forme d'un mot de 32 bits. D'autres processeurs, comme ceux qui implémentent l'architecture [IA32]_, utilisent des instructions qui sont encodées sous la forme d'un nombre variable de bytes. Ces choix d'encodage des instructions influencent la façon dont les processeurs sont implémentés d'un point de vue microélectronique, mais ont assez peu d'impact sur le développeur de programmes. L'élément qu'il est important de bien comprendre est que le processeur doit en permanence charger des données et des instructions depuis la mémoire lors de l'exécution d'un programme. - -Outre des unités de calcul, un processeur contient plusieurs registres. Un :term:`registre` est une zone de mémoire très rapide se trouvant sur le processeur. Sur les processeurs actuels, cette zone de mémoire permet de stocker un mot de 32 bits ou un long mot de 64 bits. Les premiers processeurs disposaient d'un registre unique baptisé l':term:`accumulateur`. Les processeurs actuels en contiennent généralement une ou quelques dizaines. Chaque registre est identifié par un nom ou un numéro et les instructions du processeur permettent d'accéder directement aux données se trouvant dans un registre particulier. Les registres sont les mémoires les plus rapides qui sont disponibles sur un ordinateur. Malheureusement, ils sont en nombre très limité et il est impossible de faire fonctionner un programme non trivial en utilisant uniquement des registres. - -Du point de vue des performances, il serait préférable de pouvoir construire un ordinateur équipé uniquement de :term:`SRAM`. Malheureusement, au niveau de la capacité et du prix, c'est impossible sauf pour de rares applications bien spécifiques qui nécessitent de hautes performances et se contentent d'une capacité limitée. Les ordinateurs actuels utilisent en même temps de la mémoire :term:`SRAM` et de la mémoire :term:`DRAM`. Avec les registres, les :term:`SRAM` et les :term:`DRAM` composent les trois premiers niveaux de la :term:`hiérarchie de mémoire`. - -Le tableau ci-dessous, extrait de [BryantOHallaron2011]_ , compare les temps d'accès entre les mémoires :term:`SRAM` et les mémoires :term:`DRAM` à différentes périodes. - -====== ========== ========== -Année Accès SRAM Accès DRAM -====== ========== ========== -1980 300 ns 375 ns -1985 150 ns 200 ns -1990 35 ns 100 ns -1995 15 ns 70 ns -2000 3 ns 60 ns -2005 2 ns 50 ns -2010 1.5 ns 40 ns -====== ========== ========== - -Cette évolution des temps d'accès doit être mise en parallèle avec l'évolution des performances des processeurs. En 1980, le processeur Intel 8080 fonctionnait avec une horloge de 1 MHz et accédait à la mémoire toutes les 1000 ns. A cette époque, la mémoire était nettement plus rapide que le processeur. En 1990, par contre, le processeur Intel 80386 accédait à la mémoire en moyenne toutes les 50 ns. Couplé à une mémoire uniquement de type DRAM, il était ralenti par cette mémoire. En 2000, le Pentium-III avait un cycle de 1.6 ns, plus rapide que les meilleures mémoires disponibles à l'époque. Il en va de même aujourd'hui où les temps de cycle sont inférieurs au temps d'accès des mémoires. Même s'il existe des solutions techniques pour mitiger ce problème, la différence de performance croissante entre la mémoire et le processeur est un des facteurs qui limitent les améliorations des performances de nombreux programmes. - -Une première solution pour combiner la :term:`SRAM` et la :term:`DRAM` serait de réserver par exemple les adresses basses à la :term:`SRAM` qui est plus performante et d'utiliser la :term:`DRAM` pour les adresses hautes. Avec cette solution, le programme stocké dans la :term:`SRAM` pourrait s'exécuter plus rapidement que le programme stocké en :term:`DRAM`. Afin de permettre à tous les programmes de pouvoir utiliser la :term:`SRAM`, on pourrait imaginer que le système d'exploitation fournisse des fonctions qui permettent aux applications de demander la taille de la mémoire :term:`SRAM` disponible et de déplacer des parties d'un programme et des données en :term:`SRAM`. Ce genre de solution obligerait chaque application à pouvoir déterminer quelles sont les instructions à exécuter et quelles données doivent être placées en mémoire :term:`SRAM` pour obtenir les meilleures performances. Même si en théorie, ce genre de solution est envisageable, en pratique, elle a très peu de chances de pouvoir fonctionner. - -La deuxième solution est d'utiliser le principe de la :term:`mémoire cache`. Une :term:`mémoire cache` est une mémoire de faible capacité mais rapide. La mémoire cache peut stocker des données provenant de mémoires de plus grande capacité mais plus lentes. Cette mémoire cache sert d'interface entre le processeur et la mémoire principale. Toutes les demandes d'accès à la mémoire principale passent par la mémoire cache comme illustré dans la figure ci-dessous. - -.. figure:: /Assembleur/fig/figures-memoire-005-c.png - :align: center - - Le processeur, la mémoire cache et la mémoire principale - -On utilise des mémoires caches dans de nombreux systèmes informatiques de façon à améliorer leurs performances. Ces mémoires caches utilisent en fait le :term:`principe de localité`. En pratique, deux types de localité doivent être considérés. Tout d'abord, il y a la :term:`localité temporelle`. Si un processeur a accédé à la mémoire à l'adresse `A` à l'instant `t`, il est fort probable qu'il accédera encore à cette adresse dans les instants qui suivent. La localité temporelle apparaît notamment lors de l'exécution de longues boucles qui exécutent à de nombreuses reprises les mêmes instructions. Le second type de localité est la :term:`localité spatiale`. Celle-ci implique que si un programme a accédé à l'adresse `A` à l'instant `t`, il est fort probable qu'il accédera aux adresses proches de `A` comme `A+4`, `A-4` dans les instants qui suivent. Cette localité apparaît par exemple lorsqu'un programme traite un vecteur stocké en mémoire. - -Les mémoires caches exploitent ces principes de localité en stockant de façon transparente les instructions et les données les plus récemment utilisées. D'un point de vue physique, on peut voir le processeur comme étant connecté à la (ou parfois les) mémoire cache qui est elle-même connectée à la mémoire :term:`RAM`. Les opérations de lecture en mémoire se déroulent généralement comme suit. Chaque fois que le processeur a besoin de lire une donnée se trouvant à une adresse, il fournit l'adresse demandée à la mémoire cache. Si la donnée correspondant à cette adresse est présente en mémoire cache, celle-ci répond directement au processeur. Sinon, la mémoire cache interroge la mémoire :term:`RAM`, se met à jour et ensuite fournit la donnée demandée au processeur. Ce mode de fonctionnement permet à la mémoire cache de se mettre à jour au fur et à mesure des demandes faites par le processeur afin de profiter de la localité temporelle. Pour profiter de la localité spatiale, la plupart des caches se mettent à jour en chargeant directement une :term:`ligne de cache` qui peut compter jusqu'à quelques dizaines d'adresses consécutives en mémoire. Ce chargement d'une ligne complète de cache permet également de profiter des mémoires :term:`DRAM` récentes qui sont souvent optimisées pour fournir des débits de transfert élevés pour de longs blocs consécutifs en mémoire. -La figure ci-dessous illustre graphiquement la hiérarchie de mémoires dans un ordinateur. - -.. figure:: /Assembleur/fig/figures-memoire-003-c.png - :align: center - - La hiérarchie de mémoires - - -Pour les opérations d'écriture, la situation est plus compliquée. Si le processeur écrit l'information `x` à l'adresse `A` en mémoire, il faudrait idéalement que cette valeur soit écrite simultanément en mémoire cache et en mémoire :term:`RAM` de façon à s'assurer que la mémoire :term:`RAM` contienne toujours des données à jour. La stratégie d'écriture la plus simple est baptisée :term:`write through`. Avec cette stratégie, toute demande d'écriture venant du processeur donne lieu à une écriture en mémoire cache et une écriture en mémoire :term:`RAM`. Cette stratégie garantit qu'à tout moment la mémoire cache et la mémoire :term:`RAM` contiennent la même information. Malheureusement, d'un point de vue des performances, cette technique rabaisse les performances de la mémoire cache à celles de la mémoire :term:`RAM`. Vu la différence de performance entre les deux types de mémoires, cette stratégie n'est plus acceptable aujourd'hui. L'alternative est d'utiliser la technique du :term:`write back`. Avec cette technique, toute écriture est faite en :term:`mémoire cache` directement. Cela permet d'obtenir de très bonnes performances pour les écritures. Une donnée modifiée n'est réécrite en mémoire :term:`RAM` que lorsqu'elle doit être retirée de la mémoire cache. Cette écriture est faite automatiquement par la mémoire cache. Pour la plupart des programmes, la gestion des opérations d'écriture est transparente. Il faut cependant être attentif à la technique d'écriture utilisée lorsque plusieurs dispositifs peuvent accéder directement à la mémoire :term:`RAM` sans passer par le processeur. C'est le cas par exemple pour certaines cartes réseaux ou certains contrôleurs de disque dur. Pour des raisons de performances, ces dispositifs peuvent copier des données directement de la mémoire :term:`RAM` vers le réseau ou un disque dur. Si une écriture de type :term:`write-back` est utilisée, le système d'exploitation doit veiller à ce que les données écrites par le processeur en cache aient bien été écrites également en mémoire :term:`RAM` avant d'autoriser la carte réseau ou le contrôleur de disque à effectuer un transfert. - -.. C'est particulièrement important lorsque des dispositifs tels qu'une carte réseau ou un controleur de disque dur peuvent aller lire des données en mémoire. Ces dispositifs doivent trouver en mémoire :term:`RAM` la dernière donnée écrite par le processeur - -.. _ia32_section: - -Etude de cas : Architecture IA32 -================================ - -Pour comprendre le fonctionnement d'un microprocesseur, la solution la plus efficace est de considérer une architecture en particulier et de voir comment fonctionnent les processeurs qui l'implémentent. Dans cette section, nous analysons brièvement le fonctionnement des processeurs [#fintel]_ de la famille [IA32]_. - -Cette architecture recouvre un grand nombre de variantes qui ont leur spécificités propre. Une descriptions détaillée de cette architecture est disponible dans [IA32]_. Nous nous limiterons à un très petit sous-ensemble de cette architecture dans le cadre de ce cours. Une analyse complète de l'architecture [IA32]_ occupe plusieurs centaines de pages dans des livres de référence [BryantOHallaron2011]_ [Hyde2010]_. - -L'architecture [IA32]_ est supportée par différents types de processeurs. Certains utilisent des registres et des bus de données de 32 bits. D'autres, plus récents utilisent des registres de 64 bits. Il y a des différences importantes entre ces deux architectures. Comme les processeurs récents supportent à la fois les modes 32 bits et 64 bits, nous nous limiterons à l'architecture 32 bits. - -Un des éléments importants d'un processeur tel que ceux de l'architecture [IA32]_ sont ses registres. Un processeur [IA32]_ dispose de huit registres génériques. Ceux-ci ont été baptisés ``EAX``, ``EBX``, ``ECX``, ``EDX``, ``EBP``, ``ESI``, ``EDI`` et ``ESP``. Ces registres peuvent stocker des données sous forme binaire. Dans l'architecture [IA32]_, ils ont une taille de 32 bits. Cela implique que chaque registre peut contenir un nombre ou une adresse puisque les entiers (``int`` en C) et les adresses (pointeurs ``*`` en C sur [IA32]_) sont tous les deux encodés sur 32 bits dans l'architecture [IA32]_. Cette capacité à stocker des données ou des adresses à l'intérieur d'un même registre est un des points clés de la flexibilité des microprocesseurs. - -Deux de ces registres, ``EBP`` et ``ESP`` sont utilisés dans la gestion de la pile comme nous le verrons plus tard. Les autres registres peuvent être utilisés directement par le programmeur. En outre, tout processeur contient un registre spécial qui stocke à tout moment l'adresse de l'instruction courante en mémoire. Ce registre est souvent dénommé le :term:`compteur de programme` ou :term:`program counter` (:term:`PC`) en anglais. Dans l'architecture [IA32]_, c'est le registre ``EIP`` qui stocke l':term:`Instruction Pointer` qui joue ce rôle. Ce registre ne peut pas être utilisé pour effectuer des opérations arithmétiques. Il peut cependant être modifié par les instructions de saut comme nous le verrons plus tard et joue un rôle essentiel dans l'implémentation des instructions de contrôle. - -Outre ces registres génériques, les processeurs de la famille [IA32]_ contiennent aussi des registres spécialisés pour manipuler les nombres en virgule flottante (``float`` et ``double``). Nous ne les analyserons pas dans le cadre de ce cours. Par contre, les processeurs [IA32]_ contiennent également des drapeaux regroupés dans le registre ``eflags``. Ceux-ci sont utilisés pour implémenter différents tests et comparaisons. - - -Les processeurs qui implémentent les spécifications [IA32]_ supportent les types de données repris dans le tableau ci-dessous. - - =============== ================ ===================== - Type Taille (bytes) Suffixe assembleur - =============== ================ ===================== - ``char`` 1 b - ``short`` 2 w - ``int`` 4 l - ``long int`` 4 l - ``void *`` 4 l - =============== ================ ===================== - -Dans les sections qui suivent, nous analysons quelques instructions de l'architecture [IA32]_ qui permettent de manipuler des nombres entiers en commençant par les instructions de transfert entre la mémoire et les registres. - - -Les instructions ``mov`` ------------------------- - -Les instructions de la famille ``mov`` [#fmov]_ permettent de déplacer des données entre registres ou depuis la mémoire vers un registre ou enfin d'un registre vers une zone mémoire. Ces instructions sont essentielles car elles permettent au processeur de récupérer les données qui sont stockées en mémoire mais aussi de sauvegarder en mémoire le résultat d'un calcul effectué par le processeur. Une instruction ``mov`` contient toujours deux arguments. Le premier spécifie la donnée à déplacer ou son adresse et la seconde l'endroit où il faut sauvegarder cette donnée ou la valeur stockée à cette adresse. - -.. code-block:: nasm - - mov src, dest ; déplacement de src vers dest - -Il existe une instruction de la famille ``mov`` qui correspond à chaque type de donnée pouvant être déplacé. L'instruction ``movb`` est utilisée pour déplacer un byte, ``movw`` pour déplacer un mot de 16 bits et ``movl`` lorsqu'il faut déplacer un mot de 32 bits. - -En pratique, il y a plusieurs façons de spécifier chaque argument d'une instruction ``mov``. Certains auteurs utilisent le terme :term:`mode d'adressage` pour représenter ces différents types d'arguments même si il ne s'agit pas toujours d'adresses. Le premier mode est le mode `registre`. La source et la destination d'une opération ``mov`` peuvent être un nom de registre. Ceux-ci sont en général préfixés avec le caractère ``%``. Ainsi, ``%eax`` correspond au registre ``EAX``. La première instruction ci-dessous déplace le mot de 32 bits stocké dans le registre ``%eax`` vers le registre ``%ebx``. La seconde instruction elle n'a aucun effet puisqu'elle déplace le contenu du registre ``%ecx`` vers ce même registre. - - -.. code-block:: nasm - - movl %eax, %ebx ; déplacement de %eax vers %ebx - movl %ecx, %ecx ; aucun effet - -Le deuxième mode d'adressage est le mode `immédiat`. Celui-ci ne peut être utilisé que pour l'argument `source`. Il permet de placer une constante dans un registre, par exemple pour initialiser sa valeur comme dans les exemples ci-dessous. Il se reconnaît à l'utilisation du symbole ``$`` comme préfixe de la constante. - -.. code-block:: nasm - - movl $0, %eax ; initialisation de %eax à 0 - movl $1252, %ecx ; initialisation de %ecx à 1252 - -Le troisième mode d'adressage est le mode `absolu`. Dans ce mode, l'un des arguments de l'instruction ``mov`` est une adresse en mémoire. Si la source est une adresse, alors l'instruction ``mov`` transfère le mot de 32 bits stocké à l'adresse spécifiée comme source vers le registre spécifié comme destination. Si la destination est une adresse, alors l'instruction ``mov`` sauvegarde la donnée source à cette adresse en mémoire. Pour illustrer cette utilisation de l'instruction ``mov``, considérons la mémoire illustrée ci-dessous. - - ========= ======== - Adresse Valeur - ========= ======== - 0x10 0x04 - 0x0C 0x10 - 0x08 0xFF - 0x04 0x00 - 0x00 0x04 - ========= ======== - -Les instructions ci-dessous sont un exemple de déplacement de données entre la mémoire et un registre et d'un registre vers la mémoire. - -.. code-block:: nasm - - movl 0x04, %eax ; place la valeur 0x00 (qui se trouve à l'adresse 0x04) dans %eax - movl $1252, %ecx ; initialisation de %ecx à 1252 - movl %ecx, 0x08 ; remplace 0xFF par le contenu de %ecx (1252) à l'adresse 0x08 - - -Le quatrième mode d'adressage est le mode `indirect`. Plutôt que de spécifier directement une adresse, avec le mode indirect, on spécifie un registre dont la valeur est une adresse en mémoire. Ce mode indirect est équivalent à l'utilisation des pointeurs en langage C. Il se reconnait à l'utilisation de parenthèses autour du nom du registre source ou destination. L'exemple ci-dessous illustre l'utilisation de l'adressage indirect en considérant la mémoire présentée plus haut. - -.. code-block:: nasm - - movl $0x08, %eax ; place la valeur 0x08 dans %eax - movl (%eax), %ecx ; place la valeur se trouvant à l'adresse qui est - ; dans %eax dans le registre %ecx %ecx=0xFF - movl 0x10, %eax ; place la valeur se trouvant à l'adresse 0x10 dans %eax - movl %ecx, (%eax) ; place le contenu de %ecx, c'est-à -dire 0xFF à l'adresse qui est contenue dans %eax (0x10) - -Le cinquième mode d'adressage est le mode avec une `base` et un `déplacement`. Ce mode peut être vu comme une extension du mode `indirect`. Il permet de lire en mémoire à une adresse qui est obtenue en additionnant un entier, positif ou négatif, à une adresse stockée dans un registre. Ce mode d'adressage joue un rôle important dans le fonctionnement de la pile comme nous le verrons d'ici peu. - -.. code-block:: nasm - - movl $0x08, %eax ; place la valeur 0x08 dans %eax - movl 0(%eax), %ecx ; place la valeur (0xFF) se trouvant à l'adresse - ; 0x08= (0x08+0) dans le registre %ecx - movl 4(%eax), %ecx ; place la valeur (0x10) se trouvant à l'adresse - ; 0x0C (0x08+4) dans le registre %ecx - movl -8(%eax), %ecx ; place la valeur (0x04) se trouvant à l'adresse - ; 0x00 (0x08-8) dans le registre %ecx - -L'architecture [IA32]_ supporte encore d'autres modes d'adressage. Ceux sont décrits dans [IA32]_ ou [BryantOHallaron2011]_. Une autre instruction permettant de déplacer de l'information est l'instruction ``leal`` (load effective address). Cette instruction est parfois utilisée par les compilateurs. Elle place dans le registre destination l'adresse de son argument source plutôt que sa valeur. Ainsi ``leal 4(%esp) %edx`` placera dans le registre ``%edx`` l'adresse de son argument source, c'est-à -dire l'adresse contenue dans ``%esp+4``. - - -Instructions arithmétiques et logiques --------------------------------------- - -La deuxième famille d'instructions importante sur un processeur sont les instructions qui permettent d'effectuer les opérations arithmétiques et logiques. Voici quelques exemples d'instructions arithmétiques et logiques supportées par l'architecture [IA32]_. - -Les instructions les plus simples sont celles qui prennent un seul argument. Il s'agit de : - - - ``inc`` qui incrémente d'une unité la valeur stockée dans le registre/l'adresse fournie en argument et sauvegarde le résultat de l'incrémentation au même endroit. Cette instruction peut être utilisée pour implémenter des compteurs de boucles. - - ``dec`` est équivalente à ``inc`` mais décrémente son argument. - - ``not`` qui applique l'opération logique ``NOT`` à son argument et stocke le résultat à cet endroit - -Il existe une variante de chacune de ces instructions pour chaque type de données à manipuler. Cette variante se reconnait grâce au dernier caractère de l'instruction (``b`` pour byte, ``w`` pour un mot de 16 bits et ``l`` pour un mot de 32 bits). Nous nous limiterons aux instructions qui manipulent des mots de 32 bits. - -.. code-block:: nasm - - movl $0x12345678, %ecx ; initialisation - notl %ecx ; calcul de NOT - movl $0, %eax ; %eax=0 - incl %eax ; %eax++ - -L'architecture [IA32]_ supporte également des instructions arithmétiques et logiques prenant chacune deux arguments. - - - ``add`` permet d'additionner deux nombres entiers. ``add`` prend comme arguments une source et une destination et place dans la destination la somme de ses deux arguments. - - ``sub`` permet de soustraire le premier argument du second et stocke le résultat dans le second - - ``mul`` permet de multiplier des nombres entiers non-signés (``imul`` est le pendant de ``mul`` pour la multiplication de nombres signés) - - ``div`` permet la division de nombres entiers non-signés. - - ``shl`` (resp. ``shr``) permet de réaliser un décalage logique vers la gauche (resp. droite) - - ``xor`` calcule un ou exclusif entre ses deux arguments et sauvegarde le résultat dans le second - - ``and`` calcule la conjonction logique entre ses deux arguments et sauvegarde le résultat dans le second - - -Pour illustrer le fonctionnement de ces instructions, considérons une mémoire hypothétique contenant les données suivantes. Supposons que la variable entière ``a`` est stockée à l'adresse ``0x04``, ``b`` à l'adresse ``0x08`` et ``c`` à l'adresse ``0x0C``. - - ========== ======== ======== - Adresse Variable Valeur - ========== ======== ======== - 0x0C c 0x00 - 0x08 b 0xFF - 0x04 a 0x02 - 0x00 - 0x01 - ========== ======== ======== - -Les trois premières instructions ci-dessous sont équivalentes à l'expression C ``a=a+1;``. Pour implémenter une telle opération en C, il faut d'abord charger la valeur de la variable dans un registre. Ensuite le processeur effectue l'opération arithmétique. Enfin le résultat est sauvegardé en mémoire. Après ces trois instructions, la valeur ``0x03`` est stockée à l'adresse ``0x04`` qui correspond à la variable ``a``. Les trois dernières instructions calculent ``a=b-c;``. On remarquera que le programmeur a choisi de d'abord charger la valeur de la variable ``b`` dans le registre ``%eax``. Ensuite il utilise l'instruction ``subl`` en mode d'adressage immédiat pour placer dans ``%eax`` le résultat de la soustraction entre ``%eax`` et la donnée se trouvant à l'adresse ``0x0C``. Enfin, le contenu de ``%eax`` est sauvé à l'adresse correspondant à la variable ``a``. - -.. code-block:: nasm - - movl 0x04, %eax ; %eax=a - addl $1, %eax ; %eax++ - movl %eax, 0x04 ; a=%eax - movl 0x08, %eax ; %eax=b - subl 0x0c, %eax ; %eax=b-c - movl %eax, 0x04 ; a=%eax - -L'exemple ci-dessous présente la traduction directe [#fllvm]_ d'un fragment de programme C utilisant des variables globales en langage assembleur. - -.. code-block:: c - - int j,k,g,l; - // ... - l=g^j; - j=j|k; - g=l<<6; - -Dans le code assembleur, les noms de variables tels que ``g`` ou ``j`` correspondent à l'adresse mémoire à laquelle la variable est stockée. - -.. code-block:: nasm - - movl g, %eax ; %eax=g - xorl j, %eax ; %eax=g^j - movl %eax, l ; l=%eax - movl j, %eax ; %eax=j - orl k, %eax ; %eax=j|k - movl %eax, j ; j=%eax - movl l, %eax ; %eax=l - shll $6, %eax ; %eax=%eax << 6 - movl %eax, g ; g=%eax - -Les opérations arithmétiques telles que la multiplication ou la division sont plus complexes que les opérations qui ont été présentées ci-dessus. En toute généralité, la multiplication entre deux nombres de 32 bits peut donner un résultat sur 64 bits qui ne pourra donc pas être stocké entièrement dans un registre. De la même manière, une division entière retourne un quotient et un reste qui sont tous les deux sur 32 bits. L'utilisation des instructions de division et de multiplication nécessite de prendre ces problèmes en compte. Nous ne les aborderons pas dans ce cours. Des détails complémentaires sont disponibles dans [IA32]_ et [BryantOHallaron2011]_ notamment. - - -Les instructions de comparaison -------------------------------- - -Outre les opérations arithmétiques, un processeur doit être capable de réaliser des comparaisons. Ces comparaisons sont nécessaires pour implémenter des tests tels que ``if (condition) { ... } else { ... }``. Sur les processeurs [IA32]_, les comparaisons utilisent des drapeaux qui sont mis à jour par le processeur après l'exécution de certaines instructions. Ceux-ci sont regroupés dans le registre ``eflags``. Les principaux drapeaux sont : - - - `ZF` (Zero Flag) : ce drapeau indique si le résultat de la dernière opération était zéro - - `SF` (Sign Flag) : indique si le résultat de la dernière instruction était négatif - - `CF` (Carry Flag) : indique si le résultat de la dernière instruction arithmétique non signée nécessitait plus de 32 bits pour être stocké - - `OF` (Overflow Flag) : indique si le résultat de la dernière instruction arithmétique signée a provoqué un dépassement de capacité - -Nous utiliserons principalement les drapeaux `ZF` et `SF` dans ce chapitre. Ces drapeaux peuvent être fixés par les instructions arithmétiques standard, mais aussi par des instructions dédiées comme ``cmp`` et ``test``. L'instruction ``cmp`` effectue l'équivalent d'une soustraction et met à jour les drapeaux `CF` et `SF` mais sans sauvegarder son résultat dans un registre. L'instruction ``test`` effectue elle une conjonction logique sans sauvegarder son résultat mais en mettant à jour les drapeaux. - -Ces instructions de comparaison peuvent être utilisées avec les instructions ``set`` qui permettent de fixer la valeur d'un registre en fonction des valeurs de certains drapeaux du registre ``eflags``. Chaque instruction ``set`` prend comme argument un registre. Pour des raisons historiques, ces instructions modifient uniquement les bits de poids faible du registre indiqué et non le registre complet. C'est un détail qui est lié à l'histoire de l'architecture [IA32]_. - - - ``sete`` met le registre argument à la valeur du drapeau `ZF`. Permet d'implémenter une égalité. - - ``sets`` met le registre argument à la valeur du drapeau `SF` - - ``setg`` place dans le registre argument la valeur ``~SF & ~ZF`` (tout en prenant en compte les dépassements éventuels avec `OF`). Permet d'implémenter la condition ``>``. - - ``setl`` place dans le registre argument la valeur de ``SF`` (tout en prenant en compte les dépassements éventuels avec `OF`). Permet d'implémenter notamment la condition ``<=``. - -A titre d'illustration, voici quelques expressions logiques en C et leur implémentation en assembleur lorsque les variables utilisées sont toutes des variables globales. - -.. code-block:: c - - r=(h>1); - r=(j==0); - r=g<=h; - r=(j==h); - - -Le programme assembleur utilise une instruction ``cmpl`` pour effectuer la comparaison. Ensuite, une instruction ``set`` permet de fixer la valeur du byte de poids faible de ``%eax`` et une instruction (``movzbl``) permettant de transformer ce byte en un mot de 32 bits afin de pouvoir le stocker en mémoire. Cette traduction a été obtenue avec :term:`llvm`, d'autres compilateurs peuvent générer du code un peu différent. - -.. code-block:: nasm - - cmpl $1, h ; comparaison - setg %al ; %al est le byte de poids faible de %eax - movzbl %al, %ecx ; copie le byte dans %ecx - movl %ecx, r ; sauvegarde du résultat dans r - - cmpl $0, j ; comparaison - sete %al ; fixe le byte de poids faible de %eax - movzbl %al, %ecx - movl %ecx, r ; sauvegarde du résultat dans r - - movl g, %ecx - cmpl h, %ecx ; comparaison entre g et h - setl %al ; fixe le byte de poids faible de %eax - movzbl %al, %ecx - movl %ecx, r - - movl j, %ecx - cmpl h, %ecx ; comparaison entre j et h - sete %al - movzbl %al, %ecx - movl %ecx, r - - -Les instructions de saut ------------------------- - -Les instructions de saut sont des instructions de base pour tous les processeurs. Elles permettent de modifier la valeur du compteur de programme ``%eip`` de façon à modifier l'ordre d'exécution des instructions. Elles sont nécessaires pour implémenter les tests, les boucles et les appels de fonction. Les premiers langages de programmation et des langages tels que BASIC ou FORTRAN disposent d'une construction similaire avec l'instruction ``goto``. Cependant, l'utilisation de l'instruction ``goto`` dans des programmes de haut niveau rend souvent le code difficile à lire et de nombreux langages de programmation n'ont plus de ``goto`` [Dijkstra1968]_. Contrairement à Java, le C contient une instruction ``goto``, mais son utilisation est fortement découragée. En C, l'instruction ``goto`` prend comme argument une étiquette (label en anglais). Lors de l'exécution d'un ``goto``, le programme saute directement à l'exécution de l'instruction qui suit le label indiqué. Ceci est illustré dans l'exemple ci-dessous : - -.. literalinclude:: /Assembleur/src/goto.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -Si l'utilisation ``goto`` est en pratique prohibée dans la plupart des langages de programmation, en assembleur, les instructions de saut sont inévitables. L'instruction de saut la plus simple est ``jmp``. Elle prend généralement comme argument une étiquette. Dans ce cas, l'exécution du programme après l'instruction ``jmp`` se poursuivra par l'exécution de l'instruction qui se trouve à l'adresse correspondant à l'étiquette fournie en argument. Il est également possible d'utiliser l'instruction ``jmp`` avec un registre comme argument. Ainsi, l'instruction ``jmp *%eax`` indique que l'exécution du programme doit se poursuivre par l'exécution de l'instruction se trouvant à l'adresse qui est contenue dans le registre ``%eax``. - -Il existe plusieurs variantes conditionnelles de l'instruction ``jmp``. Ces variantes sont exécutées uniquement si la condition correspondante est vérifiée. Les variantes les plus fréquentes sont : - - - ``je`` : saut si égal (teste le drapeau `ZF`) (inverse : ``jne``) - - ``js`` : saut si négatif (teste le drapeau `SF`) (inverse : ``jns``) - - ``jg`` : saut si strictement supérieur (teste les drapeaux `SF` et `ZF` et prend en compte un overflow éventuel) (inverse : ``jl``) - - ``jge`` : saut si supérieur ou égal (teste le drapeaux `SF` et prend en compte un overflow éventuel) (inverse : ``jle``) - -Ces instructions de saut conditionnel sont utilisées pour implémenter notamment des expressions ``if (condition) { ... } else { ... }`` en C. Voici quelques traductions réalisées par un compilateur C en guise d'exemple. - -.. code-block:: c - - if(j==0) - r=1; - - if(j>g) - r=2; - else - r=3; - - if (j>=g) - r=4; - - -Avant d'analyser la traduction de ce programme en assembleur, il est utile de le réécrire en utilisant l'instruction ``goto`` afin de s'approcher du fonctionnement de l'assembleur. - -.. code-block:: c - - if(j!=0) { goto diff; } - r=1; - diff: - // suite - - if(j<=g) { goto else; } - r=2; - goto fin; - else: - r=3; - fin: - // suite - - if (j<g) { goto suivant; } - r=4; - -Ce code C correspond assez bien au code assembleur produit par le compilateur. - -.. code-block:: nasm - - cmpl $0, j ; j==0 ? - jne .LBB2_2 ; jump si j!=0 - movl $1, r ; r=1 - .LBB2_2: - - movl j, %eax ; %eax=j - cmpl g, %eax ; j<=g ? - jle .LBB2_4 ; jump si j<=g - - movl $2, r ; r=2 - jmp .LBB2_5 ; jump fin expression - .LBB2_4: - movl $3, r ; r=3 - .LBB2_5: - - movl j, %eax ; %eax=j - cmpl g, %eax ; j<g ? - jl .LBB2_7 ; jump si j<g - movl $4, r ; r=4 - .LBB2_7: - -Les instructions de saut conditionnel interviennent également dans l'implémentation des boucles. Plusieurs types de boucles existent en langage C. Considérons tout d'abord une boucle ``while``. - -.. code-block:: c - - while(j>0) - { - j=j-3; - } - -Cette boucle peut se réécrire en utilisant des ``goto`` comme suit. - - -.. code-block:: c - - debut: - if(j<=0) { goto fin; } - j=j-3; - goto debut; - fin: - -On retrouve cette utilisation des instructions de saut dans la traduction en assembleur de cette boucle. - -.. code-block:: nasm - - .LBB3_1: - cmpl $0, j ; j<=0 - jle .LBB3_3 ; jump si j<=0 - movl j, %eax - subl $3, %eax - movl %eax, j ; j=j-3 - jmp .LBB3_1 - .LBB3_3: - -Les boucles ``for`` s'implémentent également en utilisant des instructions de saut. - -.. code-block:: c - - for(j=0;j<10;j++) - { g=g+h; } - - for(j=9;j>0;j=j-1) - { g=g-h; } - -La première boucle démarre par l'initialisation de la variable ``j`` à ``0``. Ensuite, la valeur de cette variable est comparée avec ``10``. L'instruction ``jge`` fait un saut à l'adresse mémoire correspondant à l'étiquette ``.LBB4_4`` si la comparaison indique que ``j>=10``. Sinon, les instructions suivantes calculent ``g=g+h`` et ``j++`` puis l'instruction ``jmp`` relance l'exécution à l'instruction de comparaison qui est stockée à l'adresse de l'étiquette ``.LBB4_1``. - -.. code-block:: nasm - - movl $0, j ; j=0 - .LBB4_1: - cmpl $10, j - jge .LBB4_4 ; jump si j>=10 - movl g, %eax ; %eax=g - addl h, %eax ; %eax+=h - movl %eax, g ; %eax=g - movl j, %eax ; %eax=j - addl $1, %eax ; %eax++ - movl %eax, j ; j=%eax - jmp .LBB4_1 - .LBB4_4: - - movl $9, j ; j=9 - .LBB4_5: - cmpl $0, j - jle .LBB4_8 ; jump si j<=0 - movl g, %eax - subl h, %eax - movl %eax, g - movl j, %eax ; %eax=j - subl $1, %eax ; %eax-- - movl %eax, j ; j=%eax - jmp .LBB4_5 - .LBB4_8: - -La seconde boucle est organisée de façon similaire. - - -Manipulation de la pile ------------------------ - -Les instructions ``mov`` permettent de déplacer de l'information à n'importe quel endroit de la mémoire. A côté de ces instructions de déplacement, il y a des instructions qui sont spécialisées dans la manipulation de la pile. La pile, qui dans un processus Unix est stockée dans les adresses hautes est essentielle au bon fonctionnement des programmes. Par convention dans l'architecture [IA32]_, l'adresse du sommet de la pile est toujours stockée dans le registre ``%esp``. Deux instructions spéciales permettent de rajouter et de retirer une information au sommet de la pile. - - - ``pushl %reg`` : place le contenu du registre ``%reg`` au sommet de la pile et décrémente dans le registre ``%esp`` l'adresse du sommet de la pile de 4 unités. - - ``popl %reg`` : retire le mot de 32 bits se trouvant au sommet de la pile, le sauvegarde dans le registre ``%reg`` et incrémente dans le registre ``%esp`` l'adresse du sommet de la pile de 4 unités. - -En pratique, ces deux instructions peuvent également s'écrire en utilisant des instructions de déplacement et des instructions arithmétiques. Ainsi, ``pushl %ebx`` est équivalent à : - -.. code-block:: nasm - - subl $4, %esp ; ajoute un bloc de 32 bits au sommet de la pile - movl %ebx, (%esp) ; sauvegarde le contenu de %ebx au sommet - -Tandis que ``popl %ecx`` est équivalent à : - -.. code-block:: nasm - - movl (%esp), %ecx ; sauve dans %ecx la donnée au sommet de la pile - addl $4, %esp ; déplace le sommet de la pile de 4 unites vers le haut - -Pour bien comprendre le fonctionnement de la pile, il est utile de considérer un exemple simple. Imaginons la mémoire ci-dessous et supposons qu'initialement le registre ``%esp`` contient la valeur ``0x0C`` et que les registres ``eax`` et ``%ebx`` contiennent les valeurs ``0x02`` et ``0xFF``. - - ========= ======== - Adresse Valeur - ========= ======== - 0x10 0x04 - 0x0C 0x00 - 0x08 0x00 - 0x04 0x00 - 0x00 0x00 - ========= ======== - -.. code-block:: nasm - - push %eax ; %esp contient 0x08 et M[0x08]=0x02 - push %ebx ; %esp contient 0x04 et M[0x04]=0xFF - pop %eax ; %esp contient 0x08 et %eax 0xFF - pop %ebx ; %esp contient 0x0C et %ebx 0x02 - pop %eax ; %esp contient 0x10 et %eax 0x00 - - -Les fonctions et procédures ---------------------------- - -Les fonctions et les procédures sont essentielles dans tout langage de programmation. Une procédure est une fonction qui ne retourne pas de résultat. Nous commençons par expliquer comment les procédures peuvent être implémentées en assembleur et nous verrons ensuite comment implémenter les fonctions. - -Une procédure est un ensemble d'instructions qui peuvent être appelées depuis n'importe quel endroit du programme. Généralement, une procédure est appelée depuis plusieurs endroits différents d'un programme. Pour comprendre l'implémentation des procédures, nous allons considérer des procédures de complexité croissante. Nos premières procédures ne prennent aucun argument. En C, elles peuvent s'écrire sous la forme de fonctions ``void`` comme suit. - -.. literalinclude:: /Assembleur/src/proc.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - -Ces deux procédures utilisent et modifient des variables globales. Nous verrons plus tard comment supporter les variables locales. Lorsque la fonction ``main`` appelle la procédure ``init_g()`` ou la procédure ``increase``, il y a plusieurs opérations qui doivent être effectuées. Tout d'abord, le processeur doit transférer l'exécution du code à la première instruction de la procédure appelée. Cela se fait en associant une étiquette à chaque procédure qui correspond à l'adresse de la première instruction de cette procédure en mémoire. Une instruction de saut telle que ``jmp`` pourrait permettre de démarrer l'exécution de la procédure. Malheureusement, ce n'est pas suffisant car après son exécution la procédure doit pouvoir poursuivre son exécution à l'adresse de l'instruction qui suit celle d'où elle a été appelée. Pour cela, il est nécessaire que la procédure qui a été appelée puisse connaître l'adresse de l'instruction qui doit être exécutée à la fin de son exécution. Dans l'architecture [IA32]_, cela se fait en utilisant la pile. Vu l'importance des appels de procédure et de fonctions, l'architecture [IA32]_ contient deux instructions dédiés pour implémenter ces appels. L'instruction ``call`` est une instruction de saut qui transfère l'exécution à l'adresse de l'étiquette passée en argument et en plus elle sauvegarde au sommet de la pile l'adresse de l'instruction qui la suit. Cette adresse est l'adresse à laquelle la procédure doit revenir après son exécution. Elle est équivalente à une instruction ``push`` suivie d'une instruction ``jmp``. L'instruction ``ret`` est également une instruction de saut. Elle suppose que l'adresse de retour se trouve au sommet de la pile, retire cette adresse de la pile et fait un saut à cette adresse. Elle est donc équivalente à une instruction ``pop`` suivie d'une instruction ``jmp``. Dans l'architecture [IA32]_, le registre ``%esp`` contient en permanence le sommet de la pile. Les instructions ``call`` et ``ret`` modifient donc la valeur de ce registre lorsqu'elles sont exécutées. En assembleur, le programme ci-dessus se traduit comme suit : - -.. code-block:: nasm - - increase: ; étiquette de la première instruction - movl g, %eax - addl h, %eax - movl %eax, g - ret ; retour à l'endroit qui suit l'appel - init_g: ; étiquette de la première instruction - movl $1252, g - ret ; retour à l'endroit qui suit l'appel - main: - subl $12, %esp - movl 20(%esp), %eax - movl 16(%esp), %ecx - movl $0, 8(%esp) - movl %ecx, 4(%esp) - movl %eax, (%esp) - calll init_g ; appel à la procédure init_g - A_init_g: calll increase ; appel à la procédure increase - A_increase: movl $0, %eax - addl $12, %esp - ret ; fin de la fonction main - g: ; étiquette, variable globale g - .long 0 ; initialisée à 0 - h: ; étiquette, variable globale g - .long 2 ; initialisée à 2 - - -Dans ce code assembleur, on retrouve dans le bas du code la déclaration des deux variables globales, ``g`` et ``h`` et leurs valeurs initiales. Chaque procédure a son étiquette qui correspond à l'adresse de sa première instruction. La fonction ``main`` débute par une manipulation de la pile qui ne nous intéresse pas pour le moment. L'appel à la procédure ``init_g()`` se fait via l'instruction ``calll init_g`` qui place sur la pile l'adresse de l'étiquette ``A_init_g``. La procédure ``init_g()`` est très simple puisqu'elle comporte une instruction ``movl`` qui permet d'initialiser la variable ``g`` suivie d'une instruction ``ret``. Celle-ci retire de la pile l'adresse ``A_init_g`` qui y avait été placée par l'instruction ``call`` et poursuit l'exécution du programme à cette adresse. L'appel à la procédure ``increase`` se déroule de façon similaire. - - -Considérons une petite variante de notre programme C dans lequel une procédure ``p`` appelle une procédure ``q``. - -.. literalinclude:: /Assembleur/src/proc2.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - -La compilation de ce programme produit le code assembleur suivant pour les procédures ``p`` et ``q``. - - -.. code-block:: nasm - - q: - movl $1252, g - ret ; retour à l'appelant - p: - subl $12, %esp ; réservation d'espace sur pile - calll q ; appel à la procédure q - movl g, %eax - addl h, %eax - movl %eax, g - addl $12, %esp ; libération espace réservé sur pile - ret ; retour à l'appelant - -La seule différence par rapport au programme précédent est que la procédure ``p`` descend le sommet de la pile de 12 unités au début de son exécution et l'augmente de 12 unités à la fin. Ces manipulations sont nécessaires pour respecter une convention de l'architecture [IA32]_ qui veut que les adresses de retour des procédures soient alignées sur des blocs de 16 bytes. - -Considérons maintenant une procédure qui prend un argument. Pour qu'une telle procédure puisse utiliser un argument, il faut que la procédure appelante puisse placer sa valeur à un endroit où la procédure appelée peut facilement y accéder. Dans l'architecture [IA32]_, c'est la pile qui joue ce rôle et permet le passage des arguments. En C, les arguments sont passés par valeur et ce sera donc les valeurs des arguments qui seront placées sur la pile. A titre d'exemple, considérons une procédure simple qui prend deux arguments entiers. - -.. literalinclude:: /Assembleur/src/fct.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - -Le passage des arguments de la fonction ``init`` depuis la fonction ``main`` se fait en les plaçant sur la pile avec les instructions ``movl $1252, (%esp)`` et ``movl $1, 4(%esp)`` qui précèdent l'instruction ``call init``. Le premier argument est placé au sommet de la pile et le second juste au-dessus. La fonction ``main`` sauvegarde d'autres registres sur la pile avant l'appel à ``init``. Ces sauvegardes sont nécessaires car la fonction ``main`` ne sait pas quels registres seront modifiés par la fonction qu'elle appelle. En pratique l'architecture [IA32]_ définit des conventions d'utilisation des registres. Les registres ``%eax``, ``%edx`` et ``%ecx`` sont des registres qui sont sous la responsabilité de la procédure appellante (dans ce cas ``main``). Une procédure appelée (dans ce cas-ci ``init``) peut modifier sans restrictions les valeurs de ces registres. Si la fonction appellante souhaite pouvoir utiliser les valeurs stockées dans ces registres après l'appel à la procédure, elle doit les sauvegarder elle-même sur la pile. C'est ce que fait la fonction ``main`` pour ``%eax``, ``%edx`` et ``%ecx``. Inversement, les registres ``%ebx``, ``%edi`` et ``%esi`` sont des registres qui doivent être sauvés par la procédure appelée si celle-ci les modifie. La procédure ``init`` n'utilisant pas ces registres, elle ne les sauvegarde pas. Par contre, la fonction ``main`` débute en sauvegardant le registre ``%esi`` sur la pile. - -.. code-block:: nasm - - init: - subl $8, %esp ; réservation d'espace sur la pile - movl 16(%esp), %eax ; récupération du second argument - movl 12(%esp), %ecx ; récupération du premier argument - movl %ecx, 4(%esp) ; sauvegarde sur la pile - movl %eax, (%esp) ; sauvegarde sur la pile - movl 4(%esp), %eax ; chargement de i - movl %eax, g ; g=i - movl (%esp), %eax ; chargement de j - movl %eax, h ; h=j - addl $8, %esp ; libération de l'espace réservé - ret - main: - pushl %esi - subl $40, %esp - movl 52(%esp), %eax - movl 48(%esp), %ecx - movl $1252, %edx - movl $1, %esi - movl $0, 36(%esp) - movl %ecx, 32(%esp) - movl %eax, 24(%esp) - movl $1252, (%esp) ; premier argument sur la pile - movl $1, 4(%esp) ; deuxième argument sur la pile - movl %esi, 20(%esp) - movl %edx, 16(%esp) - calll init ; appel à init - movl $0, %eax - addl $40, %esp - popl %esi - ret - - -La différence entre une procédure et une fonction est qu'une fonction retourne un résultat. Considérons le programme suivant et les fonctions triviales ``int init()`` et ``int sum(int, int)``. Pour que de telles fonctions puissent s'exécuter et retourner un résultat, il faut que la procédure appelante puisse savoir où aller chercher le résultat après exécution de l'instruction ``ret``. - -.. literalinclude:: /Assembleur/src/fct2.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - -La compilation du programme C ci-dessus en assembleur produit le code suivant. Dans l'architecture [IA32]_, la valeur de retour d'une fonction est stockée par convention dans le registre ``%eax``. Cette convention est particulièrement visible lorsque l'on regarde les instructions générées pour la fonction ``int init()``. La fonction ``sum`` retourne également son résultat dans le registre ``%eax``. - -.. code-block:: nasm - - init: - movl $1252, %eax - ret - sum: - subl $8, %esp ; réservation d'espace sur la pile - movl 16(%esp), %eax ; récupération du second argument - movl 12(%esp), %ecx ; récupération du premier argument - movl %ecx, 4(%esp) - movl %eax, (%esp) - movl 4(%esp), %eax ; %eax=a - addl (%esp), %eax ; %eax=a+b - addl $8, %esp ; libération de l'espace réservé - ret - main: - subl $28, %esp - movl 36(%esp), %eax - movl 32(%esp), %ecx - movl $0, 24(%esp) - movl %ecx, 20(%esp) ; sauvegarde sur la pile - movl %eax, 16(%esp) ; sauvegarde sur la pile - calll init - movl $1, %ecx - movl $2, %edx - movl %eax, g - movl $1, (%esp) ; premier argument - movl $2, 4(%esp) ; second argument - movl %ecx, 12(%esp) ; sauvegarde sur la pile - movl %edx, 8(%esp) ; sauvegarde sur la pile - calll sum - movl $0, %ecx - movl %eax, h - movl %ecx, %eax - addl $28, %esp - ret - - -Pour terminer notre exploration de la compilation de fonctions C en assembleur, considérons une fonction récursive. Par simplicité, nous utilisons la fonction ``sumn`` qui calcule de façon récursive la somme des n premiers entiers. - -.. literalinclude:: /Assembleur/src/sumn.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Lorsque cette fonction récursive est compilée, on obtient le code ci-dessous. Celui-ci démarre par réserver une zone de 28 bytes sur la pile et récupère ensuite l'argument qui est placé dans le registre ``%eax``. Cet argument est utilisé comme variable locale, il est donc sauvegardé sur la pile de la fonction ``sumn`` dans la zone qui vient d'être réservée. Ensuite, on compare la valeur de l'argument avec ``1``. Si l'argument est inférieur ou égal à ``1``, on récupère la variable locale sur la pile et on la sauve à un autre endroit en préparation à la fin du code (étiquette ``.LBB1_3``) ou elle sera placée dans le registre ``%eax`` avant l'exécution de l'instruction ``ret``. Sinon, l'appel récursif est effectué. Pour cela, il faut d'abord calculer ``n-1``. Cette valeur est stockée dans le registre ``%ecx`` puis placée sur la pile avant l'appel récursif. Comme un appel de fonction ne préserve pas ``%eax`` et que cette valeur est nécessaire après l'appel récursif, elle est sauvegardée sur la pile. La première instruction qui suit l'exécution de l'appel récursif récupère la valeur de la variable ``n`` sur la pile et la place dans le registre ``%ecx``. Le résultat de l'appel récursif étant placé dans ``%eax``, l'instruction ``addl %ecx, %eax`` calcule bien ``n+sum(n-1)``. Ce résultat est placé sur la pile puis récupéré et placé dans ``%eax`` avant l'exécution de ``ret``. Il faut noter que les 28 bytes qui avaient étés ajoutés à la pile au début de la fonction sont retirées par l'instruction ``addl $28, %esp``. C'est nécessaire pour que la pile soit bien préservée lors de l'appel à une fonction. - -.. code-block:: nasm - - sumn: - subl $28, %esp ; réservation d'espace sur la pile - movl 32(%esp), %eax ; récupération argument - movl %eax, 20(%esp) ; sauvegarde sur pile - cmpl $1, 20(%esp) - jg .LBB1_2 ; jump si n>1 - movl 20(%esp), %eax ; récupération n - movl %eax, 24(%esp) - jmp .LBB1_3 - .LBB1_2: - movl 20(%esp), %eax - movl 20(%esp), %ecx - subl $1, %ecx ; %ecx=n-1 - movl %ecx, (%esp) ; argument sur pile - movl %eax, 16(%esp) - recursion: - calll sumn - movl 16(%esp), %ecx ; récupération de n - addl %ecx, %eax ; %eax=%eax+n - movl %eax, 24(%esp) - .LBB1_3: - movl 24(%esp), %eax - addl $28, %esp ; libération de l'espace réservé sur la pile - ret - - -Ce code illustre la complexité de supporter des appels récursifs en C et le coût au niveau de la gestion de la pile notamment. Ces appels récursifs doivent être réservés à des fonctions où l'appel récursif apporte une plus value claire. - -.. rubric:: Footnotes - -.. [#fintel] Pour une liste détaillée des processeurs de cette famille produits par intel_, voir notamment http://www.intel.com/pressroom/kits/quickreffam.htm D'autres fabricants produisent également des processeurs compatibles avec l'architecture [IA32]_. - -.. [#fmov] On parle de famille d'instructions car il existe de nombreuses instructions de déplacement en mémoire. Les plus simples sont suffixées par un caractère qui indique le type de données transféré. Ainsi, ``movb`` permet le transfert d'un byte tandis que ``movl`` permet le transfert d'un mot de 32 bits. Des détails sur ces instructions peuvent être obtenus dans [IA32]_ - -.. [#fllvm] Cette traduction et la plupart des traductions utilisées dans ce chapitre ont été obtenues en utilisant l'interface `web de démo <http://llvm.org/demo/index.cgi>`_ du compilateur llvm_ qui a été configuré pour générer du code 32 bits sans optimisation. Quelques détails ont été supprimés du code assembleur pour le rendre plus compact. - - diff --git a/Theorie/Assembleur/src/argserror.c b/Theorie/Assembleur/src/argserror.c deleted file mode 100644 index eafc07a69d09dcde15e0559bef5d9999164d0198..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/argserror.c +++ /dev/null @@ -1,24 +0,0 @@ -/************************************** - * argserror.c - * - * Programme d'exemple d'appel de fonction - * avec un nombre erroné d'arguments - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int g; - -int f(int i, int j) { - return i+j; -} - -int main(int argc, char *argv[]) { - - g=f(3,0); - // g=f(5,6,7); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Assembleur/src/asm-exemples.c b/Theorie/Assembleur/src/asm-exemples.c deleted file mode 100644 index 0e22c1a9ef89707948d13fb035d8cf527bcb75bf..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/asm-exemples.c +++ /dev/null @@ -1,118 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -int g=1; -int h=2; -int j,j2,l,l,m,k; -int r; - -void a() -{ - j=j+1; - k=g-h; -} - -void cmp() -{ - r=(h>1); - r=(j==0); - r=g<h; - r=(j==h); -} - -void jump() -{ - if(j==0) - r=1; - - if(j>g) - r=2; - else - r=3; - - if (j>=g) - r=4; - -} - -void while_loop() -{ - while(j>0) - { - j=j-3; - } - -} - -void for_loop() -{ - for(j=0;j<10;j++) - g=g+h; - - for(j=9;j>0;j=j-1) - g=g-h; -} - -void increase() -{ - g=g+h; -} - -void init_g() -{ - g=1252; -} - -void init(int a) { -g=a; -} - -void sumg(int a, int b) { - g= a+b; -} - -int sum(int a, int b) { - return a+b; -} - -void b() -{ - l=g^j; - j=j|k; - g=l<<6; -} - -int test() -{ - h=~h; - j++; - j=j+1; - j=g/h; - j2=g*h; - k=g-h; - l=g>>4; - g=l<<6; - m= h&&g; - return m; - -} - -int add() -{ - int l=1252; - l=g+h; - return l; -} - -int factorial(int X) { - if (X == 0) return 1; - return X*factorial(X-1); -} - -int main(int argc, char **argv) { - init_g(); - increase(); - init(1252); - sumg(6,7); - printf("%d\n", factorial(atoi(argv[1]))); -} diff --git a/Theorie/Assembleur/src/asm-intro.c b/Theorie/Assembleur/src/asm-intro.c deleted file mode 100644 index 18a5e8310667be3f03a918c79d7e4736d069c926..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/asm-intro.c +++ /dev/null @@ -1,54 +0,0 @@ -/************************************** - * var.c - * - * Programme d'exemple pour localiser - * les variables en mémoire - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - - - -int global_int=1; -int global_i=1; -int global_j=1; -float global_float=1.0; -char global_char='c'; - -int add() { - int v=global_i+global_j; - return(v); -} - -int sum(int i, int j) { - return (i+j); -} - -int sumn(int n) { - if(n>0) - return (n + sumn(n-1)); - else - return n; -} - - -int while_loop(void) { - int i=1; - int j=17; - while(i<j) - i=i+2; - return i; -} - -int main(int argc, char *argv[]) { - - int local_int=1; - float local_float=1.0; - char local_char='c'; - printf("while0=%d\n",while_loop()); - printf("add=%d\n",add()); - printf("sumn(3)=%d\n",sumn(3)); - return(EXIT_SUCCESS); -} diff --git a/Theorie/Assembleur/src/backtrace.c b/Theorie/Assembleur/src/backtrace.c deleted file mode 100644 index 8802f85cffca07bb8ea633474b4b722c4b4bc35e..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/backtrace.c +++ /dev/null @@ -1,56 +0,0 @@ -#include <stdio.h> -#include <string.h> - -char safechar(char c) -{ - if (c >= 'a' && c <= 'z') return(c); - if (c >= 'A' && c <= 'Z') return(c); - if (c >= '0' && c <= '9') return(c); - if (c == ' ') return(c); - if (c == '.') return(c); - if (c == '-') return(c); - if (c == ',') return(c); - if (c == '(') return(c); - if (c == ')') return(c); - if (c == '[') return(c); - if (c == ']') return(c); - if (c == '{') return(c); - if (c == '}') return(c); - return '.'; -} - -void print_backtrace(void *from) -{ - long *s = (long *) &s+1; - - while ((long) s <= (long) from) { - int i; - printf("[%p] %20ld 0x%-16lx ", s, *s, *s); - for (i = 0; i < sizeof(*s); i++) - printf("%c", safechar(((char *) s)[i])); - printf("\n"); - s++; - } - -} - -long bar(void *p) -{ - print_backtrace(p); - return 42; -} - -long foo(void *p) -{ - long a = 42, b; - void *cool = p; - b = a; - - return b + a + bar(cool); -} - -int main(int argc, char const *argv[]) -{ - const char *args = argv[argc-1]; - return foo((void *)&args[strlen(args)+1]); -} diff --git a/Theorie/Assembleur/src/fct.c b/Theorie/Assembleur/src/fct.c deleted file mode 100644 index 376d17bebf77698091d9942b632c5c6b759fb26b..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/fct.c +++ /dev/null @@ -1,22 +0,0 @@ -/************************************** - * fct.c - * - * Programme d'exemple pour une fonction - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -///AAA -int g=0; -int h=2; -void init(int i, int j) { - g=i; - h=j; -} - -int main(int argc, char *argv[]) { - init(1252,1); - return(EXIT_SUCCESS); -} diff --git a/Theorie/Assembleur/src/fct2.c b/Theorie/Assembleur/src/fct2.c deleted file mode 100644 index 5a93282031ce2c7d595c5d09f57aebe86f75323a..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/fct2.c +++ /dev/null @@ -1,27 +0,0 @@ -/************************************** - * fct2.c - * - * Programme d'exemple pour une fonction - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -///AAA -int g=0; -int h=2; - -int init() { - return 1252; -} - -int sum(int a, int b) { - return a+b; -} - -int main(int argc, char *argv[]) { - g=init(); - h=sum(1,2); - return(EXIT_SUCCESS); -} diff --git a/Theorie/Assembleur/src/gdb.c b/Theorie/Assembleur/src/gdb.c deleted file mode 100644 index c1f104d95735d53290039f25e12daf46352af831..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/gdb.c +++ /dev/null @@ -1,31 +0,0 @@ -#include <stdio.h> - -void calc (int *tab, int i, int num) -{ - tab[i] = num / i; -} - -void iter (int *tab, int num) -{ - int i; - printf("Iterating\n"); - for (i = 0; i <= 10; i++) { - calc(tab, i, num); - } -} - -int main (int argc, char * argv[]) -{ - int *tab = NULL; - int num = 20; - int i; - - iter(tab, num); - - for (i = 0; i < 10; i++) { - printf(" %d", tab[i]); - } - printf("\n"); - - return 0; -} diff --git a/Theorie/Assembleur/src/gdbex.c b/Theorie/Assembleur/src/gdbex.c deleted file mode 100644 index 504615dcaab59fb7ddea5e32f0031fb3aa44f867..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/gdbex.c +++ /dev/null @@ -1,21 +0,0 @@ -/************************************** - * gdbex.c - * - * Programme d'exemple pour gdb - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - - -int g=0; -int h=0; - -int main(int argc, char *argv[]) { - - g=3; - h=g+h; - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Assembleur/src/goto.c b/Theorie/Assembleur/src/goto.c deleted file mode 100644 index 7a5bafcc1dddc681a5a7a539366ab79882af5aa4..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/goto.c +++ /dev/null @@ -1,40 +0,0 @@ -/************************************** - * goto.c - * - * Programme d'exemple pour goto - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -#define SIZE 10 -#define MVAL 2100000000 - -int m[SIZE][SIZE]; - -int main(int argc, char *argv[]) { - - srandom(getpid()); - for(int i=0;i<SIZE;i++) - for(int j=0;j<SIZE;j++) { - m[i][j]=(int)random(); - } - ///AAA - int v=0; - for(int i=0;i<SIZE;i++) - for(int j=0;j<SIZE;j++) { - if(m[i][j]>MVAL) { - v=m[i][j]; - goto suite; - } - } - printf("aucune valeur supérieure à %d\n",MVAL,v); - goto fin; - suite: - printf("première valeur supérieure à %d : %d\n",MVAL,v); - fin: - return(EXIT_SUCCESS); - ///BBB - -} diff --git a/Theorie/Assembleur/src/memory.c b/Theorie/Assembleur/src/memory.c deleted file mode 100644 index a3bacbd066eb539ef1797729b684ee9f1b1725cc..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/memory.c +++ /dev/null @@ -1,34 +0,0 @@ -/************************************** - * memory.c - * - * Programme de manipulation de la mémoire - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - - -#define SIZE 1000000 - -struct s1 { - int i; - char c[1]; - int j; -}; - -struct s100 { - int i; - char c[100]; - int j; -}; - - -int main(int argc, char *argv[]) { - - struct s1 *s1_ptr=(struct s1 *)malloc(sizeof(struct s1)*SIZE); - struct s100 *s100_ptr=(struct s100 *)malloc(sizeof(struct s100)*SIZE); - - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Assembleur/src/nofree.c b/Theorie/Assembleur/src/nofree.c deleted file mode 100644 index 490d9d9d88f55af9d18f232c93faf54cc4c6120c..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/nofree.c +++ /dev/null @@ -1,9 +0,0 @@ -#include <stdlib.h> - -int main(int argc, char * argv[]) -{ - char *ptrChars = (char *)malloc(6 * sizeof(char)); - ptrChars[0]= 'H'; - - return 0; -} diff --git a/Theorie/Assembleur/src/outofbounds.c b/Theorie/Assembleur/src/outofbounds.c deleted file mode 100644 index 6142f78364591ab0d843adcdeddc7b887137c12b..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/outofbounds.c +++ /dev/null @@ -1,11 +0,0 @@ -#include <stdlib.h> - -int main(int argc, char * argv[]) -{ - char *ptrChars = (char *)malloc(6 * sizeof(char)); - ptrChars[0]= 'H'; - ptrChars[12]= 'W'; - free(ptrChars); - - return 0; -} diff --git a/Theorie/Assembleur/src/proc.c b/Theorie/Assembleur/src/proc.c deleted file mode 100644 index b396bbd439f173e89e6951582bb68a17d6af289c..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/proc.c +++ /dev/null @@ -1,27 +0,0 @@ -/************************************** - * proc.c - * - * Programme d'exemple pour les procédures - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -///AAA -int g=0; -int h=2; - -void increase() { - g=g+h; -} - -void init_g() { - g=1252; -} - -int main(int argc, char *argv[]) { - init_g(); - increase(); - return(EXIT_SUCCESS); -} diff --git a/Theorie/Assembleur/src/proc2.c b/Theorie/Assembleur/src/proc2.c deleted file mode 100644 index 24e646116690d40bf213cbdc2402643e1cabf01a..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/proc2.c +++ /dev/null @@ -1,29 +0,0 @@ -/************************************** - * proc2.c - * - * Programme d'exemple pour les procédures - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -///AAA -int g=0; -int h=2; - -void q() { - g=1252; -} - -void p() { - q(); - g=g+h; -} - - - -int main(int argc, char *argv[]) { - p(); - return(EXIT_SUCCESS); -} diff --git a/Theorie/Assembleur/src/sumarray.c b/Theorie/Assembleur/src/sumarray.c deleted file mode 100644 index 6351bcc625e42ceaf83451ac8002543d782c0a86..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/sumarray.c +++ /dev/null @@ -1,56 +0,0 @@ -/************************************** - * sumarray.c - * - * Programme d'exemple pour calculer la - * somme des éléments d'une matrice - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -/* Return t2-t1 in microseconds */ -long timeval_diff(struct timeval *t2, struct timeval *t1) -{ - long diff = (t2->tv_usec + 1000000 * t2->tv_sec) - (t1->tv_usec + 1000000 * t1->tv_sec); - return (diff); -} - -///AAA -#define SIZE 10000 - -int matrix[SIZE][SIZE]; - -int sum() { - int sum=0; - for(int i=0;i<SIZE;i++) { - for(int j=0;j<SIZE;j++) { - sum+=matrix[i][j]; - } - } - return sum; -} - -int sum2() { - int sum=0; - for(int i=0;i<SIZE;i++) { - for(int j=0;j<SIZE;j++) { - sum+=matrix[j][i]; - } - } - return sum; -} -///BBB - -int main(int argc, char *argv[]) { - - for(int i=0;i<SIZE;i++) { - for(int j=0;j<SIZE;j++) { - matrix[i][j]=1; - } - } - printf("%d\n",sum()); - printf("%d\n",sum2()); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Assembleur/src/sumn.c b/Theorie/Assembleur/src/sumn.c deleted file mode 100644 index 208c855013270ebc95aa7dec4f48c022359c14c9..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/sumn.c +++ /dev/null @@ -1,34 +0,0 @@ -/************************************** - * sumn.c - * - * Programme d'exemple pour un calcul récursif - * de la somme des n premiers entiers - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - - -int g=0; -int h=0; -///CCC -int sumn_iter(int n) { - int sum=0; - for(int i=1;i<=n;i++) - sum+=i; - return sum; -} -///AAA -int sumn(int n) { - if(n<=1) - return n; - else - return n+sumn(n-1); -} -///BBB -int main(int argc, char *argv[]) { - g=sumn(3); - h=sumn_iter(3); - return(EXIT_SUCCESS); -} diff --git a/Theorie/Assembleur/src/twofree.c b/Theorie/Assembleur/src/twofree.c deleted file mode 100644 index 93d7ae59b6b9aecf2193bedd669cc69b106af2aa..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/twofree.c +++ /dev/null @@ -1,11 +0,0 @@ -#include <stdlib.h> - -int main(int argc, char * argv[]) -{ - char *ptrChars = (char *)malloc(6 * sizeof(char)); - ptrChars[0]= 'H'; - free(ptrChars); - free(ptrChars); - - return 0; -} diff --git a/Theorie/Assembleur/src/var.c b/Theorie/Assembleur/src/var.c deleted file mode 100644 index 4ce1462aa121293a39baf57f087a6dca78b42b75..0000000000000000000000000000000000000000 --- a/Theorie/Assembleur/src/var.c +++ /dev/null @@ -1,17 +0,0 @@ -/************************************** - * var.c - * - * Programme d'exemple pour localiser - * les variables en mémoire - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) { - // affiche sur la sortie standard - printf("Hello, world!\n"); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S2-src/array.c b/Theorie/C/S2-src/array.c deleted file mode 100644 index b9414f65d61180245ce5cf181f7ec6bb0f3ba488..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/array.c +++ /dev/null @@ -1,97 +0,0 @@ -/*********************************************** - * array.c - * - * Programme d'exemple d'utilisation de tableaux - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - -///AAA - -#define N 10 -int vecteur[N]; -float matriceC[N][N]; -float matriceR[N][2*N]; - -///BBB - -// calcule la somme des éléments d'un tableau -int sum(int v[]) -{ - ///CCC - - int i; - int sum = 0; - for (i = 0; i < N; i++) { - sum += v[i]; - } - - ///DDD - - return sum; -} - -// calcule la somme des éléments d'un tableau -int sum2(int size, int v[size]) -{ - int i; - int sum = 0; - for (i = 0; i < size; i++) { - sum += v[i]; - } - return sum; -} - -#include <float.h> - -// retourne le maximum d'un matrice -// carrée de NxN élément -float max() -{ - ///EEE - #define L 2 - #define C 3 - float matriceR[L][C] = { {1.0,2.0,3.0}, - {4.0,5.0,6.0} }; - int i, j; - float min = FLT_MAX; - for (i = 0; i < L; i++) - for (j = 0; j < C; j++) - if (matriceR[i][j] < min) - min=matriceR[i][j]; - - ///FFF - return min; -} - -// retourne le maximum d'un matrice -// carrée de NxN élément -float max2(int size, float mat[size][size]) { - int i,j; - float m=0.0; // corrige MINFLOAT - for(i=0;i<size;i++) - for(j=0;j<size;j++){ - if(mat[i][j]>m) - m=mat[i][j]; - } - return m; -} - - -int main(int argc, char *argv[]) { - - ///CCC - int vecteur[N]={0,1,2,3,4,5,6,7,8,9}; - int i; - int sum=0; - for(i=0;i<N; i++) { - sum+=vecteur[i]; - } - ///DDD - - - return(EXIT_SUCCESS); -} - diff --git a/Theorie/C/S2-src/arrayvar.c b/Theorie/C/S2-src/arrayvar.c deleted file mode 100644 index eb5c7a77039b4678ee0d40a4c70eebfbbc1a3af5..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/arrayvar.c +++ /dev/null @@ -1,46 +0,0 @@ -/*********************************************** - * arrayvar.c - * - * Programme d'exemple d'utilisation de tableaux - * de taille non prédéfinie à la compilation - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <math.h> - -#define N 10 - -void init(int size, int v[]) { - int i; - for(i=0;i<size;i++) - v[i]=1; - -} - - -int main(int argc, char *argv[]) { - /* - int size; - int vecteur[]; - int i; - if(argc!=1) { - fprintf(stderr, "Usage : arrayvar n avec n entier\n"); - return(EXIT_FAILURE); - } - size=atoi(argv[1]); - */ - - ///CCC - int vecteur[N]={0,1,2,3,4,5,6,7,8,9}; - int i; - int sum=0; - for(i=0;i<N; i++) { - sum+=vecteur[i]; - } - ///DDD - - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S2-src/char-addr.c b/Theorie/C/S2-src/char-addr.c deleted file mode 100644 index 667a1f2b944c03623ea68a40679086cc04b3e2f2..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/char-addr.c +++ /dev/null @@ -1,27 +0,0 @@ -/*********************************************** - * charaddr.c - * - * Pointeurs et chaînes de caractères - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - - -///BBB -int main(int argc, char *argv[]) { - -///AAA - - int i; - char name1[] = "str"; - // char name2[] = "SINF1252"; - - for(i=0;i<10;i++) { - printf("%c",name1[i]); - } - - return(EXIT_SUCCESS); -} - diff --git a/Theorie/C/S2-src/char.c b/Theorie/C/S2-src/char.c deleted file mode 100644 index 657e37b3bd10f813cf1bcdc90776f2a1c9d66061..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/char.c +++ /dev/null @@ -1,36 +0,0 @@ -/*********************************************** - * strlen.c - * - * Initialisation de chaînes de caractères - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - - -///AAA - -int length(char str[]) { - int i=0; - while(str[i]!=0) { // '\0' et 0 sont égaux - i++; - } - return(i); -} - -///BBB -int main(int argc, char *argv[]) { - - int i; - char name1[] = "str"; - // char name2[] = "SINF1252"; - - printf("Longueur de name1 [%s] : %d\n",name1,length(name1)); - for(i=0;i<10;i++) { - printf("%c",name1[i]); - } - - return(EXIT_SUCCESS); -} - diff --git a/Theorie/C/S2-src/exprbin.c b/Theorie/C/S2-src/exprbin.c deleted file mode 100644 index 405d3f1b6a2546985dfd2407348da6a0e9012f85..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/exprbin.c +++ /dev/null @@ -1,104 +0,0 @@ -/*********************************************** - * exprbin.c - * - * Programme d'exemple d'utilisation d'expressions - * binaires - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - -#include <stdlib.h> -#define BITS_CHAR 8 - -///EEE -#define BITS_INT 32 -// str[BITS_INT] -void int2bin(unsigned int num, char *str) -{ - int i; - str[BITS_INT] = '\0'; - for (i = BITS_INT - 1; i >= 0; i--) { - if ((num & 1) == 1) - str[i] = '1'; - else - str[i] = '0'; - num = num >> 1; - } -} -///FFF - -// str[32] -void char2bin(unsigned char num, char *str) -{ - int i; - str[BITS_CHAR]='\0'; - for(i=BITS_CHAR-1; i>=0; i--) { - if( (num & 1)==1) - str[i]='1'; - else - str[i]='0'; - num = num >> 1; - } -} - - - -int main(int argc, char *argv[]) { - - unsigned char zero='\0'; ///EEE - unsigned char a=0xFA; - unsigned char b=0x5F; - unsigned char c=0x50; - unsigned char d=0x50; - - unsigned char r; - unsigned int i1,i2,i3; - i1=0; - i2=0x4; - i3=0x5; - - char str1[32]; - char str2[32]; - char str3[32]; - - char2bin(zero,str1); - char2bin(~zero,str2); - printf("~ %s = %s\n",str1,str2); - char2bin(a,str1); - char2bin(b,str2); - char2bin(a&b,str3); - printf("%s & %s = %s\n",str1,str2,str3); - char2bin(a,str1); - char2bin(b,str2); - char2bin(a|b,str3); - printf("%s | %s = %s\n",str1,str2,str3); - char2bin(a^b,str3); - printf("%s ^ %s = %s\n",str1,str2,str3); - -///AAA - -r = ~a; // négation bit à bit -r = a & b; // conjonction bit à bit -r = a | b; // disjonction bit à bit -r = a ^ b; // xor bit à bit - -///BBB - -///CCC - -r = c & 0x7E; // 0b01111110 force les bits de poids faible et fort à 0 -r = d | 0x18; // 0b00011000 force les bits 4 et 3 à 1 - -///DDD - - /* - printf("0x%x & 0x%x = 0x%x\n",i2,i3,i2 & i3); - printf("0x%x && 0x%x = 0x%8x\n",i2,i3,i2 && i3); - printf("0x%x | 0x%x = 0x%8x\n",i2,i3,i2 | i3); - printf("0x%x || 0x%x = 0x%8x\n",i2,i3,i2 || i3); - */ - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S2-src/exprbin.out b/Theorie/C/S2-src/exprbin.out deleted file mode 100644 index 01ca81de56e2d8d0cafd5cd17632a1891de76154..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/exprbin.out +++ /dev/null @@ -1,4 +0,0 @@ -~ 00000000 = 11111111 -11111010 & 01011111 = 01011010 -11111010 | 01011111 = 11111111 -11111010 ^ 01011111 = 10100101 diff --git a/Theorie/C/S2-src/fct.c b/Theorie/C/S2-src/fct.c deleted file mode 100644 index 4c407b0d9d932105c8d4bf5364912320c79c5374..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/fct.c +++ /dev/null @@ -1,79 +0,0 @@ -/*********************************************** - * fct.c - * - * Programme d'exemple d'utilisation de fonctions - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -///AAA - -void usage() -{ - printf("Usage : ...\n"); -} - -///BBB - -///CCC - -int twotimes(int n) -{ - return 2 * n; -} - -int two_times(int n) -{ - n = 2 * n; - return n; -} - -///DDD - - -///EEE - -int times_two(int *n) -{ - return (*n) + (*n); -} - -int timestwo(int *n) -{ - *n = (*n) + (*n); - return *n; -} - -void f() -{ - int i = 1252; - printf("i:%d\n", i); - printf("times_two(&i)=%d\n", times_two(&i)); - printf("après times_two, i:%d\n", i); - printf("timestwo(&i)=%d\n", timestwo(&i)); - printf("après timestwo, i:%d\n", i); -} - -///FFF - -void plusun(int size, int *v) { - int i; - for(i=0;i<size;i++) - v[i]++; -} - -///GGG - - -int main(int argc, char *argv[]) { - - int i=1252; - int j; - - f(); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S2-src/fct.h b/Theorie/C/S2-src/fct.h deleted file mode 100644 index 5f423f84bd19fb926bdee8cb4a03b22a5dfba740..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/fct.h +++ /dev/null @@ -1,11 +0,0 @@ -/*********************************************** - * fct.h - * - * Exemple de signatures de fonctions - * - ***********************************************/ - -///HHH -int times_two(int *); -int timestwo(int *); -///III diff --git a/Theorie/C/S2-src/fct.out b/Theorie/C/S2-src/fct.out deleted file mode 100644 index 8c4f1575eff2047ccbdceacd2ea44afa1bc2df53..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/fct.out +++ /dev/null @@ -1,5 +0,0 @@ -i:1252 -times_two(&i)=2504 -après times_two, i:1252 -timestwo(&i)=2504 -après timestwo, i:2504 diff --git a/Theorie/C/S2-src/fctargs.c b/Theorie/C/S2-src/fctargs.c deleted file mode 100644 index a08a229a46cb03841fd895888dcfbde383864d44..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/fctargs.c +++ /dev/null @@ -1,65 +0,0 @@ -/*********************************************** - * fctargs.c - * - * Programme d'exemple d'utilisation de fonctions - * montre l'importance de traiter les arguments en - * ordre - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> - -#define N 5 -///AAA -int length(char c[]) { - int i=0; - while(c[i]!='\0') - i++; - return (i); -} -///BBB - -///CCC -void plusun(int size, int *v) -{ - int i; - for (i = 0; i < size; i++) - v[i]++; -} - -void print_vecteur(int size, int*v) { - int i; - printf("v={"); - for (i = 0;i < size - 1; i++) - printf("%d,", v[i]); - - if (size > 0) - printf("%d}", v[size - 1]); - else - printf("}"); -} -///DDD - -void wrong() { - int vecteur[N]={1,2,3,4,5}; - /// provoque un segmentation fault - ///GGG - plusun(vecteur,N); - print_vecteur(N,vecteur); - ///HHH -} - - -int main(int argc, char *argv[]) { - -///EEE -int vecteur[N] = {1, 2, 3, 4, 5}; -plusun(N, vecteur); -print_vecteur(N, vecteur); -///FFF - - return EXIT_SUCCESS; -} diff --git a/Theorie/C/S2-src/foobar.c b/Theorie/C/S2-src/foobar.c deleted file mode 100644 index c54fe40d0e88999c739aff1f8cf84b72dbcfd54f..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/foobar.c +++ /dev/null @@ -1,25 +0,0 @@ -/*********************************************** - * foobar.c - * - * Exercice - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> -void foo(void) { - int a = 42; - printf("%d\n", a); -} - -void bar(void) { -// cppcheck-suppress uninitvar ; - int a; - printf("%d\n", a); -} -// cppcheck-suppress uninitvar // -int main(int argc, char *argv[]) { - foo(); - bar(); - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S2-src/int2bin.c b/Theorie/C/S2-src/int2bin.c deleted file mode 100644 index f0cf288853724c63857dfeaf4c4a9e9045e50373..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/int2bin.c +++ /dev/null @@ -1,36 +0,0 @@ -/********************************************** - * int2bin - * - * Conversion d'entier non signé en binaire - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - -#define MAXSIZE 33 // nombre maximum de bits+1 - -void print_bin(int num) { - int i; - int n=num; - char str[MAXSIZE]; - i=MAXSIZE; - while (--i>=0) { - str[i] = n & 1 ? '1' : '0'; - n >>= 1; - } - printf("La valeur de %d en hexadécimal est %x et en binaire : %s\n",num,num,str); - -} - -int main(int argc, char *argv[]) { - - int n=7654321; - print_bin(n); - print_bin(123); - print_bin(987654321); - - return(EXIT_SUCCESS); -} - -// inspiré de http://stackoverflow.com/questions/111928/is-there-a-printf-converter-to-print-in-binary-format diff --git a/Theorie/C/S2-src/num.c b/Theorie/C/S2-src/num.c deleted file mode 100644 index d0f045decb10c5e20191f04f0b22e96da13525c2..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/num.c +++ /dev/null @@ -1,24 +0,0 @@ -/*********************************************** - * num - * - * Déclaration de nombres - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) -{ - ///AAA - - int i; - i = 123; // décimal - i = 0x7b; // hexadécimal - i = 0173; // octal !! - // i = 0b1111011; // binaire, seulement certains compilateurs - - ///BBB - - return EXIT_SUCCESS; -} diff --git a/Theorie/C/S2-src/octal.c b/Theorie/C/S2-src/octal.c deleted file mode 100644 index b2796c9659f5e477b0693577e47652ae64a8bec2..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/octal.c +++ /dev/null @@ -1,27 +0,0 @@ -/*********************************************** - * octal - * - * Exemple d'erreur avec les nombres en octal - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) -{ - - ///AAA - - int i, j; - i = 65; // décimal - j = 065; // octal !!! - if (i == j) - printf("%d et %d sont égaux\n", i, j); - else - printf("%d et %d sont différents\n", i, j); - - ///BBB - - return EXIT_SUCCESS; -} diff --git a/Theorie/C/S2-src/perf.c b/Theorie/C/S2-src/perf.c deleted file mode 100644 index a31da934037b771956cf3979fcec0aa30e8e76ef..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/perf.c +++ /dev/null @@ -1,53 +0,0 @@ -/*********************************************** - * perf.c - * - * Mesure de temps de calcul via gettimeofday - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <sys/time.h> - -/* Return t2-t1 in microseconds */ -long timeval_diff(struct timeval *t2, struct timeval *t1) -{ - long diff = (t2->tv_usec + 1000000 * t2->tv_sec) - (t1->tv_usec + 1000000 * t1->tv_sec); - return (diff); -} -// n : number of iterations of the loop -void compute(int n) { - // long computation - double sum=0; - int i; - for(i=0;i<n;i++) { - sum=sum+i; - } -} - -int main(int argc, char *argv[]) -{ - struct timeval tvStart, tvEnd; - int err; - int num; // number of operations for compute - if(argc!=2) - exit(EXIT_FAILURE); - else - num=atoi(argv[1]); - - err=gettimeofday(&tvStart, NULL); - if(err!=0) - exit(EXIT_FAILURE); - - // long computation - compute(num); - - err=gettimeofday(&tvEnd, NULL); - if(err!=0) - exit(EXIT_FAILURE); - - printf("Duration : %ld microseconds\n", timeval_diff(&tvEnd, &tvStart)); - - return(EXIT_SUCCESS); -} - diff --git a/Theorie/C/S2-src/ptr.c b/Theorie/C/S2-src/ptr.c deleted file mode 100644 index 1e02c8fe1bd24418e7a238fc206c17df91fc66ad..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/ptr.c +++ /dev/null @@ -1,28 +0,0 @@ -/*********************************************** - * ptr - * - * Programme d'exemple d'utilisation de pointeurs - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) { - - ///AAA - - int i = 1252; - char str[] = "sinf1252"; - char c = 'c'; - - printf("i vaut %d, occupe %ld bytes et est stocké à l'adresse : %p\n", - i, sizeof(i), &i); - printf("c vaut %c, occupe %ld bytes et est stocké à l'adresse : %p\n", - c, sizeof(c), &c); - printf("str contient \"%s\" et est stocké à partir de l'adresse : %p\n", - str, &str); - - ///BBB - return EXIT_SUCCESS; -} diff --git a/Theorie/C/S2-src/ptr.out b/Theorie/C/S2-src/ptr.out deleted file mode 100644 index a4ade1396ffc919267443e148d49a006958ab8a1..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/ptr.out +++ /dev/null @@ -1,3 +0,0 @@ -i vaut 1252, occupe 4 bytes et est stocké à l'adresse : 0x7fff89f99cbc -c vaut c, occupe 1 bytes et est stocké à l'adresse : 0x7fff89f99caf -str contient "sinf1252" et est stocké à partir de l'adresse : 0x7fff89f99cb0 diff --git a/Theorie/C/S2-src/ptrchar.c b/Theorie/C/S2-src/ptrchar.c deleted file mode 100644 index ce253e2f81fc1c80e041b526da00d805fc0992d7..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/ptrchar.c +++ /dev/null @@ -1,34 +0,0 @@ -/*********************************************** - * ptrchar - * - * Programme d'exemple d'utilisation de pointeurs - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -int main(int argc, char *argv[]) { - - ///AAA - char c='Z'; - char str[]="sinf1252"; - char *str_ptr=NULL; - int i; - - str_ptr=&c; - printf("c vaut %c et est stocké à l'adresse : %p\n",c,&c); - printf("*str_ptr vaut %p et pointe vers %c\n",str_ptr,*(str_ptr)); - str_ptr=str; // équivaut à str_ptr=&(str[0]); - printf("après str_ptr=str[];\n"); - printf("*str_ptr vaut %p et pointe vers %c\n",str_ptr,*(str_ptr)); - printf("Contenu du tableau\n"); - for(i=0;i<strlen(str);i++) { - printf("str[%d]=%c et *(str_ptr+%d) contient %c\n",i,str[i],i,*(str_ptr+i)); - } - - - ///BBB - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S2-src/ptrex.c b/Theorie/C/S2-src/ptrex.c deleted file mode 100644 index 7b7cbb6372b0435ac9a92569188033451d298337..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/ptrex.c +++ /dev/null @@ -1,33 +0,0 @@ -/*********************************************** - * ptrex.c - * - * Programme d'exemple d'utilisation de pointeurs - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -int main(int argc, char *argv[]) { - - ///AAA - - int i = 1; // entier - int *ptr_i; // pointeur vers un entier - char str[] = "Unix"; - char *s; // pointeur vers un char - - ptr_i = &i; - printf("valeur de i : %d, valeur pointée par ptr_i : %d\n", i, *ptr_i); - *ptr_i = *ptr_i + 1252; - printf("valeur de i : %d, valeur pointée par ptr_i : %d\n", i, *ptr_i); - s = str; - for (i = 0; i < strlen(str); i++){ - printf("valeur de str[%d] : %c, valeur pointée par *(s+%d) : %c\n", - i, str[i], i, *(s+i)); - } - - ///BBB - return EXIT_SUCCESS; -} diff --git a/Theorie/C/S2-src/ptrex.out b/Theorie/C/S2-src/ptrex.out deleted file mode 100644 index 43314a5863d5a297306b4d406f22bc75cc79afa1..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/ptrex.out +++ /dev/null @@ -1,6 +0,0 @@ -valeur de i : 1, valeur pointée par ptr_i : 1 -valeur de i : 1253, valeur pointée par ptr_i : 1253 -valeur de str[0] : U, valeur pointée par *(s+0) : U -valeur de str[1] : n, valeur pointée par *(s+1) : n -valeur de str[2] : i, valeur pointée par *(s+2) : i -valeur de str[3] : x, valeur pointée par *(s+3) : x diff --git a/Theorie/C/S2-src/random.c b/Theorie/C/S2-src/random.c deleted file mode 100644 index 51a211f80a795a4ed2c328969ecf2604cc06ba37..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/random.c +++ /dev/null @@ -1,29 +0,0 @@ -/*********************************************** - * random - * - * Utilisation de nombres aléatoires - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) { - - ///AAA - - long int r; - int i; - int pair=0; - unsigned int seed=1252; // semence initiale - srandom(seed); - for(i=0;i<10000;i++) { - r=random(); - if (r%2==0) - pair++; - } - printf("%d nombres pairs ont été générés\n",pair); - ///BBB - return(EXIT_SUCCESS); -} - diff --git a/Theorie/C/S2-src/short.c b/Theorie/C/S2-src/short.c deleted file mode 100644 index f7452beab3cc1923aaae496e3776fadd53162994..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/short.c +++ /dev/null @@ -1,34 +0,0 @@ -/*********************************************** - * short - * - * Overflow sur les shorts - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) -{ - ///AAA - - short int i = 1; - unsigned short j = 1; - int n; - - printf("\nPuissances de 5 en notation signée\n"); - for (n = 1; n < 10; n++) { - i = i * 5; - printf("5^%d=%d\n", n, i); - } - - printf("\nPuissances de 10 en notation non signée\n"); - for (n = 1; n < 10; n++) { - j = j * 10; - printf("10^%d=%d\n", n, j); - } - - ///BBB - - return EXIT_SUCCESS; -} diff --git a/Theorie/C/S2-src/short.out b/Theorie/C/S2-src/short.out deleted file mode 100644 index eb18f95164070ca249dba78e92402d38223be12e..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/short.out +++ /dev/null @@ -1,22 +0,0 @@ - -Puissances de 5 en notation signée -5^1=5 -5^2=25 -5^3=125 -5^4=625 -5^5=3125 -5^6=15625 -5^7=12589 -5^8=-2591 -5^9=-12955 - -Puissances de 10 en notation non signée -10^1=10 -10^2=100 -10^3=1000 -10^4=10000 -10^5=34464 -10^6=16960 -10^7=38528 -10^8=57600 -10^9=51712 diff --git a/Theorie/C/S2-src/sizeof.c b/Theorie/C/S2-src/sizeof.c deleted file mode 100644 index 1f604959c96f3b7e25265f9ce7e452a8b2d99969..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/sizeof.c +++ /dev/null @@ -1,33 +0,0 @@ -/********************************************** - * sizeof - * - * Programme d'exemple d'utilisation de sizeof - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) { - - ///AAA - - printf("Type\t\t\tTaille\n"); - printf("\n"); - printf("char\t\t\t%ld octet(s)\n",sizeof(char)); - printf("unsigned char\t\t%ld octet(s)\n",sizeof(unsigned char)); - printf("short\t\t\t%ld octet(s)\n",sizeof(short)); - printf("unsigned short\t\t%ld octet(s)\n",sizeof(unsigned short)); - printf("int\t\t\t%ld octet(s)\n",sizeof(int)); - printf("unsigned int\t\t%ld octet(s)\n",sizeof(unsigned int)); - printf("long\t\t\t%ld octet(s)\n",sizeof(long)); - printf("unsigned long\t\t%ld octet(s)\n",sizeof(unsigned long)); - printf("long long\t\t%ld octet(s)\n",sizeof(long long)); - printf("unsigned long long\t%ld octet(s)\n",sizeof(unsigned long long)); - printf("float\t\t\t%ld octet(s)\n",sizeof(float)); - printf("double\t\t\t%ld octet(s)\n",sizeof(double)); - printf("long double\t\t%ld octet(s)\n",sizeof(long double)); - - ///BBB - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S2-src/sizeofptr.c b/Theorie/C/S2-src/sizeofptr.c deleted file mode 100644 index 29a2b7cdfcdadc71103bf67fe0f117c39bab687f..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/sizeofptr.c +++ /dev/null @@ -1,32 +0,0 @@ -/********************************************** - * sizeofptr - * - * Programme d'exemple d'utilisation de sizeof - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) { - - - printf("Type\t\t\tTaille\n"); - printf("\n"); - printf("char *\t\t\t%ld octet(s)\n",sizeof(char *)); - printf("unsigned char *\t\t%ld octet(s)\n",sizeof(unsigned char *)); - printf("short *\t\t\t%ld octet(s)\n",sizeof(short *)); - printf("unsigned short *\t%ld octet(s)\n",sizeof(unsigned short *)); - printf("int *\t\t\t%ld octet(s)\n",sizeof(int *)); - printf("unsigned int *\t\t%ld octet(s)\n",sizeof(unsigned int *)); - printf("long *\t\t\t%ld octet(s)\n",sizeof(long *)); - printf("unsigned long *\t\t%ld octet(s)\n",sizeof(unsigned long *)); - printf("long long *\t\t%ld octet(s)\n",sizeof(long long *)); - printf("unsigned long long *\t%ld octet(s)\n",sizeof(unsigned long long *)); - printf("float *\t\t\t%ld octet(s)\n",sizeof(float *)); - printf("double *\t\t%ld octet(s)\n",sizeof(double *)); - printf("long double *\t\t%ld octet(s)\n",sizeof(long double *)); - - ///BBB - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S2-src/strlen.c b/Theorie/C/S2-src/strlen.c deleted file mode 100644 index a623e5b6ddaa0e85a280872e674c821bcab382bc..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/strlen.c +++ /dev/null @@ -1,39 +0,0 @@ -/*********************************************** - * strlen.c - * - * Initialisation de chaînes de caractères - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - - -///AAA - -int length(char str[]) -{ - int i = 0; - while (str[i] != 0) {// '\0' et 0 sont égaux - i++; - } - return i; -} - -///BBB - -int main(int argc, char *argv[]) -{ - - int i; - char name1[] = "str"; - // char name2[] = "SINF1252"; - - printf("Longueur de name1 [%s] : %d\n", name1, length(name1)); - for (i = 0; i < length(str); i++) { - printf("%c", name1[i]); - } - - return EXIT_SUCCESS; -} - diff --git a/Theorie/C/S2-src/strlenptr.c b/Theorie/C/S2-src/strlenptr.c deleted file mode 100644 index 7030859576476982b386f674b81805cec6bae7c8..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/strlenptr.c +++ /dev/null @@ -1,36 +0,0 @@ -/*********************************************** - * strlen.c - * - * Calcul de longueur de chaînes avec pointeurs - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - -///AAA - -int length(char *s) -{ - int i = 0; - while (*(s+i) != '\0') - i++; - return i; -} - -///BBB - -int main(int argc, char *argv[]) -{ - int i; - char name1[] = "str"; - // char name2[] = "SINF1252"; - - printf("Longueur de name1 [%s] : %d\n", name1, length(name1)); - for (i = 0; i < 10; i++) { - printf("%c", name1[i]); - } - - return EXIT_SUCCESS; -} - diff --git a/Theorie/C/S2-src/struct.c b/Theorie/C/S2-src/struct.c deleted file mode 100644 index dac885b590fce623c5e37e4cda0142ecbdc39972..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/struct.c +++ /dev/null @@ -1,103 +0,0 @@ -/*********************************************** - * struct.c - * - * Programme d'exemple de structures - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -///AAA - -// structure pour stocker une coordonnée 3D -struct coord { - int x; - int y; - int z; -}; - -struct coord point = {1, 2, 3}; -struct coord p; - -// structure pour stocker une fraction -struct fraction { - int numerator; - int denominator; -}; - -struct fraction demi = {1, 2}; -struct fraction f; - -// structure pour représenter un étudiant -struct student { - int matricule; - char prenom[20]; - char nom[30]; -}; - -struct student s = {1, "Linus", "Torvalds"}; - -///BBB - -///EEE -struct fraction init(int num, int den) -{ - struct fraction f; - f.numerator = num; - f.denominator = den; - return f; -} - -int equal(struct fraction f1, struct fraction f2) -{ - return ((f1.numerator == f2.numerator) - && (f1.denominator == f2.denominator)); -} - -int equalptr(struct fraction *f1, struct fraction *f2) -{ - return ((f1->numerator==f2->numerator) - && (f1->denominator==f2->denominator)); -} - -void initptr(struct fraction *f, int num, int den) -{ - f->numerator = num; - f->denominator = den; -} -///FFF - -int main(int argc, char *argv[]) -{ - - int c[3] = {0, 0, 0}; - -///CCC - -point.x = 1; -point.y = 2; -point.z = 3; - -///DDD - -///GGG - -struct fraction quart; -struct fraction tiers; -quart = init(1, 4); -initptr(&tiers, 1, 3); -printf("equal(tiers,quart)=%d\n", equal(tiers, quart)); -printf("equalptr(&tiers,&quart)=%d\n", equalptr(&tiers, &quart)); - -///HHH - - f.numerator=1; - f.denominator=4; - printf("%c\n",s.prenom[2]); - printf("sizeof int[3]=%ld, sizeof coord=%ld\n",sizeof(c),sizeof(struct coord)); - printf("sizeof student : %ld\n",sizeof(s)); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S2-src/structptr.c b/Theorie/C/S2-src/structptr.c deleted file mode 100644 index 59b93ebda18435e2ab1eb0d91204b9326039073e..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/structptr.c +++ /dev/null @@ -1,37 +0,0 @@ -/*********************************************** - * structptr.c - * - * Programme d'exemple de pointeurs vers des - * structures - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -int main(int argc, char *argv[]) -{ - - struct fraction { - int num; - int den; - }; - -///AAA -struct fraction demi, quart; -struct fraction *demi_ptr; -struct fraction *quart_ptr; - -demi_ptr = &demi; -quart_ptr = &quart; - -(*demi_ptr).num = 1; -(*demi_ptr).den = 2; - -quart_ptr->num = 1; -quart_ptr->den = 4; -///BBB - - return EXIT_SUCCESS; -} diff --git a/Theorie/C/S2-src/time.c b/Theorie/C/S2-src/time.c deleted file mode 100644 index 3b082a83db74d7d7a100510ebb54995d832ddab6..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/time.c +++ /dev/null @@ -1,69 +0,0 @@ -/*********************************************** - * struct.c - * - * Programme d'exemple de structures - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -///AAA - -// structure pour stocker une coordonnée 3D -struct coord { - int x; - int y; - int z; -} ; - -struct coord origin={1,2,3}; -struct coord p; - -// structure pour stocker une fraction -struct fraction { - double numerator; - double denominator; -}; - -struct fraction demi={1.0,2.0}; -struct fraction f; - -// structure pour représenter un étudiant -struct student { - int matricule; - char prenom[20]; - char nom[30]; -}; - -struct student s={1,"Linux","Torvalds"}; - -///BBB - -///EEE - -int equal(struct fraction f1, struct fraction f2) { - return ( (f1.numerator==f2.numerator) && - (f1.denominator==f2.denominator) ); -} - -///FFF - -int main(int argc, char *argv[]) { - int c[3]={0,0,0}; - - ///CCC - origin.x=1; - origin.y=2; - origin.z=3; - ///DDD - - f.numerator=1; - f.denominator=4; - printf("%c\n",s.prenom[2]); - printf("sizeof int[3]=%ld, sizeof coord=%ld\n",sizeof(c),sizeof(struct coord)); - printf("sizeof student : %ld\n",sizeof(s)); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S2-src/toupper.c b/Theorie/C/S2-src/toupper.c deleted file mode 100644 index cf87bc40a7795e9dc56e9fcedc28f523570e28a3..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/toupper.c +++ /dev/null @@ -1,31 +0,0 @@ -/*********************************************** - * toupper.c - * - * Conversion de caractères - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - -///AAA - -// conversion de minuscules en majuscules -int toUpper(char c) { - if (c >= 'a' && c <= 'z') - return c + ('A' - 'a'); - else - return c; -} -///BBB - -int main(int argc, char *argv[]) -{ - - printf("%c\n",toUpper('g')); - printf("%c\n",toUpper('=')); - printf("%c\n",toUpper('Z')); - printf("%c\n",toUpper('x')); - - return EXIT_SUCCESS; -} diff --git a/Theorie/C/S2-src/typedef.c b/Theorie/C/S2-src/typedef.c deleted file mode 100644 index 988cd9dedbfc60e92b3ab19b60e9e36d2447e491..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/typedef.c +++ /dev/null @@ -1,37 +0,0 @@ -/*********************************************** - * typedef.c - * - * Programme d'exemple d'utilisation de typedef - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> - -///EEE -typedef unsigned int u_int_t; -typedef unsigned long u_long_t; -///FFF - -///CCC -typedef int * int_ptr; -typedef char * string; -///DDD - -///AAA -// structure pour stocker une fraction -typedef struct fraction { - double numerator; - double denominator; -} Fraction ; - -typedef int Entier; - -int main(int argc, char *argv[]) -{ - Fraction demi = {1, 2}; - Entier i = 2; - // ... - return EXIT_SUCCESS; -} -///BBB diff --git a/Theorie/C/S2-src/xor.c b/Theorie/C/S2-src/xor.c deleted file mode 100644 index 9466a8228fae60901803ac6d8651831afbfc5e46..0000000000000000000000000000000000000000 --- a/Theorie/C/S2-src/xor.c +++ /dev/null @@ -1,34 +0,0 @@ -/*********************************************** - * xor.c - * - * Programme d'exemple d'encryptage avec XOR - * - ***********************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -// affiche un message d'erreur -void usage(char *msg) -{ - fprintf(stderr,"Usage : %s\n",msg); - exit(EXIT_FAILURE); -} - -///AAA -int main(int argc, char* argv[]) -{ - if (argc != 2) - usage("ce programme prend une clé comme argument"); - - char *key = argv[1]; - char c; - int i = 0; - while (((c = getchar()) != EOF) && (i < strlen(key))) { - putchar(c ^ *(key + i)); - i++; - } - return EXIT_SUCCESS; -} -///BBB diff --git a/Theorie/C/S3-src/argv-env.c b/Theorie/C/S3-src/argv-env.c deleted file mode 100644 index 7800144572cd51b561dfecbcb55ec4d4f309e9bf..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/argv-env.c +++ /dev/null @@ -1,42 +0,0 @@ -/************************************** - * arg-env.c - * - * Arguments et variables d'environnement - * - **************************************/ - -///AAA -#include <stdio.h> -#include <stdlib.h> - -// affiche la valeur de la variable d'environnement var -void print_var(char *var) { - char *val=getenv(var); - if(val!=NULL) - printf("La variable %s a la valeur : %s\n",var,val); - else - printf("La variable %s n'a pas été assignée\n",var); -} - -int main(int argc, char *argv[]) { - - char *old_path=getenv("PATH"); - - print_var("PATH"); - - if(unsetenv("PATH")!=0) { - fprintf(stderr,"Erreur unsetenv\n"); - exit(EXIT_FAILURE); - } - - print_var("PATH"); - - if(setenv("PATH",old_path,1)!=0) { - fprintf(stderr,"Erreur setenv\n"); - exit(EXIT_FAILURE); - } - - print_var("PATH"); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S3-src/callocperf.c b/Theorie/C/S3-src/callocperf.c deleted file mode 100644 index 5707955a4e9a3bf6b30553bf121af6f107cd24ff..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/callocperf.c +++ /dev/null @@ -1,39 +0,0 @@ -/************************************** - * callocperf.c - * - * Programme mesurant les performances - * de calloc - * - **************************************/ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#define LOOP 2 - -void error(char *msg) { - fprintf(stderr,"Erreur :%s\n",msg); - exit(EXIT_FAILURE); -} - -int main(int argc, char *argv[]) { - int size=1; - if(argc==2) - size=atoi(argv[1]); - - for(int j=1;j<LOOP+1;j++) { - int *vector; - vector=(int *)calloc(size,sizeof(int)); - - int count=0; - for(int i=0;i<size;i++) { - if( *(vector+i)!=0) - count++; - else - *(vector+i)=j; - } - printf("Nombre d'entiers non initialisés à zéro : %d\n",count); - free(vector); - } - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S3-src/const.c b/Theorie/C/S3-src/const.c deleted file mode 100644 index ee0077524db848061a6294ec4a5dff3ebda2a0d6..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/const.c +++ /dev/null @@ -1,29 +0,0 @@ -/************************************** - * const.c - * - * Programme d'exemple de constantes - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -///AAA -// extrait de <math.h> -#define M_PI 3.14159265358979323846264338327950288; - -const double pi=3.14159265358979323846264338327950288; - -const struct fraction { - int num; - int denom; -} demi={1,2}; -///BBB -int main(int argc, char *argv[]) { - // demi.num=0; invalid - printf("%d/%d\n",demi.num,demi.denom); - printf("Adresse de pi :%p\n",&pi); - printf("Adresse de demi :%p\n",&demi); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S3-src/dataseg.c b/Theorie/C/S3-src/dataseg.c deleted file mode 100644 index 9f4cb34767e2ee3510068e0663ba3fed7ad98224..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/dataseg.c +++ /dev/null @@ -1,32 +0,0 @@ -/************************************** - * initvar.c - * - * Programme d'exemple sur le segment - * de données - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -///AAA -#define MSG_LEN 10 -int g; // initialisé par le compilateur -int g_init=1252; -const int un=1; -int tab[3]={1,2,3}; -int array[10000]; -char cours[]="SINF1252"; -char msg[MSG_LEN]; // initialisé par le compilateur - -int main(int argc, char *argv[]) { - int i; - printf("g est à l'adresse %p et initialisée à %d\n",&g,g); - printf("msg est à l'adresse %p contient les caractères :",msg); - for(i=0;i<MSG_LEN;i++) - printf(" %x",msg[i]); - printf("\n"); - printf("Cours est à l'adresse %p et contient : %s\n",&cours,cours); - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/C/S3-src/dataseg.out b/Theorie/C/S3-src/dataseg.out deleted file mode 100644 index 9a372e29ce61182f94e9cfcc47b7500e46f0b880..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/dataseg.out +++ /dev/null @@ -1,3 +0,0 @@ -g est à l'adresse 0x60aeac et initialisée à 0 -msg est à l'adresse 0x60aea0 contient les caractères : 0 0 0 0 0 0 0 0 0 0 -Cours est à l'adresse 0x601220 et contient : SINF1252 diff --git a/Theorie/C/S3-src/empty.c b/Theorie/C/S3-src/empty.c deleted file mode 100644 index 80fa49285f10109c0d13737be89f09262169e13a..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/empty.c +++ /dev/null @@ -1,17 +0,0 @@ -/************************************** - * static.c - * - * Programme d'exemple de variables static -éé - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) { - // affiche sur la sortie standard - printf("Hello, world!\n"); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S3-src/enum.c b/Theorie/C/S3-src/enum.c deleted file mode 100644 index 63b4776777d25f444678edb0609dd34aa7ff33f6..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/enum.c +++ /dev/null @@ -1,44 +0,0 @@ -/************************************** - * enum.c - * - * Programme d'exemple de enum - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -///AAA -// les jours de la semaine -typedef enum { - monday, tuesday, wednesday, thursday, friday, saturday, sunday - } day; - -// jeu de carte -typedef enum { - coeur, carreau, trefle, pique -} carte; - -// bits -typedef enum { - BITRESET = 0, - BITSET = 1 -} bit_t; - -///BBB - - -int main(int argc, char *argv[]) { - ///CCC - bit_t bit=BITRESET; - day jour=monday; - if(jour==saturday||jour==sunday) - printf("Congé\n"); - ///DDD - printf("jour: %d\n",jour); - printf("sizeof(day) %ld\n",sizeof(day)); - printf("sizeof(bit_t) %ld\n",sizeof(bit_t)); - - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S3-src/exhaust-stack.c b/Theorie/C/S3-src/exhaust-stack.c deleted file mode 100644 index c177bd4f88473ce2a61aa0c784f8cd4e61423936..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/exhaust-stack.c +++ /dev/null @@ -1,47 +0,0 @@ -/************************************** - * exhaust-stack.c - * - * Programme qui sature le stack - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <sys/resource.h> - -///AAA - -#define ARRAY_SIZE 10000 - -int sumn(int i) { - int array[ARRAY_SIZE]; - printf("Computing sumn(%d)\n",i); - for(int j=0;j<ARRAY_SIZE;j++){ - array[j]=i; - } - if(i>0) - return (i+sumn(i-1)); - else - return i; -} - -///BBB -int main(int argc, char *argv[]) { - int n; - if(argc==2) { - n=atoi(argv[1]); - } - else - n=5; - struct rlimit r; - - int err=getrlimit(RLIMIT_STACK,&r); - if(err!=0) { - printf("Error\n"); - return(EXIT_FAILURE); - } - printf("Softlimit %ld, hard limit %ld\n",(rlim_t) r.rlim_cur,(rlim_t)r.rlim_max); - printf("La somme des %d premiers entiers est : %d\n",n,sumn(n)); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S3-src/fact.c b/Theorie/C/S3-src/fact.c deleted file mode 100644 index 2ea01e9c3c44e7fa686d140e4029bbc9c7f000fd..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/fact.c +++ /dev/null @@ -1,82 +0,0 @@ -/************************************** - * fact.c - * - * Programme de calcul de factorielle - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> -///BBB -// retourne i*j -int times(int i, int j) { - int m; - m=i*j; - printf("\t[times(%d,%d)] : return(%d)\n",i,j,m); - return m; -} -// calcul récursif de factorielle -// n>0 -int fact(int n) { - printf("[fact(%d)]: Valeur de n:%d, adresse: %p\n",n,n,&n); - int f; - if(n==1) { - printf("[fact(%d)]: return(1)\n",n); - return(n); - } - printf("[fact(%d)]: appel à fact(%d)\n",n,n-1); - f=fact(n-1); - printf("[fact(%d)]: calcul de times(%d,%d)\n",n,n,f); - f=times(n,f); - printf("[fact(%d)]: return(%d)\n",n,f); - return(f); -} - -void compute() { - int nombre=3; - int f; - printf("La fonction fact est à l'adresse : %p\n",fact); - printf("La fonction times est à l'adresse : %p\n",times); - printf("La variable nombre vaut %d et est à l'adresse %p\n",nombre,&nombre); - f=fact(nombre); - printf("La factorielle de %d vaut %d\n",nombre,f); -} -///AAA - - -#define MSG_LEN 80 -char msg[MSG_LEN]; -float matrix1[4]; -float matrix3[2]={1.3,2.4}; -struct fraction { - float den; - float num; -} fract; -const int nombre=7; - -int max(int i, int j) { - if(i>j) - return(i); - else - return(j); -} - -int main(int argc, char *argv[]) { - - int f=1252; // variable locale - - printf("La variable nombre est à l'adresse : %p\n",(void *) &nombre); - printf("Le tableau msg est à l'adresse : %p\n",(void *)msg); - printf("La variable locale f est à l'adresse : %p\n",(void *) &f); - - printf("La fonction main est à l'adresse : %p\n",main); - printf("La fonction max est à l'adresse : %p\n",max); - - /// ... - ///BBB - printf("///FACT\n"); - compute(); - - return(EXIT_SUCCESS); -} - diff --git a/Theorie/C/S3-src/fact.out b/Theorie/C/S3-src/fact.out deleted file mode 100644 index c2698ff8d11222fd32a4b8b1c39b581a87a69a6e..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/fact.out +++ /dev/null @@ -1,22 +0,0 @@ -La variable nombre est à l'adresse : 0x100000e68 -Le tableau msg est à l'adresse : 0x1000010a0 -La variable locale f est à l'adresse : 0x7fff5fbfe1dc -La fonction main est à l'adresse : 0x100000b6b -La fonction max est à l'adresse : 0x100000b46 -///FACT -La fonction fact est à l'adresse : 0x100000a0f -La fonction times est à l'adresse : 0x1000009d8 -La variable nombre vaut 3 et est à l'adresse 0x7fff5fbfe1ac -[fact(3)]: Valeur de n:3, adresse: 0x7fff5fbfe17c -[fact(3)]: appel à fact(2) -[fact(2)]: Valeur de n:2, adresse: 0x7fff5fbfe14c -[fact(2)]: appel à fact(1) -[fact(1)]: Valeur de n:1, adresse: 0x7fff5fbfe11c -[fact(1)]: return(1) -[fact(2)]: calcul de times(2,1) - [times(2,1)] : return(2) -[fact(2)]: return(2) -[fact(3)]: calcul de times(3,2) - [times(3,2)] : return(6) -[fact(3)]: return(6) -La factorielle de 3 vaut 6 diff --git a/Theorie/C/S3-src/getpid.c b/Theorie/C/S3-src/getpid.c deleted file mode 100644 index 916a5945629a6a9a86c87c49430054703d7612aa..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/getpid.c +++ /dev/null @@ -1,28 +0,0 @@ -/************************************** - * getpid.c - * - * Programme d'exemple pour getpid - * - **************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -int main(int argc, char *argv[]) { - - unsigned int sec=30; - int pid=(int) getpid(); - - printf("Processus : %d\n",pid); - printf("[pid=%d] Sleep : %d secondes\n",pid, sec); - sec=sleep(sec); - if(sec==0) { - printf("[pid=%d] Fin du processus\n",pid ); - return(EXIT_SUCCESS); - } - else { - printf("[pid=%d] Interrompu alors qu'il restait %d secondes\n",pid,sec); - return(EXIT_FAILURE); - } -} diff --git a/Theorie/C/S3-src/initvar.c b/Theorie/C/S3-src/initvar.c deleted file mode 100644 index 80d027c38be42f74e0b004414524dfb60afe2af5..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/initvar.c +++ /dev/null @@ -1,50 +0,0 @@ -/************************************** - * initvar.c - * - * Programme d'exemple sur l'initialisation - * des variables - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -///AAA - -#define ARRAY_SIZE 1000 - -// initialise un tableau local -void init(void) { - long a[ARRAY_SIZE]; - for(int i=0;i<ARRAY_SIZE;i++) { - a[i]=i; - } -} - -// retourne la somme des éléments -// d'un tableau local -long read(void) { - long b[ARRAY_SIZE]; - long sum=0; - for(int i=0;i<ARRAY_SIZE;i++) { - sum+=b[i]; - } - return sum; -} - - -///BBB -int main(int argc, char *argv[]) { - unsigned int n=5; - - if(argc==2) { - n=atoi(argv[1]); - } - - ///CCC - printf("Résultat de read() avant init(): %ld\n",read()); - init(); - printf("Résultat de read() après init() : %ld\n",read()); - ///DDD - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S3-src/initvar.out b/Theorie/C/S3-src/initvar.out deleted file mode 100644 index c54a887c8ffc40c19e46a3545f4f8dbea7461dd3..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/initvar.out +++ /dev/null @@ -1,2 +0,0 @@ -Résultat de read() avant init(): 7392321044987950589 -Résultat de read() après init() : 499500 diff --git a/Theorie/C/S3-src/malloc.c b/Theorie/C/S3-src/malloc.c deleted file mode 100644 index 3474c744e2f24fa3c9c20641a48dcb1d8360125c..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/malloc.c +++ /dev/null @@ -1,55 +0,0 @@ -/************************************** - * malloc.c - * - * Programme illustrant malloc - * - **************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - - -typedef struct fraction { - int num; - int den; -} Fraction; - -void error(char *msg) { - fprintf(stderr,"Erreur :%s\n",msg); - exit(EXIT_FAILURE); -} - -int main(int argc, char *argv[]) { - int size=1; - if(argc==2) - size=atoi(argv[1]); - - char * string; - printf("Valeur du pointeur string avant malloc : %p\n",string); - string=(char *) malloc((size+1)*sizeof(char)); - if(string==NULL) - error("malloc(string)"); - - printf("Valeur du pointeur string après malloc : %p\n",string); - int *vector; - vector=(int *)malloc(size*sizeof(int)); - if(vector==NULL) - error("malloc(vector)"); - - Fraction * fract_vect; - fract_vect=(Fraction *) malloc(size*sizeof(Fraction)); - if(fract_vect==NULL) - error("malloc(fract_vect)"); - - free(string); - printf("Valeur du pointeur string après free : %p\n",string); - string=NULL; - free(vector); - vector=NULL; - free(fract_vect); - fract_vect=NULL; - - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/C/S3-src/malloc.out b/Theorie/C/S3-src/malloc.out deleted file mode 100644 index 44c87d400d19e800815c1417e2ad5f8afbbc403a..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/malloc.out +++ /dev/null @@ -1,3 +0,0 @@ -Valeur du pointeur string avant malloc : 0x7fff5fbfe1d8 -Valeur du pointeur string après malloc : 0x100100080 -Valeur du pointeur string après free : 0x100100080 diff --git a/Theorie/C/S3-src/mallocinit.c b/Theorie/C/S3-src/mallocinit.c deleted file mode 100644 index 645ac40c80d69e26f5942c925473770b2fa402cf..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/mallocinit.c +++ /dev/null @@ -1,34 +0,0 @@ -/************************************** - * mallocinit.c - * - * Malloc et les données non-initialisées - * - **************************************/ -#include <stdio.h> -#include <stdlib.h> -///AAA -#define LEN 1024 - -int main(int argc, char *argv[]) { - - int *v1; - int *v2; - int sum=0; - v1=(int *)malloc(sizeof(int)*LEN); - for(int i=0;i<LEN;i++) { - sum+=*(v1+i); - *(v1+i)=1252; - } - printf("Somme des éléments de v1 : %d\n", sum); - sum=0; - free(v1); - v2=(int *)malloc(sizeof(int)*LEN); - for(int i=0;i<LEN;i++) { - sum+=*(v2+i); - } - - printf("Somme des éléments de v2 : %d\n", sum); - free(v2); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S3-src/mallocinit.out b/Theorie/C/S3-src/mallocinit.out deleted file mode 100644 index 14d3a6866425c4b8c15441d8a9126042e94fbf6b..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/mallocinit.out +++ /dev/null @@ -1,2 +0,0 @@ -Somme des éléments de v1 : 0 -Somme des éléments de v2 : 1282048 diff --git a/Theorie/C/S3-src/mallocperf.c b/Theorie/C/S3-src/mallocperf.c deleted file mode 100644 index 291a614ef74b22ed36ac4ce39e4e2165f3c58f13..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/mallocperf.c +++ /dev/null @@ -1,57 +0,0 @@ -/************************************** - * mallocperf.c - * - * Programme mesurant les performances - * de malloc - * - **************************************/ -#include <stdio.h> -#include <stdlib.h> -#include <sys/time.h> - - -#define LOOP 10 -#define SIZE 1000000000 - -void error(char *msg) { - fprintf(stderr,"Erreur :%s\n",msg); - exit(EXIT_FAILURE); -} - -/* Return t2-t1 in microseconds */ -long timeval_diff(struct timeval *t2, struct timeval *t1) -{ - long diff = (t2->tv_usec + 1000000 * t2->tv_sec) - (t1->tv_usec + 1000000 * t1->tv_sec); - return (diff); -} - -int main(int argc, char *argv[]) { - - int *vector; - long mesures[LOOP], sum; - - struct timeval tvStart, tvEnd; - int err; - - vector=(int *)malloc(SIZE*sizeof(int)); - free(vector); - - for(int i=0;i<LOOP+1;i++) { - err=gettimeofday(&tvStart, NULL); - if(err!=0) - exit(EXIT_FAILURE); - - vector=(int *)calloc(SIZE,sizeof(int)); - //vector=(int *)malloc(SIZE*sizeof(int)); - err=gettimeofday(&tvEnd, NULL); - if(err!=0) - exit(EXIT_FAILURE); - - mesures[i]=timeval_diff(&tvEnd, &tvStart); - sum+=mesures[i]; - free(vector); - } - printf("Durée moyenne : %ld\n",sum/LOOP); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S3-src/nofree.c b/Theorie/C/S3-src/nofree.c deleted file mode 100644 index 2308e6dd424ae16df84572eca4b4d8a880881c81..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/nofree.c +++ /dev/null @@ -1,21 +0,0 @@ -/************************************** - * nofree.c - * - * malloc sans free - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> -///AAA -#define LEN 1024 -int main(int argc, char *argv[]) { - - char *str=(char *) malloc(sizeof(char)*LEN); - for(int i=0;i<LEN-1;i++) { - *(str+i)='A'; - } - *(str+LEN)='\0'; // fin de chaîne - return(EXIT_SUCCESS); -} - diff --git a/Theorie/C/S3-src/portee.c b/Theorie/C/S3-src/portee.c deleted file mode 100644 index 12ed7d94290b12b052c4e85cb7aa191cce5f3bbd..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/portee.c +++ /dev/null @@ -1,62 +0,0 @@ -/************************************** - * portee.c - * - * Programme d'exemple pour la portée de - * variables - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -///AAA - -int g1; -int g2=1; - -void f(int i) { - int loc; //def1a - int loc2=2; //def2a - int g2=-i*i; - g1++; - - printf("[f-%da] \t\t %d \t %d \t %d \t %d\n",i,g1,g2,loc,loc2); - loc=i*i; - g1++; - g2++; - printf("[f-%db] \t\t %d \t %d \t %d \t %d\n",i,g1,g2,loc,loc2); - -} - - -int main(int argc, char *argv[]) { - int loc; //def1b - int loc2=1; //def2b - - printf("Valeurs de : \t g1 \t g2\t loc\t loc2\n"); - printf("===================================================\n"); - - printf("[main1] \t %d \t %d \t %d \t %d\n",g1,g2,loc,loc2); - - loc=1252; - loc2=1234; - g1=g1+1; - g1=g1+2; - - printf("[main2] \t %d \t %d \t %d \t %d\n",g1,g2,loc,loc2); - - for(int i=1;i<3;i++) { - int loc=i; //def1c - int g2=-i; - loc++; - g1=g1*2; - f(i); - printf("[main-for-%d] \t %d \t %d \t %d \t %d\n",i,g1,g2,loc,loc2); - } - f(7); - g1=g1*3; - g2=g2+2; - printf("[main3] \t %d \t %d \t %d \t %d\n",g1,g2,loc,loc2); - - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/C/S3-src/portee.out b/Theorie/C/S3-src/portee.out deleted file mode 100644 index c2034d21514472921f1e95e0288e6fdf51c620f2..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/portee.out +++ /dev/null @@ -1,13 +0,0 @@ -Valeurs de : g1 g2 loc loc2 -=================================================== -[main1] 0 1 0 1 -[main2] 3 1 1252 1234 -[f-1a] 7 -1 0 2 -[f-1b] 8 0 1 2 -[main-for-1] 8 -1 2 1234 -[f-2a] 17 -4 0 2 -[f-2b] 18 -3 4 2 -[main-for-2] 18 -2 3 1234 -[f-7a] 19 -49 0 2 -[f-7b] 20 -48 49 2 -[main3] 60 3 1252 1234 diff --git a/Theorie/C/S3-src/stack.c b/Theorie/C/S3-src/stack.c deleted file mode 100644 index db62dc7800b84962af464eca7bd6d491785f0bfb..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/stack.c +++ /dev/null @@ -1,96 +0,0 @@ -/************************************** - * stack.c - * - * Programme d'exemple implémentant un stack comme structure - * chaînée - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -typedef struct fraction_t { - int num; - int den; -} fraction; - -///AAA -typedef struct node_t -{ - struct fraction_t *data; - struct node_t *next; -} node; - -struct node_t *stack; // sommet de la pile - -// ajoute un élément au sommet de la pile -void push(struct fraction_t *f) -{ - struct node_t *n; - n=(struct node_t *)malloc(sizeof(struct node_t)); - if(n==NULL) - exit(EXIT_FAILURE); - n->data = f; - n->next = stack; - stack = n; -} -// retire l'élément au sommet de la pile -struct fraction_t * pop() -{ - if(stack==NULL) - return NULL; - // else - struct fraction_t *r; - struct node_t *removed=stack; - r=stack->data; - stack=stack->next; - free(removed); - return (r); -} - -///BBB - -// affiche le contenu de la pile -void display() -{ - struct node_t *t; - t = stack; - while(t!=NULL) { - if(t->data!=NULL) { - printf("Item at addr %p : Fraction %d/%d Next %p\n",t,t->data->num,t->data->den,t->next); - } - else { - printf("Bas du stack %p\n",t); - } - t=t->next; - } -} - -// exemple -int main(int argc, char *argv[]) { - - struct fraction_t demi={1,2}; - struct fraction_t tiers={1,3}; - struct fraction_t quart={1,4}; - struct fraction_t zero={0,1}; - - // initialisation - stack = (struct node_t *)malloc(sizeof(struct node_t)); - stack->next=NULL; - stack->data=NULL; - - display(); - push(&zero); - display(); - push(&demi); - push(&tiers); - push(&quart); - display(); - - struct fraction_t *f=pop(); - if(f!=NULL) - printf("Popped : %d/%d\n",f->num,f->den); - - return(EXIT_SUCCESS); -} -///CCC diff --git a/Theorie/C/S3-src/stack.out b/Theorie/C/S3-src/stack.out deleted file mode 100644 index a3b08610b0c5642b458c409301b0bf3012021999..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/stack.out +++ /dev/null @@ -1,9 +0,0 @@ -Bas du stack 0x100100080 -Item at addr 0x100100090 : Fraction 0/1 Next 0x100100080 -Bas du stack 0x100100080 -Item at addr 0x1001000c0 : Fraction 1/4 Next 0x1001000b0 -Item at addr 0x1001000b0 : Fraction 1/3 Next 0x1001000a0 -Item at addr 0x1001000a0 : Fraction 1/2 Next 0x100100090 -Item at addr 0x100100090 : Fraction 0/1 Next 0x100100080 -Bas du stack 0x100100080 -Popped : 1/4 diff --git a/Theorie/C/S3-src/static.c b/Theorie/C/S3-src/static.c deleted file mode 100644 index 5d369ef57c81805549e8d8c6d4ebcaf08d5ba7a0..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/static.c +++ /dev/null @@ -1,24 +0,0 @@ -/************************************** - * static.c - * - * Programme d'exemple d'utilisation de static - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - - -void f(int i) { - static int sum; - -} - -int main(int argc, char *argv[]) { - - f(1); - - f(2); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S3-src/strcat.c b/Theorie/C/S3-src/strcat.c deleted file mode 100644 index f1a785048b18706b070b983c04ccb3be8fcafd69..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/strcat.c +++ /dev/null @@ -1,56 +0,0 @@ -/************************************** - * concat.c - * - * Programme d'exemple pour concaténer - * deux chaînes de caractères - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -#define SIZE 4 - -int * init_vector(int length, int val) { - int *ret=malloc(length*sizeof(int)); - for(int i=0;i<length;i++) { - *(ret+i)=val; - } - return(ret); -} - -int *unit_matrix(int length) { - int *r=malloc(length*length*sizeof(int)); - for(int i=0;i<length;i++) { - for(int j=0;j<length;j++) { - if(i==j) { - *(r+(i*length)+j)=1; - } - else { - *(r+(i*length)+j)=0; - } - } - } - return (r); -} - -int main(int argc, char *argv[]) { - int *v; - int *m; - v=init_vector(SIZE,1252); - m=unit_matrix(SIZE); - for(int i=0;i<SIZE;i++) { - printf(" v[%d]=%d",i,*(v+i)); - } - printf("\n"); - for(int i=0;i<SIZE;i++) { - for(int j=0;j<SIZE;j++) { - printf(" m[%d,%d]=%d",i,j,*(m+(i*SIZE)+j)); - } - printf("\n"); - } - printf("\n"); - free(v); - free(m); - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S3-src/strcpy.c b/Theorie/C/S3-src/strcpy.c deleted file mode 100644 index c24c942b69aa6eb22145f49239beb62b5ce87d09..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/strcpy.c +++ /dev/null @@ -1,46 +0,0 @@ -/************************************** - * strcpy.c - * - * Programme d'exemple pour strcpy - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> -///AAA -#include <string.h> - -char *duplicate(char * str) { - int i; - size_t len=strlen(str); - char *ptr=(char *)malloc(sizeof(char)*(len+1)); - if(ptr!=NULL) { - for(i=0;i<len+1;i++) { - *(ptr+i)=*(str+i); - } - } - return ptr; -} -///BBB -char *duplicate2(char * str) { - int i; - size_t len=strlen(str); - char str2[len+1]; - for(i=0;i<len+1;i++) { - str2[i]=*(str+i); - } - return str2; -} -///CCC - -int main(int argc, char *argv[]) { - - char str[]="Hello, world"; - char *str2=duplicate(str); - char *str3=duplicate2(str); - printf("str: %s\n",str); - printf("str2: %s\n",str2); - printf("str3: %s\n",str3); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S3-src/structargs.c b/Theorie/C/S3-src/structargs.c deleted file mode 100644 index a8fc564afa05822c54ecdd3bd835a82989078485..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/structargs.c +++ /dev/null @@ -1,72 +0,0 @@ -/************************************** - * structargs.c - * - * exemple de structures comme arguments - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <sys/time.h> - - -/* Return t2-t1 in microseconds */ -long timeval_diff(struct timeval *t2, struct timeval *t1) -{ - long diff = (t2->tv_usec + 1000000 * t2->tv_sec) - (t1->tv_usec + 1000000 * t1->tv_sec); - return (diff); -} - -///AAA - -#define MILLION 1000000 - -struct large_t { - int i; - char str[MILLION]; -}; - -int sum(struct large_t s1, struct large_t s2) { - return (s1.i+s2.i); -} - -int sumptr(struct large_t *s1, struct large_t *s2) { - return (s1->i+s2->i); -} - -int main(int argc, char *argv[]) { - struct timeval tvStart, tvEnd; - int err; - int n; - struct large_t one={1,"one"}; - struct large_t two={1,"two"}; - - n=sum(one,two); - n=sumptr(&one,&two); - -///BBB - - err=gettimeofday(&tvStart, NULL); - if(err!=0) - exit(EXIT_FAILURE); - - err=sum(one,two); - - err=gettimeofday(&tvEnd, NULL); - if(err!=0) - exit(EXIT_FAILURE); - printf("Durée de sum : %ld microsecondes\n",timeval_diff(&tvEnd, &tvStart)); - - err=gettimeofday(&tvStart, NULL); - if(err!=0) - exit(EXIT_FAILURE); - - err=sumptr(&one,&two); - - err=gettimeofday(&tvEnd, NULL); - if(err!=0) - exit(EXIT_FAILURE); - - printf("Durée de sumptr : %ld microsecondes\n",timeval_diff(&tvEnd, &tvStart)); -} - diff --git a/Theorie/C/S3-src/typecast.c b/Theorie/C/S3-src/typecast.c deleted file mode 100644 index 5093e47386b25e7db546629d16b9c259fb8df5bb..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/typecast.c +++ /dev/null @@ -1,26 +0,0 @@ -/************************************** - * typecast.c - * - * Programme d'exemple de conversion entre - * types de données - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) { - - ///AAA - int i=1; - float f=1e20; - double d=1e100; - - printf("i [int]: %d, [float]:%f, [double]:%f\n",i,(float)i,(double)i); - printf("f [int]: %d, [float]:%f, [double]:%f\n",(int)f,f,(double)f); - printf("d [int]: %d, [float]:%f, [double]:%f\n",(int)d,(float)d,d); - printf("sizeof -> int:%d float:%d double:%d\n",(int)sizeof(int), (int)sizeof(float), (int)sizeof(double)); - - ///BBB - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S3-src/union.c b/Theorie/C/S3-src/union.c deleted file mode 100644 index 9951e915f6ebacea9cfa148363eaf283030175d5..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/union.c +++ /dev/null @@ -1,61 +0,0 @@ -/************************************** - * union.c - * - * Programme d'exemple de union - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -///AAA - -struct s_t { - int i; - char c; -} s; - -union u_t { - int i; - char c; -} u; - -///BBB - -typedef enum { INTEGER, CHAR } Type; - -typedef struct -{ - Type type; - union { - int i; - char c; - } x; -} Value; - - -///XXX - -int main(int argc, char *argv[]) { - ///CCC - // initialisation - s.i=1252; - s.c='A'; - u.i=1252; - // u contient un int - u.c='Z'; - // u contient maintenant un char (et u.i est perdu) - ///DDD - printf("sizeof(s_t) : %ld\n",sizeof(s)); - printf("sizeof(u_t) : %ld\n",sizeof(u)); - ///EEE - u.i=1252; - printf("char : %c\n", u.c); - - ///FFF -Value v; -v.type=INTEGER; -v.x.i=1252; -///GGG - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S3-src/var.c b/Theorie/C/S3-src/var.c deleted file mode 100644 index 4ce1462aa121293a39baf57f087a6dca78b42b75..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/var.c +++ /dev/null @@ -1,17 +0,0 @@ -/************************************** - * var.c - * - * Programme d'exemple pour localiser - * les variables en mémoire - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) { - // affiche sur la sortie standard - printf("Hello, world!\n"); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S3-src/vector.c b/Theorie/C/S3-src/vector.c deleted file mode 100644 index d41579c3e55a0bac3702941e812cefdedb5039e6..0000000000000000000000000000000000000000 --- a/Theorie/C/S3-src/vector.c +++ /dev/null @@ -1,59 +0,0 @@ -/************************************** - * vector.c - * - * Programme de manipulation de vecteurs - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> -///AAA -struct vector_t { - int size; - float *v; -}; -// initialise le vecteur à la valeur du réel -struct vector_t * init(int, float) ; -// récupère le nième élément -float get(struct vector_t *, int) ; -// fixe la valeur du nième élément -void set(struct vector_t *, int , float); -// supprime un vecteur -void destroy(struct vector_t *); - -///BBB -struct vector_t * init(int size, float val) -{ - struct vector_t *v=(struct vector_t *)malloc(sizeof(struct vector_t)); - v->v=(float *)malloc(size*sizeof(float)); - v->size=size; - for(int i=0;i<size;i++) { - *(v->v+i)=val; - } - return v; -} - -float get(struct vector_t *v, int i) { - return *(v->v+i); -} - -void set(struct vector_t *v, int i, float val) { - if(i<v->size) - *(v->v+i)=val; -} - -void destroy(struct vector_t *v) { - free(v->v); - free(v); -} - -int main(int argc, char *argv[]) { - - struct vector_t *v1=init(10,2.0); - printf("v1[%d]=%f\n",3,get(v1,3)); - set(v1,3,17.0); - printf("v1[%d]=%f\n",3,get(v1,3)); - destroy(v1); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/C/S5-src/Makefile2 b/Theorie/C/S5-src/Makefile2 deleted file mode 100644 index 9f43fcadd9455f1b955e8f59c63e7fa3d8ce9244..0000000000000000000000000000000000000000 --- a/Theorie/C/S5-src/Makefile2 +++ /dev/null @@ -1,21 +0,0 @@ -# -# Makefile for source code -# -# Builds all .c files, assuming they are all independant and runs them -# to collect the output on stdout -# -# Automatically builds some of the examples to be included in the text -# - -###AAA - -myprog: main.o min.o - gcc -std=c99 -o myprog main.o min.o - -main.o: main.c min.h - gcc -std=c99 -c main.c - -min.o: min.c min.h - gcc -std=c99 -c min.c - -###BBB diff --git a/Theorie/C/S5-src/errno.c b/Theorie/C/S5-src/errno.c deleted file mode 100644 index 4c0a4ec790bb622f03dfdb9a0714063f065c1950..0000000000000000000000000000000000000000 --- a/Theorie/C/S5-src/errno.c +++ /dev/null @@ -1,24 +0,0 @@ -/************************************** - * errno.c - * - * Programme d'exemple pour errno - * - **************************************/ -///AAA -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -int main(int argc, char *argv[]) { - - if(setenv(NULL,NULL,1)!=0) { - fprintf(stderr,"Erreur : errno=%d %s\n",errno,strerror(errno)); - } - if(setenv("PATH=","/usr/bin",1)!=0) { - fprintf(stderr,"Erreur : errno=%d %s\n",errno,strerror(errno)); - } - - -} - diff --git a/Theorie/C/S5-src/fctptr.c b/Theorie/C/S5-src/fctptr.c deleted file mode 100644 index c9b68d53b0d4231dd3e6f9348b13263c5ed3c031..0000000000000000000000000000000000000000 --- a/Theorie/C/S5-src/fctptr.c +++ /dev/null @@ -1,45 +0,0 @@ -/************************************** - * fctptr.c - * - * Programme d'exemple pour les pointeurs - * vers des fonctions - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> -///AAA -int g=1; -int debug_level; - -void empty (char *str) { - return; -} - -void oneline(char *str) { - fprintf(stderr,"debug: %s\n",str); -} - -void detailed(char *str) { - fprintf(stderr, "debug: %s\n",str); - fprintf(stderr,"g=%d\n",g); -} - -void (* debug_print[])(char *) = { empty, - oneline, - detailed }; - -int main(int argc, char *argv[]) { - - if(argc!=2) - return(EXIT_FAILURE); - - debug_level=atoi(argv[1]); - if((debug_level<0) || (debug_level>2) ) - return(EXIT_FAILURE); - printf("fct debug_print : %p\n",debug_print[debug_level]); - (debug_print[debug_level])("Hello"); - - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/C/S5-src/main.c b/Theorie/C/S5-src/main.c deleted file mode 100644 index 01130f8a563511b4851a98873a0e95f937025024..0000000000000000000000000000000000000000 --- a/Theorie/C/S5-src/main.c +++ /dev/null @@ -1,18 +0,0 @@ -/************************************** - * main.c - * - * Programme d'exemple pour le linker - * - **************************************/ - -#include "min.h" -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) { - float f1=3.45; - float f2=-4.12; - printf("Minimum(%f,%f)=%f\n",f1,f2,min(f1,f2)); - return(EXIT_SUCCESS); -} - diff --git a/Theorie/C/S5-src/min.c b/Theorie/C/S5-src/min.c deleted file mode 100644 index 1a0c53f81b43a18e0c0be95f386570b256c0cfef..0000000000000000000000000000000000000000 --- a/Theorie/C/S5-src/min.c +++ /dev/null @@ -1,17 +0,0 @@ -/************************************** - * min.c - * - * Programme d'exemple pour le linker - * - **************************************/ - -#include "min.h" - -float min(float a, float b) { - if(a<b) - return a; - else - return b; -} - - diff --git a/Theorie/C/S5-src/min.h b/Theorie/C/S5-src/min.h deleted file mode 100644 index 7812a4fe350d83e1b36316adc991c0355efe4f25..0000000000000000000000000000000000000000 --- a/Theorie/C/S5-src/min.h +++ /dev/null @@ -1,13 +0,0 @@ -/************************************** - * min.h - * - **************************************/ - -#ifndef _MIN_H_ -#define _MIN_H_ - -float min(float, float); - -#endif /* _MIN_H */ - - diff --git a/Theorie/C/S5-src/module.c b/Theorie/C/S5-src/module.c deleted file mode 100644 index a8f6204ae63f555734b0d31f3fd6285b5915bad7..0000000000000000000000000000000000000000 --- a/Theorie/C/S5-src/module.c +++ /dev/null @@ -1,31 +0,0 @@ -/************************************** - * module.c - * - **************************************/ - -#include "module.h" - -static float min(float, float); - -int num1=0; // accessible hors de module.c -extern int num2; // définie dans un autre module -static int num3=1252; // accessible uniquement dans ce module - -float vmin(int n, float *ptr) { - float *p=ptr; - float m=*ptr; - for(int i=1;i<n;i++) { - m=min(m,*p); - p++; - } - return m; -} - -static float min(float a, float b) { - if(a<b) - return a; - else - return b; -} - - diff --git a/Theorie/C/S5-src/module.h b/Theorie/C/S5-src/module.h deleted file mode 100644 index cbfdb4ccc758a6b2c35d734c86f61ec7ba6cb261..0000000000000000000000000000000000000000 --- a/Theorie/C/S5-src/module.h +++ /dev/null @@ -1,12 +0,0 @@ -/************************************** - * module.h - * - **************************************/ -#ifndef _MODULE_H_ -#define _MODULE_H_ - -float vmin(int, float *); - -#endif /* _MODULE_H */ - - diff --git a/Theorie/C/S5-src/mystrtol.c b/Theorie/C/S5-src/mystrtol.c deleted file mode 100644 index 3cfbfdc267ac23810a787a128d3110798f254138..0000000000000000000000000000000000000000 --- a/Theorie/C/S5-src/mystrtol.c +++ /dev/null @@ -1,46 +0,0 @@ -/************************************** - * stresep.c - * - * Implementation partielle de strtol - * - **************************************/ -///AAA -#include <stdlib.h> -#include <stdio.h> -#include <ctype.h> -#include <stdbool.h> - -int mystrtol(const char *restrict str, - char **restrict endptr, - int base) { - - int val; - int i=0; - int err=false; - while(!err && *(str+i)!='\0') - { - if(!isdigit(*(str+i))) { - err=true; - *endptr=(char *)(str+i); - } - i++; - } - // ... - return val; -} -///BBB - -int main(int argc, char *argv[]) -{ - char *p, *s; - long li; - s = "1252m"; - li = mystrtol(s,&p,10); - if(p!=NULL) { - printf("Caractère erronné : %c\n",*p); - // p pointe vers le caractère en erreur - } - printf("Valeur convertie : %s -> %ld\n",s,li); - return(EXIT_SUCCESS); - -} diff --git a/Theorie/C/S5-src/prog.c b/Theorie/C/S5-src/prog.c deleted file mode 100644 index 538d4f8a4b0aa521664f00e9169d11dd8fa3556d..0000000000000000000000000000000000000000 --- a/Theorie/C/S5-src/prog.c +++ /dev/null @@ -1,39 +0,0 @@ -/************************************** - * prog - * - * Programme d'exemple pour le linker - * - **************************************/ - -#include <stdlib.h> -#include <stdio.h> -///AAA -#include "min.h" -#include "module.h" - -#define SIZE 4 - -extern int num1; // définie dans un autre module -int num2=1252; // accessible depuis un autre module -static int num3=-1; // accessible uniquement dans ce module - -void f() { - static int n=0; - int loc=2; - if(n==0) - printf("n est à l'adresse %p et loc à l'adresse %p\n",&n,&loc); - printf("f, n=%d\n",n); - n++; -} - -int main(int argc, char* argv[]) { - - float v[SIZE]={1.0, 3.4, -2.4, 9.9}; - printf("Minimum: %f\n",vmin(SIZE,v)); - f(); - f(); - printf("Minimum(0.0,1.1)=%f\n",min(0.0,1.1)); - return(EXIT_SUCCESS); -} - - diff --git a/Theorie/C/S5-src/prog.out b/Theorie/C/S5-src/prog.out deleted file mode 100644 index 95f658621a9fdc78dda8a325d1a33dace5f76d29..0000000000000000000000000000000000000000 --- a/Theorie/C/S5-src/prog.out +++ /dev/null @@ -1,5 +0,0 @@ -Minimum: -2.400000 -n est à l'adresse 0x100001078 et loc à l'adresse 0x7fff5fbfe1cc -f, n=0 -f, n=1 -Minimum(0.0,1.1)=0.000000 diff --git a/Theorie/C/S5-src/ptrptr.c b/Theorie/C/S5-src/ptrptr.c deleted file mode 100644 index 1044c2a914f7f8902b5257fd951ec34e529fbdd3..0000000000000000000000000000000000000000 --- a/Theorie/C/S5-src/ptrptr.c +++ /dev/null @@ -1,24 +0,0 @@ -/************************************** - * ptrptr.c - * - * Programme d'exemple pour les pointeurs - * vers des pointeurs - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> -///AAA -int main(int argc, char **argv) { - - char **p; - p=argv; - printf("Arguments :"); - while(*p!=NULL) { - printf(" %s",*p); - p++; - } - printf("\n"); - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/C/S5-src/qsort.c b/Theorie/C/S5-src/qsort.c deleted file mode 100644 index 3e834bba35d90ebcebafc19a92e954a0e72d5723..0000000000000000000000000000000000000000 --- a/Theorie/C/S5-src/qsort.c +++ /dev/null @@ -1,41 +0,0 @@ -/************************************** - * qosrt.c - * - * Programme d'exemple d'utilisation de qsort - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> -///AAA -#define SIZE 5 -double array[SIZE]= { 1.0, 7.32, -3.43, 8.7, 9.99 }; - -void print_array() { - for(int i=0;i<SIZE;i++) - printf("array[i]:%f\n",array[i]); -} - -int cmp(const void *ptr1, const void *ptr2) { - const double *a=ptr1; - const double *b=ptr2; - if(*a==*b) - return 0; - else - if(*a<*b) - return -1; - else - return +1; -} - -int main(int argc, char *argv[]) { - - printf("Avant qsort\n\n"); - print_array(); - qsort(array,SIZE,sizeof(double),cmp); - printf("Après qsort\n\n"); - print_array(); - - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/C/S5-src/strtol.c b/Theorie/C/S5-src/strtol.c deleted file mode 100644 index b1755d6fa8bdd9d8dea44720458583bbe5539441..0000000000000000000000000000000000000000 --- a/Theorie/C/S5-src/strtol.c +++ /dev/null @@ -1,34 +0,0 @@ -/************************************** - * strtol.c - * - * Programme d'exemple d'utilisation de strtol - * - **************************************/ -///AAA -#include <stdlib.h> -#include <stdio.h> - -int main(int argc, char *argv[]) { - - char *p, *s; - long li; - s = "1252"; - li = strtol(s,&p,10); - if(*p != '\0') { - printf("Caractère erronné : %c\n",*p); - // p pointe vers le caractère en erreur - } - printf("Valeur convertie : %s -> %ld\n",s,li); - - s = "12m52"; - li = strtol(s,&p,10); - if(*p != '\0') { - printf("Caractère erronné : %c\n",*p); - } - printf("Valeur convertie : %s -> %ld\n",s,li); - - return(EXIT_SUCCESS); -} - - - diff --git a/Theorie/C/S5-src/strtol.out b/Theorie/C/S5-src/strtol.out deleted file mode 100644 index 58f9b96802b3183d71b2b2296f9a86d2e9eb9026..0000000000000000000000000000000000000000 --- a/Theorie/C/S5-src/strtol.out +++ /dev/null @@ -1,3 +0,0 @@ -Valeur convertie : 1252 -> 1252 -Caractère erronné : m -Valeur convertie : 12m52 -> 12 diff --git a/Theorie/C/datatypes.rst b/Theorie/C/datatypes.rst deleted file mode 100644 index ceb4e4d0f3a72fc116a79c862455cd40c9605bc6..0000000000000000000000000000000000000000 --- a/Theorie/C/datatypes.rst +++ /dev/null @@ -1,1022 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012, 2019 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -Types de données -================ - -Dans les sections précédentes, nous avons abordé quelques types de -données de base dont les ``int`` et les ``char``. Pour utiliser ces types de données à bon escient, il est important de comprendre en détail la façon dont ils sont supportés par le compilateur et leurs limitations. Celles-ci dépendent souvent de leur représentation en mémoire et durant cette semaine nous allons commencer à analyser de façon plus détaillée comment la mémoire d'un ordinateur est structurée. - - - -Nombres entiers ---------------- - -Toutes les données stockées sur un ordinateur sont représentées sous la forme de séquences de bits. -Ces séquences de bits peuvent d'abord permettre de représenter des -nombres entiers. Un système informatique peut travailler avec deux -types de nombres entiers : - - - les nombres entiers signés (``int`` notamment en C) - - les nombres entiers non-signés (``unsigned int`` notamment en C) - -Une séquence de :math:`n` bits :math:`b_0 ... b_i ... b_{n-1}` peut représenter le -nombre entier :math:`\sum_{i=0}^{n-1} b_i \times 2^i`. Par convention, le bit -:math:`b_{n-1}`, associé au facteur du plus grand indice :math:`2^{n-1}`, est appelé le -:term:`bit de poids fort` tandis que le bit :math:`b_0`, associé à :math:`2^0`, -est appelé le :term:`bit de poids faible`. Les suites de bits sont communément -écrites dans l'ordre descendant des indices :math:`b_{n-1} ... b_i ... b_0`. À titre -d'exemple, la suite de bits ``0101`` correspond à l'entier non signé représentant -la valeur cinq. Le bit de poids fort de cette séquence de quatre bits -(ou :term:`nibble`) est ``0``. Le bit de poids faible est ``1``. La table ci-dessous reprend les -différentes valeurs décimales correspondant à toutes les séquences de quatre bits consécutifs. - -======= ===== =========== ======= -binaire octal hexadécimal décimal -======= ===== =========== ======= -0000 00 0 0 -0001 01 1 1 -0010 02 2 2 -0011 03 3 3 -0100 04 4 4 -0101 05 5 5 -0110 06 6 6 -0111 07 7 7 -1000 10 8 8 -1001 11 9 9 -1010 12 A 10 -1011 13 B 11 -1100 14 C 12 -1101 15 D 13 -1110 16 E 14 -1111 17 F 15 -======= ===== =========== ======= - - -Écrire une séquence de bits sous la forme d'une suite de -``0`` et de ``1`` peut s'avérer fastidieux. La représentation décimale -traditionnelle n'est pas pratique (optimale) non plus car il faut un ou deux -chiffres pour représenter une séquence de quatre bits (ou :term:`nibble`) en fonction de la -valeur de ces bits. En pratique, de nombreux systèmes informatiques -utilisent une représentation hexadécimale pour afficher des séquences -de bits. Cette notation hexadécimale est définie sur base de la table -ci-dessus en utilisant des lettres pour représenter chaque séquence de quatre -bits dont la valeur numérique est supérieure à ``9``. Tout comme avec -la représentation décimale habituelle, il est possible d'utiliser la -représentation hexadécimale pour de longues séquences de bits. La -notation octale est parfois utilisée et est supportée par les -compilateurs C. Elle utilise un chiffre pour représenter trois bits -consécutifs. A titre -d'exemple, voici quelques conversions de nombres en notation -décimale vers les notations hexadécimales et binaires. - - - L'entier décimal ``123`` s'écrit ``0x7b`` en notation hexadécimale - et ``0b000000000000000000000000001111011`` en notation binaire - - L'entier décimal ``7654321`` s'écrit ``0x74cbb1`` en notation - hexadécimale et ``0b000000000011101001100101110110001`` en notation - binaire - -Dans ces exemples, nous avons pris la convention de représentation des -nombres en langage C. En C, un nombre décimal s'écrit avec la -représentation standard. Un nombre entier en notation hexadécimale est par -convention préfixé par ``0x`` tandis qu'un nombre entier en notation -binaire est préfixé par ``0b``. Ainsi, les déclarations ci-dessous -correspondent toutes à la même valeur. - -.. literalinclude:: /C/S2-src/num.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Certains compilateurs permettent d'entrer des constantes en binaire -directement en préfixant le nombre avec ``0b`` comme dans -``i=0b1111011;``. Cependant, cette notation n'est pas portable sur -tous les compilateurs. Elle doit donc être utilisée avec précaution, -contrairement à la notation hexadécimale qui fait partie du langage. - -.. note:: Notation octale - - La notation octale peut poser des surprises désagréables au - programmeur C débutant. En effet, pour des raisons historiques, les - compilateurs C considèrent qu'un entier dont le premier chiffre est - ``0`` est écrit en représentation octale et non en représentation - décimale. - - Ainsi, le fragment de code ci-dessous affichera à l'écran le message - ``65 et 53 sont différents`` car le compilateur C interprète la ligne - ``j=065;`` comme contenant un entier en notation octale et non décimale. - - .. literalinclude:: /C/S2-src/octal.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -Le langage C supporte différents types de données qui permettent de -représenter des nombres entiers non signés. Les principaux sont repris -dans le tableau ci-dessous. - -====================== =========================================================== -Type Explication -====================== =========================================================== -``unsigned short`` Nombre entier non signé représenté sur au moins 16 bits -``unsigned int`` Nombre entier non signé représenté sur au moins 16 bits -``unsigned long`` Nombre entier non signé représenté sur au moins 32 bits -``unsigned long long`` Nombre entier non signé représenté sur au moins 64 bits -====================== =========================================================== - - - -Le nombre de bits utilisés pour stocker chaque type d'entier non signé -peut varier d'une implémentation à l'autre. Le langage C permet de -facilement déterminer le nombre de bits utilisés pour stocker un type -de données particulier en utilisant l'expression ``sizeof``. Appliquée -à un type de données, celle-ci retourne le nombre d'octets que ce type -occupe. Ainsi, sur de nombreuses plateformes, -``sizeof(int)`` retournera la valeur ``4``. - -Les systèmes informatiques doivent également manipuler des nombres -entiers négatifs. Cela se fait en utilisant des nombres dits -signés. Au niveau binaire, il y a plusieurs approches possibles pour -représenter des nombres signés. La première est de réserver le bit de poids fort dans la représentation du nombre pour stocker le signe et stocker la -valeur absolue du nombre dans les bits de poids faible. -Mathématiquement, un nombre de `n` bits utilisant cette notation -pourrait se convertir via la formule -:math:`(-1)^{b_{n-1}} \times \sum_{i=0}^{n-2} b_i \times 2^i`. - -En pratique, cette notation est rarement utilisée pour les nombres -entiers car elle rend la réalisation des circuits électroniques de -calcul plus compliquée. Un autre inconvénient de cette notation est -qu'elle utilise deux séquences de bits différentes pour représenter la -valeur zéro (``00...0`` et ``10...0``). La représentation la plus courante pour les -nombres entiers signés est la notation en `complément à 2`. Avec cette -notation, une séquence de `n` bits correspond au nombre entier -:math:`-(b_{n-1})\times 2^{n-1} + \sum_{i=0}^{n-2} b_i \times 2^i`. -Avec cette notation, le nombre négatif de 4 bits le plus petit -correspond à la valeur ``-8``. En notation en complément à deux, il -n'y a qu'une seule représentation pour le nombre zéro, la séquence -dont tous les bits valent ``0``. Par contre, il existe toujours -un nombre entier négatif qui n'a pas d'équivalent positif. - -======= ============= -binaire décimal signé -======= ============= -0000 0 -0001 1 -0010 2 -0011 3 -0100 4 -0101 5 -0110 6 -0111 7 -1000 -8 -1001 -7 -1010 -6 -1011 -5 -1100 -4 -1101 -3 -1110 -2 -1111 -1 -======= ============= - -En C, les types de données utilisés pour représenter des entiers sont -signés par défaut. Ils ont la même taille que leurs équivalents -non signés et sont repris dans la table ci-dessous. - -============================= =================================================== -Type Explication -============================= =================================================== -``short`` Nombre entier signé représenté sur au moins 16 bits -``int`` Nombre entier signé représenté sur au moins 16 bits -``long`` Nombre entier signé représenté sur au moins 32 bits -``long long`` Nombre entier signé représenté sur au moins 64 bits -============================= =================================================== - - -Dans de nombreux systèmes Unix, on retrouve dans le fichier -`stdint.h`_ les définitions des types d'entiers supportés par le -système avec le nombre de bits et les valeurs minimales et maximales -pour chaque type. La table ci-dessous reprend à titre d'exemple -l'information relative aux types ``short`` (16 bits) et ``unsigned -int`` (32 bits). - -================= ==== ======= =========== -Type Bits Minimum Maximum -================= ==== ======= =========== -``short`` 16 -32768 32767 -``unsigned int`` 32 0 4294967295 -================= ==== ======= =========== - -.. todo:: ajouter les noms des constantes - -Le fichier `stdint.h`_ contient de nombreuses constantes qui doivent -être utilisées lorsque l'on a besoin des valeurs minimales et -maximales pour un type donné. Voici à titre d'exemple quelques unes de ces valeurs : - -.. code-block:: c - - #define INT8_MAX 127 - #define INT16_MAX 32767 - #define INT32_MAX 2147483647 - #define INT64_MAX 9223372036854775807LL - - #define INT8_MIN -128 - #define INT16_MIN -32768 - #define INT32_MIN (-INT32_MAX-1) - #define INT64_MIN (-INT64_MAX-1) - - #define UINT8_MAX 255 - #define UINT16_MAX 65535 - #define UINT32_MAX 4294967295U - #define UINT64_MAX 18446744073709551615ULL - - -L'utilisation d'un nombre fixe de bits pour représenter les entiers -peut causer des erreurs dans certains calculs. Par exemple, -voici un petit programme qui affiche les 10 premières puissances de -cinq et dix. - -.. literalinclude:: /C/S2-src/short.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Lorsqu'il est exécuté, ce programme affiche la sortie suivante. - -.. literalinclude:: /C/S2-src/short.out - :encoding: utf-8 - :language: console - -Il est important de noter que le langage C ne contient aucun mécanisme -d'exception qui permettrait au programmeur de détecter ce problème à -l'exécution. Lorsqu'un programmeur choisit une représentation pour -stocker des nombres entiers, il est essentiel qu'il ait en tête -l'utilisation qui sera faite de cet entier et les limitations qui -découlent du nombre de bits utilisés pour représenter le nombre en -mémoire. Si dans de nombreuses applications ces limitations ne sont -pas pénalisantes, il existe des applications critiques où un calcul -erroné peut avoir des conséquences énormes [Bashar1997]_. - -Nombres réels -------------- - -Outre les nombres entiers, les systèmes informatiques doivent aussi -pouvoir manipuler des nombres réels. Ceux-ci sont également -représentés sous la forme d'une séquence fixe de bits. Il existe deux formes de représentation pour les nombres réels : - - - la représentation en :term:`simple précision` dans laquelle le nombre réel est stocké sous la forme d'une séquence de 32 bits; - - la représentation en :term:`double précision` dans laquelle le nombre réel est stocké sous la forme d'une séquence de 64 bits. - -La plupart des systèmes informatiques qui permettent de manipuler des -nombres réels utilisent le standard IEEE-754. Un nombre réel est -représenté en virgule flottante et la séquence de bits correspondante -est décomposée en trois parties [#fexemple]_ : - - - le bit de poids fort indique le signe du nombre. Par convention, ``0`` est utilisé pour les nombres positifs et ``1`` pour les nombres négatifs. - - `e` bits sont réservés pour stocker l'exposant [#fexposant]_. - - Les `f` bits de poids faible servent à stocker la partie fractionnaire du nombre réel. - -.. figure:: /C/svg/Float_example.png - :align: center - :scale: 100 - - Exemple de nombre en virgule flottante (simple précision). (source : Wikipedia) - -En simple (resp. double) précision, `8` (resp. `11`) bits sont utilisés pour -stocker l'exposant et `23` (resp. `52`) bits pour la partie -fractionnaire. L'encodage des nombres réels en simple et double -précision a un impact sur la précision de divers algorithmes -numériques. Une analyse détaillée de ces problèmes sort du cadre de ce -cours, mais il est important de noter deux propriétés importantes de -la notation en virgule flottante utilisée actuellement. Ces deux -propriétés s'appliquent de la même façon à la simple qu'à la double précision. - - - une représentation en virgule flottante sur `n` bits ne permet jamais de représenter plus de :math:`2^n` nombres réels différents; - - les représentations en virgule flottante privilégient les nombres réels compris dans l'intervalle :math:`[-1,1]`. On retrouve autant de nombres réels représentables dans cet intervalle que de nombres dont la valeur absolue est supérieure à `1`. - -En C, ces nombres en virgule flottante sont représentés en utilisant -les types ``float`` (simple précision) et ``double`` (double précision). Les fichiers `float.h`_ et `math.h`_ définissent de nombreuses constantes relatives à ces types. Voici, à titre d'exemple, les valeurs minimales et maximales pour les ``float`` et les ``double`` ainsi que les constantes associées. Pour qu'un programme soit portable, il faut utiliser les constantes définies dans `float.h`_ et `math.h`_ et non leurs valeurs numériques. - -.. code-block:: c - - #define FLT_MIN 1.17549435e-38F - #define FLT_MAX 3.40282347e+38F - - #define DBL_MIN 2.2250738585072014e-308 - #define DBL_MAX 1.7976931348623157e+308 - - -Les tableaux ------------- - -En langage C, les tableaux permettent d'agréger des données d'un même type. Il est possible de définir des vecteurs et des matrices en utilisant la syntaxe ci-dessous. - -.. literalinclude:: /C/S2-src/array.c - :language: c - :encoding: utf-8 - :start-after: ///AAA - :end-before: ///BBB - -Les premières versions du langage C ne permettaient que la définition de tableaux dont la taille est connue à la compilation. Cette restriction était nécessaire pour permettre au compilateur de réserver la zone mémoire pour stocker le tableau. Face à cette limitation, de nombreux programmeurs définissaient la taille du tableau via une directive ``#define`` du pré-processeur comme dans l'exemple ci-dessus. Cette directive permet d'associer une chaîne de caractères quelconque à un symbole. Dans l'exemple ci-dessus, la chaîne ``10`` est associée au symbole ``N``. Lors de chaque compilation, le préprocesseur remplace toutes les occurrences de ``N`` par ``10``. Cela permet au compilateur de ne traiter que des tableaux de taille fixe. - -Un tableau à une dimension peut s'utiliser avec une syntaxe similaire à celle utilisée par Java. Dans un tableau contenant ``n`` éléments, le premier se trouve à l'indice ``0`` et le dernier à l'indice ``n-1``. L'exemple ci-dessous présente le calcul de la somme des éléments d'un vecteur. - -.. literalinclude:: /C/S2-src/array.c - :language: c - :encoding: utf-8 - :start-after: ///CCC - :end-before: ///DDD - -Le langage C permet aussi la manipulation de matrices carrées ou rectangulaires qui sont composées d'éléments d'un même type. L'exemple ci-dessous calcule l'élément minimum d'une matrice rectangulaire. Il utilise la constante ``FLT_MAX`` qui correspond au plus grand nombre réel représentable avec un ``float`` et qui est définie dans `float.h`_. - -.. literalinclude:: /C/S2-src/array.c - :language: c - :encoding: utf-8 - :start-after: ///EEE - :end-before: ///FFF - -Les compilateurs récents qui supportent [C99]_ permettent l'utilisation de tableaux dont la taille n'est connue qu'à l'exécution. Nous en reparlerons ultérieurement. - -Caractères et chaînes de caractères ------------------------------------ - -Historiquement, les caractères ont été représentés avec des séquences -de bits de différentes longueurs. Les premiers ordinateurs utilisaient -des blocs de cinq bits. Ceux-ci permettaient de représenter 32 valeurs -différentes. Cinq bits ne permettent pas facilement de représenter à -la fois les chiffres et les lettres et les premiers ordinateurs -utilisaient différentes astuces pour supporter ces caractères sur 5 -bits. Ensuite, des représentations sur six puis sept et huit bits -ont été utilisées. Au début des années septante, le code de caractères -ASCII sur ``7`` et ``8`` bits s'est imposé sur un grand nombre -d'ordinateurs et a été utilisé comme standard pour de nombreuses -applications et notamment sur Internet :rfc:`20`. La table de -caractères ASCII définit une correspondance entre des séquences de -bits et des caractères. :rfc:`20` contient la table des caractères -ASCII représentés sur 7 bits. À titre d'exemple, le chiffre `0` -correspond à l'octet `0b00110000` et le chiffre `9` à l'octet -`0b00111001`. La lettre `a` correspond à l'octet `0b01100001` et la -lettre `A` à l'octet `0b01000001`. De nombreux détails sur la table ASCII sont disponibles sur la page Wikipedia: https://en.wikipedia.org/wiki/ASCII - -Les inventeurs du C se sont appuyés sur la table ASCII et ont choisi -de représenter un caractère en utilisant un octet. Cela correspond au -type ``char`` que nous avons déjà évoqué. - -Concernant le type ``char``, il est utile de noter qu'un ``char`` est -considéré en C comme correspondant à un entier. Cela implique qu'il -est possible de faire des manipulations numériques sur les -caractères. À titre d'exemple, une fonction `toupper(3)`_ permettant -de transformer un caractère représentant une minuscule dans le -caractère représentant la majuscule correspondante peut s'écrire : - -.. literalinclude:: /C/S2-src/toupper.c - :language: c - :encoding: utf-8 - :start-after: ///AAA - :end-before: ///BBB - - -En pratique, l'utilisation de la table ASCII pour représenter des -caractères souffre d'une limitation majeure. Avec `7` ou `8` bits il -n'est pas possible de représenter exactement tous les caractères -écrits de toutes les langues. Une table des caractères sur `7` bits -est suffisante pour les langues qui utilisent peu de caractères -accentués comme l'anglais. Pour le français et de nombreuses langues -en Europe occidentale, la table sur `8` bits est suffisante et la norme -ISO-8859_ contient des tables de caractères `8` bits pour de -nombreuses langues. La norme :term:`Unicode` va plus loin en permettant de -représenter les caractères écrits de toutes les langues connues -sur Terre. Une description détaillée du support de ces types de -caractères sort du cadre de ce cours sur les systèmes -informatiques. Il est cependant important que vous soyez conscient de -cette problématique pour pouvoir la prendre en compte lorsque vous -développerez des applications qui doivent traiter du texte dans -différentes langues. - -À titre d'exemple, la fonction `toupper(3)`_ qui est implémentée dans -les versions récentes de Linux est nettement plus complexe que celle -que nous avons vue ci-dessus. Tout d'abord, la fonction `toupper(3)`_ -prend comme argument un ``int`` et non un ``char``. Cela lui permet -d'accepter des caractères dans n'importe quel encodage. Ensuite, le -traitement qu'elle effectue dépend du type d'encodage qui a été -défini via `setlocale(3)`_ (voir `locale(7)`_). - - -.. see http://en.wikipedia.org/wiki/List_of_binary_codes - -Dans la suite de ce document, nous supposerons qu'un caractère -est toujours représentable en utilisant le type ``char`` permettant de -stocker un octet. - -En C, les chaînes de caractères sont représentées sous la forme d'un -tableau de caractères. Une chaîne de caractères peut être initialisée de -différentes façons reprises ci-dessous. - -.. code-block:: c - - char name1[] = { 'U', 'n', 'i', 'x' }; - char name2[] = { "Unix" }; - char name3[] = "Unix"; - - - -Lorsque la taille de la chaîne de caractères n'est pas indiquée à -l'initialisation (c'est-à -dire dans les deux dernières lignes -ci-dessus), le compilateur C la calcule et alloue un tableau -permettant de stocker la chaîne de caractères suivie du caractère ``\0`` -qui par convention termine `toujours` les chaînes de caractères en C. -En mémoire, la chaîne de caractères correspondant à ``name3`` occupe donc cinq -octets. Les quatre premiers contiennent les caractères `U`, `n`, `i` -et `x` et le cinquième le caractère ``\0``. Il est important de bien se -rappeler cette particularité du langage C car comme nous le verrons -plus tard ce choix a de nombreuses conséquences. - -Cette particularité permet d'implémenter facilement des -fonctions de manipulation de chaînes de -caractères. À titre d'exemple, la fonction ci-dessous calcule -la longueur d'une chaîne de caractères. - -.. literalinclude:: /C/S2-src/strlen.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Contrairement à des langages comme Java, C ne fait aucune vérification -sur la façon dont un programme manipule un tableau. En C, il est tout -à fait légal d'écrire le programme suivant : - -.. code-block:: c - - char name[5] = "Unix"; - printf("%c", name[6]); - printf("%c", name[12345]); - printf("%c", name[-1]); - -En Java, tous les accès au tableau ``name`` en dehors de la zone -mémoire réservée provoqueraient une ``ArrayIndexOutOfBoundsException``. En -C, il n'y a pas de mécanisme d'exception et le langage présuppose que -lorsqu'un programmeur écrit ``name[i]``, il a la garantie que la valeur -``i`` sera telle qu'il accédera bien à un élément valide du tableau -``name``. Ce choix de conception du C permet d'obtenir du code plus -efficace qu'avec Java puisque l'interpréteur Java doit vérifier tous -les accès à chaque tableau lorsqu'ils sont exécutés. Malheureusement, -ce choix de conception du C est aussi à l'origine d'un très grand -nombre de problèmes qui affectent la sécurité de nombreux -logiciels. Ces problèmes sont connus sous la dénomination -:term:`buffer overflow`. Nous aurons l'occasion d'y revenir plus tard. - -Les pointeurs -------------- - -Une différence majeure entre le C et la plupart des langages de -programmation actuels est que le C est proche de la machine (langage de bas niveau) et permet -au programmeur d'interagir directement avec la mémoire où les données -qu'un programme manipule sont stockées. En Java, un programme peut -créer autant d'objets qu'il souhaite (ou presque [#fstackjava]_). Ceux-ci sont -stockés en mémoire et le :term:`garbage collector` retire de la -mémoire les objets qui ne sont plus utilisés. En C, un programme peut -aussi réserver des zones pour stocker de l'information en -mémoire. Cependant, comme nous le verrons plus tard, c'est le -programmeur qui doit explicitement allouer et libérer la mémoire. - -Les `pointeurs` sont une des caractéristiques principales du langage C -par rapport à de nombreux autres langages. Un :term:`pointeur` est -défini comme étant une variable contenant l'adresse d'une autre -variable. Pour bien comprendre le fonctionnement des pointeurs, il est -important d'avoir en tête la façon dont la mémoire est organisée sur -un ordinateur. D'un point de vue abstrait, la mémoire d'un ordinateur -peut être vue sous la forme d'une zone de stockage dans laquelle il -est possible de lire ou d'écrire de l'information. Chaque zone -permettant de stocker de l'information est identifiée par une -:term:`adresse`. La mémoire peut être vue comme une implémentation de -deux fonctions C : - - - ``data read(addr)`` est une fonction qui, sur base - d'une adresse, retourne la valeur stockée à cette adresse. - - ``void write(addr, data)`` est une fonction qui écrit la donnée - ``data`` à l'adresse ``addr`` en mémoire. - -Ces adresses sont stockées sur un nombre fixe de -bits qui dépend en général de l'architecture du microprocesseur. Les -valeurs les plus courantes aujourd'hui sont `32` et `64`. Par -convention, les adresses sont représentées sous la forme d'entiers -non signés. Sur la plupart des architectures de processeurs, une -adresse correspond à une zone mémoire permettant de stocker un octet. -Lorsque nous utiliserons une représentation graphique de la mémoire, -nous placerons toujours les adresses numériquement basses en bas de la -figure et elles croîtront vers le haut. - -Considérons l'initialisation ci-dessous et supposons qu'elle est -stockée dans une mémoire où les adresses sont encodées sur `3` -bits. Une telle mémoire dispose de huit zones permettant chacune de -stocker un octet. - -.. code-block:: c - - char name[] = "Unix"; - char c = 'Z'; - -Après exécution de cette initialisation et en supposant que rien -d'autre n'est stocké dans cette mémoire, celle-ci contiendra les -informations reprises dans la table ci-dessous. - -+-------------+-----------+ -| Adresse | Contenu | -+=============+===========+ -| 111 | 0 | -+-------------+-----------+ -| 110 | 0 | -+-------------+-----------+ -| 101 | Z | -+-------------+-----------+ -| 100 | 0 | -+-------------+-----------+ -| 011 | x | -+-------------+-----------+ -| 010 | i | -+-------------+-----------+ -| 001 | n | -+-------------+-----------+ -| 000 | U | -+-------------+-----------+ - -En langage C, l'expression ``&var`` permet de récupérer l'adresse à -laquelle une variable a été stockée. Appliquée à l'exemple ci-dessus, -l'expression ``&(name[0])`` retournerait la valeur ``0b000`` tandis que -``&c`` retournerait la valeur ``0b101``. - -L'expression ``&`` peut s'utiliser avec n'importe quel type de -donnée. Les adresses de données en mémoire sont rarement affichées, -mais quand c'est le cas, on utilise la notation hexadécimale comme -dans l'exemple ci-dessous. - -.. literalinclude:: /C/S2-src/ptr.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -L'exécution de ce fragment de programme produit la sortie suivante. - -.. literalinclude:: /C/S2-src/ptr.out - :encoding: utf-8 - :language: console - -L'intérêt des pointeurs en C réside dans la possibilité de les -utiliser pour accéder et manipuler des données se trouvant en mémoire -de façon efficace. En C, chaque pointeur a un type et le type du -pointeur indique le type de la donnée qui est stockée dans une zone -mémoire particulière. Le type est associé au pointeur lors de la -déclaration de celui-ci. - -.. code-block:: c - - int i = 1; // entier - int *ptr_i; // pointeur vers un entier - char c = 'Z'; // caractère - char *ptr_c; // pointeur vers un char - - -Grâce aux pointeurs, il est possible non seulement d'accéder à -l'adresse où une donnée est stockée, mais aussi d'accéder à la valeur -qui est stockée dans la zone mémoire pointée par le pointeur en utilisant -l'expression ``*ptr``. Il est -également possible d'effectuer des calculs sur les pointeurs comme -représenté dans l'exemple ci-dessous. - - -.. literalinclude:: /C/S2-src/ptrex.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -L'exécution de ce fragment de programme produit la sortie suivante. - -.. literalinclude:: /C/S2-src/ptrex.out - :encoding: utf-8 - :language: console - - -En pratique en C, les notations ``char*`` et ``char[]`` sont -équivalentes et l'une peut s'utiliser à la place de l'autre. En utilisant -les pointeurs, la fonction de calcul de la longueur d'une chaîne de -caractères peut se réécrire comme suit. - -.. literalinclude:: /C/S2-src/strlenptr.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -Les pointeurs sont fréquemment utilisés dans les programmes écrits en langage C et il est important de bien comprendre leur fonctionnement. Un point important à bien comprendre est ce que l'on appelle l'`arithmétique des pointeurs`, c'est-à -dire la façon dont les opérations sur les pointeurs sont exécutées en langage C. Pour cela, il est intéressant de considérer la manipulation d'un tableau d'entiers à travers des pointeurs. - -.. literalinclude:: /C/src/ptr_arith.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -En mémoire, ce tableau est stocké en utilisant trois mots consécutifs de 32 bits comme le montre l'exécution du programme ci-dessous : - -.. literalinclude:: /C/src/ptr_arith.c - :encoding: utf-8 - :language: c - :start-after: ///CCC - :end-before: ///DDD - -.. code-block:: console - - 1020304 est à l'adresse 0x7fff5fbff750 - 5060708 est à l'adresse 0x7fff5fbff754 - 90A0B0C est à l'adresse 0x7fff5fbff758 - -La même sortie est produite avec le fragment de programme suivant qui utilise un pointeur. - -.. literalinclude:: /C/src/ptr_arith.c - :encoding: utf-8 - :language: c - :start-after: ///EEE - :end-before: ///FFF - -Ce fragment de programme est l'occasion de réfléchir sur la façon dont le C évalue les expressions qui contiennent des pointeurs. La première est l'assignation ``ptr=tab``. Lorsque ``tab`` est déclaré par la ligne ``unsigned int tab[3]``, le compilateur considère que ``tab`` est une constante qui contiendra toujours l'adresse du premier élément du tableau. Il faut noter que puisque ``tab`` est considéré comme une constante, il est interdit d'en modifier la valeur en utilisant une assignation comme ``tab=tab+1``. Le pointeur ``ptr``, par contre, correspond à une zone mémoire qui contient une adresse. Il est tout à fait possible d'en modifier la valeur. Ainsi, l'assignation ``ptr=tab`` (ou ``ptr=&(tab[0])``) place dans ``ptr`` l'adresse du premier élément du tableau. Les pointeurs peuvent aussi être modifiés en utilisant des expressions arithmétiques. - -.. code-block:: c - - ptr = ptr + 1; // ligne 1 - ptr++; // ligne 2 - ptr = ptr - 2; // ligne 3 - -Après l'exécution de la première ligne, ``ptr`` va contenir l'adresse de l'élément ``1`` du tableau ``tab`` (c'est-à -dire ``&(tab[1])``). Ce résultat peut surprendre car si l'élément ``tab[0]`` se trouve à l'adresse ``0x7fff5fbff750`` c'est cette adresse qui est stockée dans la zone mémoire correspondant au pointeur ``ptr``. On pourrait donc s'attendre à ce que l'expression ``ptr+1`` retourne plutôt la valeur ``0x7fff5fbff751``. Il n'en est rien. En C, lorsque l'on utilise des calculs qui font intervenir des pointeurs, le compilateur prend en compte le type du pointeur qui est utilisé. Comme ``ptr`` est de type ``unsigned int*``, il pointe toujours vers une zone mémoire permettant de stocker un entier non signé sur 32 bits. L'expression ``ptr+1`` revient en fait à calculer la valeur ``ptr+sizeof(unsigned int)`` et donc ``ptr+1`` correspondra à l'adresse ``0x7fff5fbff754``. Pour la même raison, l'exécution de la deuxième ligne placera l'adresse ``0x7fff5fbff758`` dans ``ptr``. Enfin, la dernière ligne calculera ``0x7fff5fbff758-2*sizeof(unsigned int)``, ce qui correspond à ``0x7fff5fbff750``. - -Il est intéressant pour terminer cette première discussion de l'arithmétique des pointeurs, de considérer l'exécution du fragment de code ci-dessous. - -.. literalinclude:: /C/src/ptr_arith.c - :encoding: utf-8 - :language: c - :start-after: ///GGG - :end-before: ///HHH - -L'exécution de ce fragment de code produit une sortie qu'il est intéressant d'analyser. - -.. code-block:: console - - ptr_char contient 0x7fff5fbff750 - 4 est à l'adresse 0x7fff5fbff750 - 3 est à l'adresse 0x7fff5fbff751 - 2 est à l'adresse 0x7fff5fbff752 - 1 est à l'adresse 0x7fff5fbff753 - -Tout d'abord, l'initialisation du pointeur ``ptr_char`` a bien stocké dans ce pointeur l'adresse en mémoire du premier élément du tableau. Ensuite, comme ``ptr_char`` est un pointeur de type ``unsigned char *``, l'expression ``*ptr_char`` a retourné la valeur de l'octet se trouvant à l'adresse ``0x7fff5fbff750``. Le pointeur ``ptr_char`` a été incrémenté en respectant l'arithmétique des pointeurs. Comme ``sizeof(unsigned char)`` retourne ``1``, la valeur stockée dans ``ptr_char`` a été incrémentée d'une seule unité par l'instruction ``ptr_char++``. En analysant les quatre ``unsigned char`` se trouvant aux adresses ``0x7fff5fbff750`` à ``0x7fff5fbff753``, on retrouve bien l'entier ``0x01020304`` qui avait été placé dans ``tab[0]``. - -.. todo:: exemples - - -Les structures --------------- - -Outre les types de données décrits ci-dessus, les programmes informatiques doivent souvent pouvoir manipuler des données plus complexes. À titre d'exemples, un programme de calcul doit pouvoir traiter des nombres complexes, un programme de gestion des étudiants doit traiter des fiches d'étudiants avec nom, prénom, numéro de matricule,... Dans les langages orientés objet comme Java, cela se fait en encapsulant des données de différents types avec les méthodes permettant leur traitement. C n'étant pas un langage orienté objet, il ne permet pas la création d'objets et de méthodes directement associées. Par contre, C permet de construire des types de données potentiellement complexes. - -C permet la définition de structures qui combinent différents types de données simples ou structurés. Contrairement aux langages orientés objet, il n'y a pas de méthode directement associée aux structures qui sont définies. Une structure est uniquement un type de données. Voici quelques exemples de structures simples en C. - -.. literalinclude:: /C/S2-src/struct.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Le premier bloc définit une structure dénommée ``coord`` qui contient trois entiers baptisés ``x``, ``y`` et ``z``. Dans une structure, chaque élément est identifié par son nom et il est possible d'y accéder directement. La variable ``point`` est de type ``struct coord`` et son élément ``x`` est initialisé à la valeur ``1`` tandis que son élément ``z`` est initialisé à la valeur ``3``. La variable ``p`` est également de type ``struct coord`` mais elle n'est pas explicitement initialisée lors de sa déclaration. - -La structure ``struct fract`` définit une fraction qui est composée de deux entiers qui sont respectivement le numérateur et le dénominateur. La structure ``struct student``, elle, définit un type de données qui comprend un numéro de matricule et deux chaînes de caractères. - -Les structures permettent de facilement regrouper des données qui sont logiquement reliées entre elles et doivent être manipulées en même temps. C permet d'accéder facilement à un élément d'une structure en utilisant l'opérateur '``.``'. Ainsi, la structure ``point`` dont nous avons parlé ci-dessus aurait pu être initialisée par les trois expressions ci-dessous : - -.. literalinclude:: /C/S2-src/struct.c - :encoding: utf-8 - :language: c - :start-after: ///CCC - :end-before: ///DDD - - -Dans les premières versions du langage C, une structure devait nécessairement contenir uniquement des données qui ont une taille fixe, c'est-à -dire des nombres, des caractères, des pointeurs ou des tableaux de taille fixe. Il n'était pas possible de stocker des tableaux de taille variable comme une chaîne de caractères ``char []``. Les compilateurs récents [C99]_ permettent de supporter des tableaux flexibles à l'intérieur de structures. Nous ne les utiliserons cependant pas dans le cadre de ce cours. - -Les structures sont utilisées dans différentes librairies et appels système sous Unix et Linux. Un exemple classique est la gestion du temps sur un système Unix. Un système informatique contient généralement une horloge dite `temps-réel` qui est en pratique construite autour d'un cristal qui oscille à une fréquence fixée. Ce cristal est piloté par un circuit électronique qui compte ses oscillations, ce qui permet de mesurer le passage du temps. Le système d'exploitation utilise cette horloge `temps réel` pour diverses fonctions et notamment la mesure du temps du niveau des applications. - -Un système de type Unix maintient différentes structures qui sont associées à la mesure du temps [#ftimelibc]_. La première sert à mesurer le nombre de secondes et de microsecondes qui se sont écoulées depuis le premier janvier 1970. Cette structure, baptisée ``struct timeval`` est définie dans `sys/time.h`_ comme suit : - -.. code-block:: c - - struct timeval { - time_t tv_sec; /* seconds since Jan. 1, 1970 */ - suseconds_t tv_usec; /* and microseconds */ - }; - -Cette structure est utilisée par des appels système tels que `gettimeofday(2)`_ pour notamment récupérer l'heure courante ou les appels de manipulation de temporisateurs (`timers` en anglais) tels que `getitimer(2)`_ / `setitimer(2)`_. Elle est aussi utilisée par la fonction `time(3posix)`_ de la librairie standard et est très utile pour mesurer les performances d'un programme. - -Les structures sont également fréquemment utilisées pour représenter des formats de données spéciaux sur disque comme le format des répertoires [#fdirent]_ ou les formats de paquets qui sont échangés sur le réseau [#freseau]_. - -La définition de ``struct timeval`` utilise une fonctionnalité fréquemment utilisée du C : la possibilité de définir des alias pour des noms de type de données existants. Cela se fait en utilisant l'opérateur ``typedef``. En C, il est possible de renommer des types de données existants. Ainsi, l'exemple ci-dessous utilise ``typedef`` pour définir ``Entier`` comme alias pour le type ``int`` et ``Fraction`` pour la structure ``struct fraction``. - -.. literalinclude:: /C/S2-src/typedef.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -Les types ``Entier`` et ``int`` peuvent être utilisés de façon interchangeable à l'intérieur du programme une fois qu'ils ont été définis. - -.. note:: ``typedef`` en pratique - - Renommer des types de données a des avantages et des inconvénients dont il faut être conscient pour pouvoir l'utiliser à bon escient. L'utilisation de ``typedef`` peut faciliter la lecture et la portabilité de certains programmes. Lorsqu'un ``typedef`` est associé à une structure, cela facilite la déclaration de variables de ce type et permet le cas échéant de modifier la structure de données ultérieurement sans pour autant devoir modifier l'ensemble du programme. Cependant, contrairement aux langages orientés objet, des méthodes ne sont pas directement associées aux structures et la modification d'une structure oblige souvent à vérifier toutes les fonctions qui utilisent cette structure. L'utilisation de ``typedef`` permet de clarifier le rôle de certains types de données ou valeurs de retour de fonctions. À titre d'exemple, l'appel système `read(2)`_ qui permet notamment de lire des données dans un fichier retourne le nombre d'octets qui ont été lus après chaque appel. Cette valeur de retour est de type ``ssize_t``. L'utilisation de ces types permet au compilateur de vérifier que les bons types de données sont utilisés lors des appels de fonctions. - - ``typedef`` est souvent utilisé pour avoir des identifiants de types de données plus courts. Par exemple, il est très courant de remplacer le types ``unsigned`` par les abréviations ci-dessous. - - .. literalinclude:: /C/S2-src/typedef.c - :encoding: utf-8 - :language: c - :start-after: ///EEE - :end-before: ///FFF - - Soyez prudents si vous utilisez des ``typedef`` pour redéfinir des pointeurs. En C, il est tout à fait valide d'écrire les lignes suivantes. - - .. literalinclude:: /C/S2-src/typedef.c - :encoding: utf-8 - :language: c - :start-after: ///CCC - :end-before: ///DDD - - Malheureusement, il y a un risque dans un grand programme que le développeur oublie que ces types de données correspondent à des pointeurs qui doivent être manipulés avec soin. Le `Linux kernel coding style <http://www.kernel.org/doc/Documentation/CodingStyle>`_ contient une discussion intéressante sur l'utilisation des ``typedef``. - - -Les pointeurs sont fréquemment utilisés lors de la manipulation de structures. Lorsqu'un pointeur pointe vers une structure, il est utile de pouvoir accéder facilement aux éléments de la structure. Le langage C supporte deux notations pour représenter ces accès aux éléments d'une structure. La première notation est ``(*ptr).elem`` où ``ptr`` est un pointeur et ``elem`` l'identifiant d'un des éléments de la structure pointée par ``ptr``. Cette notation est en pratique assez peu utilisée. La notation la plus fréquente est ``ptr->elem`` dans laquelle ``ptr`` et ``->elem`` sont respectivement un pointeur et un identifiant d'élément. L'exemple ci-dessous illustre l'initialisation de deux fractions en utilisant ces notations. - -.. literalinclude:: /C/S2-src/structptr.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Les pointeurs sont fréquemment utilisés en combinaison avec des structures et on retrouve très souvent la seconde notation dans des programmes écrits en C. - - -Les fonctions -------------- - -Comme la plupart des langages, le C permet de faciliter la compréhension d'un programme -en le découpant en de nombreuses fonctions. Chacune réalise une -tâche simple. Tout comme Java, C permet la définition de fonctions qui ne retournent aucun résultat. Celles-ci sont de type ``void`` comme l'exemple trivial ci-dessous. - -.. literalinclude:: /C/S2-src/fct.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -La plupart des fonctions utiles retournent un résultat qui peut être une donnée d'un des types standard ou une structure. Cette utilisation est similaire à ce que l'on trouve dans des langages comme Java. Il faut cependant être attentif à la façon dont le langage C traite les arguments des fonctions. Le langage C utilise le `passage par valeur` des arguments. Lorsqu'une fonction est exécutée, elle reçoit les valeurs de ces arguments. Ces valeurs sont stockées dans une zone mémoire qui est locale à la fonction. Toute modification faite sur la valeur d'une variable à l'intérieur d'une fonction est donc locale à cette fonction. Les deux fonctions ci-dessous ont le même résultat et aucune des deux n'a d'effet de bord. - -.. literalinclude:: /C/S2-src/fct.c - :encoding: utf-8 - :language: c - :start-after: ///CCC - :end-before: ///DDD - -Il faut être nettement plus attentif lorsque l'on écrit des fonctions qui utilisent des pointeurs comme arguments. Lorsqu'une fonction a un argument de type pointeur, celui-ci est passé par valeur, mais connaissant la valeur du pointeur, il est possible à la fonction de modifier le contenu de la zone mémoire pointée par le pointeur. Ceci est illustré par l'exemple ci-dessous. - -.. literalinclude:: /C/S2-src/fct.c - :encoding: utf-8 - :language: c - :start-after: ///EEE - :end-before: ///FFF - -Lors de l'exécution de la fonction ``f``, le programme ci-dessus affiche à la console la sortie suivante : - -.. literalinclude:: /C/S2-src/fct.out - :encoding: utf-8 - :language: console - -Cet exemple illustre aussi une contrainte imposée par le langage C sur l'ordre de définition des fonctions. Pour que les fonctions ``times_two`` et ``timestwo`` puissent être utilisées à l'intérieur de la fonction ``f``, il faut qu'elles aient été préalablement définies. Dans l'exemple ci-dessus, cela s'est fait en plaçant la définition des deux fonctions avant leur utilisation. C'est une règle de bonne pratique utilisable pour de petits programmes composés de quelques fonctions. Pour des programmes plus larges, il est préférable de placer au début du code source la signature des fonctions qui y sont définies. La signature d'une fonction comprend le type de valeur de retour de la fonction, son nom et les types de ses arguments. Généralement, ces déclarations sont regroupées à l'intérieur d'un :term:`fichier header` dont le nom se termine par ``.h``. - -.. literalinclude:: /C/S2-src/fct.h - :encoding: utf-8 - :language: c - :start-after: ///HHH - :end-before: ///III - -Les fonctions peuvent évidemment recevoir également des tableaux comme arguments. Cela permet par exemple d'implémenter une fonction qui calcule la longueur d'une chaîne de caractères en itérant dessus jusqu'à trouver le caractère de fin de chaîne. - -.. literalinclude:: /C/S2-src/strlenptr.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -.. spelling:: - - ième - -Tout comme cette fonction peut accéder au `ième` caractère de la chaîne passée en argument, elle peut également et sans aucune restriction modifier chacun des caractères de cette chaîne. Par contre, comme le pointeur vers la chaîne de caractères est passé par valeur, la fonction ne peut pas modifier la zone mémoire qui est pointée par l'argument. - -Un autre exemple de fonctions qui manipulent les tableaux sont des fonctions mathématiques qui traitent des vecteurs par exemple. - -.. literalinclude:: /C/S2-src/fctargs.c - :encoding: utf-8 - :language: c - :start-after: ///CCC - :end-before: ///DDD - - -Ces deux fonctions peuvent être utilisées par le fragment de code ci-dessous : - -.. literalinclude:: /C/S2-src/fctargs.c - :encoding: utf-8 - :language: c - :start-after: ///EEE - :end-before: ///FFF - - -.. note:: Attention à la permissivité du compilateur C - - Certains langages comme Java sont fortement typés et le compilateur contient de nombreuses vérifications, notamment sur les types de données utilisés, qui permettent d'éviter un grand nombre d'erreurs. Le langage C est lui nettement plus libéral. Les premiers compilateurs C étaient très permissifs notamment sur les types de données passés en arguments. Ainsi, un ancien compilateur C accepterait probablement sans broncher les appels suivants : - - .. literalinclude:: /C/S2-src/fctargs.c - :encoding: utf-8 - :language: c - :start-after: ///GGG - :end-before: ///HHH - - Dans ce fragment de programme, l'appel à ``print_vecteur`` est tout à fait valide. Par contre, l'appel à ``plusun`` est lui erroné puisque le premier argument est un tableau d'entiers (ou plus précisément un pointeur vers le premier élément d'un tableau d'entiers) alors que la fonction ``plusun`` attend un entier. Inversement, le second argument est un entier à la place d'un tableau d'entiers. Cette erreur n'empêche pas le compilateur `gcc(1)`_ de compiler le programme correspondant. Il émet cependant le :term:`warning` suivant : - - .. code-block:: console - - warning: passing argument 1 of ‘plusun’ makes integer from pointer without a cast - warning: passing argument 2 of ‘plusun’ makes pointer from integer without a cast - - De nombreux programmeurs débutants ignorent souvent les warnings émis par le compilateur et se contentent d'avoir un programme compilé. C'est la source de nombreuses erreurs et de nombreux problèmes. Dans l'exemple ci-dessus, l'exécution de l'appel ``plusun(vecteur,N)`` provoquera une tentative d'accès à la mémoire dans une zone qui n'est pas allouée au processus. Dans ce cas, la tentative d'accès est bloquée par le système et provoque l'arrêt immédiat du programme sur une :term:`segmentation fault`. Dans d'autres cas, des erreurs plus subtiles mais du même type ont provoqué des problèmes graves de sécurité dans des programmes écrits en langage C. Nous y reviendrons ultérieurement. - -Pour terminer, mentionnons que les fonctions écrites en C peuvent utiliser des structures et des pointeurs vers des structures comme arguments. Elles peuvent aussi retourner des structures comme résultat. Ceci est illustré par deux variantes de fonctions permettant d'initialiser une fraction et de déterminer si deux fractions sont égales [#fegal]_. - -.. literalinclude:: /C/S2-src/struct.c - :encoding: utf-8 - :language: c - :start-after: ///EEE - :end-before: ///FFF - -Considérons d'abord les fonctions ``init`` et ``equal``. ``init`` est une fonction qui construit une structure sur base d'arguments entiers et retourne la valeur construite. ``equal`` quant à elle reçoit comme arguments les valeurs de deux structures. Elle peut accéder à tous les éléments des structures passées en argument. Comme ces structures sont passées par valeur, toute modification aux éléments de la structure est locale à la fonction ``equal`` et n'est pas répercutée sur le code qui a appelé la fonction. - -Les fonctions ``initptr`` et ``equalptr`` utilisent toutes les deux des pointeurs vers des ``struct fraction`` comme arguments. Ce faisant, elles ne peuvent modifier la valeur de ces pointeurs puisqu'ils sont passés comme valeurs. Par contre, les deux fonctions peuvent bien entendu modifier les éléments de la structure qui se trouvent dans la zone de mémoire pointée par le pointeur. C'est ce que ``initptr`` fait pour initialiser la structure. ``equalptr`` par contre se contente d'accéder aux éléments des structures passées en argument sans les modifier. Le fragment de code ci-dessous illustre comment ces fonctions peuvent être utilisées en pratique. - -.. literalinclude:: /C/S2-src/struct.c - :encoding: utf-8 - :language: c - :start-after: ///GGG - :end-before: ///HHH - - -Les expressions de manipulation de bits ---------------------------------------- - -La plupart des langages de programmation sont spécialisés dans la manipulation des types de données classiques comme les entiers, les réels et les chaînes de caractères. Comme nous l'avons vu, le langage C permet de traiter ces types de données. En outre, il permet au programmeur de pouvoir facilement manipuler les bits qui se trouvent en mémoire. Pour cela, le langage C définit des expressions qui correspondent à la plupart des opérations de manipulation de bits que l'on retrouve dans les langages d'assemblage. Les premières opérations sont les opérations logiques. - -La première opération logique est la négation :term:`négation` (:term:`NOT` en anglais). Elle prend comme argument un bit et retourne le bit inverse. Comme toutes les opérations logiques, elle peut se définir simplement sous la forme d'une table de vérité. Dans des formules mathématiques, la négation est souvent représentée sous la forme :math:`\neg{A}`. - -=== =========== -A NOT(A) -=== =========== -0 1 -1 0 -=== =========== - -La deuxième opération est la :term:`conjonction logique` (:term:`AND` en anglais). Cette opération prend deux arguments binaires et retourne un résultat binaire. Dans des formules mathématiques, la conjonction logique est souvent représentée sous la forme :math:`A \wedge B`. -Elle se définit par la table de vérité suivante : - -=== === ============ -A B A AND B -=== === ============ -0 0 0 -0 1 0 -1 0 0 -1 1 1 -=== === ============ - -La troisième opération est la :term:`disjonction logique` (:term:`OR` en anglais). Cette opération prend deux arguments binaires. Dans des formules mathématiques, la disjonction logique est souvent représentée sous la forme :math:`A \vee B`. -Elle se définit par la table de vérité suivante. - -=== === =========== -A B A OR B -=== === =========== -0 0 0 -0 1 1 -1 0 1 -1 1 1 -=== === =========== - -Enfin, une dernière opération logique intéressante est le :term:`ou exclusif` (:term:`XOR` en anglais). Celle-ci se définit par la table de vérité ci-dessous. Cette opération est parfois représentée mathématiquement comme :math:`A \oplus B`. - -=== === ============ -A B A XOR B -=== === ============ -0 0 0 -0 1 1 -1 0 1 -1 1 0 -=== === ============ - -.. spelling:: - - De Morgan - - -Ces opérations peuvent être combinées entre elles. Pour des raisons technologiques, les circuits logiques implémentent plutôt les opérations NAND (qui équivaut à AND suivi de NOT) ou NOR (qui équivaut à OR suivi de NOT). Il est également important de mentionner les lois formulées par De Morgan qui peuvent se résumer par les équations suivantes : - - - :math:`\neg{(A \wedge B)}=\neg{A} \vee \neg{B}` - - :math:`\neg{(A \vee B)}=\neg{A} \wedge \neg{B}` - -Ces opérations binaires peuvent s'étendre à des séquences de bits. Voici quelques exemples qui permettent d'illustrer ces opérations sur des octets. - -.. literalinclude:: /C/S2-src/exprbin.out - :encoding: utf-8 - :language: console - -En C, ces expressions logiques s'utilisent comme dans le fragment de code suivant. En général, elles s'utilisent sur des représentations non signées, souvent des ``unsigned char`` ou des ``unsigned int``. - -.. literalinclude:: /C/S2-src/exprbin.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -En pratique, les opérations logiques sont utiles pour effectuer des manipulations au niveau des bits de données stockées en mémoire. Une utilisation fréquente dans certaines applications réseaux ou systèmes est de forcer certains bits à prendre la valeur ``0`` ou ``1``. La conjonction logique permet de forcer facilement un bit à zéro tandis que la disjonction logique permet de forcer facilement un bit à un. L'exemple ci-dessous montre comment forcer les valeurs de certains bits dans un ``unsigned char``. Il peut évidemment se généraliser à des séquences de bits plus longues. - -.. literalinclude:: /C/S2-src/exprbin.c - :encoding: utf-8 - :language: c - :start-after: ///CCC - :end-before: ///DDD - -.. spelling:: - - Vernam - -L'opération XOR joue un rôle important dans certaines applications. La plupart des méthodes de chiffrement et de déchiffrement utilisent de façon extensive cette opération. Une des propriétés intéressantes de l'opération XOR est que :math:`(A \oplus B) \oplus B=A`. Cette propriété est largement utilisée par les méthodes de chiffrement. La méthode développée par Vernam au début du vingtième siècle s'appuie sur l'opération XOR. Pour transmettre un message `M` de façon sûre, elle applique l'opération XOR bit à bit entre tous les bits du message `M` et une clé `K` doit avoir au moins le même nombre de bits que `M`. Si cette clé `K` est totalement aléatoire et n'est utilisée qu'une seule fois, alors on parle de *one-time-pad*. On peut montrer que dans ce cas, la méthode de chiffrement est totalement sûre. En pratique, il est malheureusement difficile d'avoir une clé totalement aléatoire qui soit aussi longue que le message à transmettre. Le programme ci-dessous implémente cette méthode de façon triviale. La fonction `memfrob(3)`_ de la librairie :term:`GNU` utilise également un chiffrement via un XOR. - -.. literalinclude:: /C/S2-src/xor.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -.. note:: Ne pas confondre expressions logiques et opérateurs binaires. - - En C, les symboles utilisés pour les expressions logiques (``||`` et ``&&``) sont très proches de ceux utilisés pour représenter les opérateurs binaires (`|` et `&`). Il arrive parfois qu'un développeur confonde ``&`` avec ``&&``. Malheureusement, le compilateur ne peut pas détecter une telle erreur car dans les deux cas le résultat attendu est généralement du même type. - - .. code-block:: console - - 0b0100 & 0b0101 = 0b0100 - 0b0100 && 0b0101 = 0b0001 - 0b0100 | 0b0101 = 0b0101 - 0b0100 || 0b0101 = 0b0001 - - Un autre point important à mentionner concernant les expressions logiques est qu'en C celles-ci sont évaluées de gauche à droite. Cela implique que dans l'expression ``( expr1 && expr2 )``, le compilateur C va d'abord évaluer l'expression ``expr1``. Si celle-ci est évaluée à la valeur ``0``, la seconde expression ne sera pas évaluée. Cela peut être très utile lorsque l'on doit exécuter du code si un pointeur est non-``NULL`` et qu'il pointe vers une valeur donnée. Dans ce cas, la condition sera du type ``((ptr != NULL) && (ptr->den > 0))``. - -Pour terminer, le langage C supporte des expressions permettant le décalage à gauche ou à droite à l'intérieur d'une suite de bits non signée. - - - ``a = n >> B`` décale les bits représentants ``n`` de ``B`` bits vers la droite et place le résultat dans la variable ``a``. - - ``a = n << B`` décale les bits représentants ``n`` de ``B`` bits vers la gauche et place le résultat dans la variable ``a``. - -Ces opérations de décalage permettent différentes manipulations de bits. À titre d'exemple, la fonction ``int2bin`` utilise à la fois des décalages et des masques pour calculer la représentation binaire d'un entier non signé et la placer dans une chaîne de caractères. - -.. literalinclude:: /C/S2-src/exprbin.c - :encoding: utf-8 - :language: c - :start-after: ///EEE - :end-before: ///FFF - - -.. rubric:: Footnotes - - -.. [#fexposant] En pratique, le format binaire contient :math:`127+exp` en simple précision et non l'exposant `exp`. Ce choix facilite certaines comparaisons entre nombres représentés en virgule flottante. Une discussion détaillée de la représentation binaire des nombres en virgule flottante sort du cadre de ce cours dédié aux systèmes informatiques. Une bonne référence à ce sujet est [Goldberg1991]_. - -.. [#fexemple] Source : http://en.wikipedia.org/wiki/Single-precision_floating-point_format - -.. [#fstackjava] En pratique, l'espace mémoire accessible à un programme Java est limité par différents facteurs. Voir notamment le paramètre ``-Xm`` de la machine virtuelle Java http://docs.oracle.com/javase/6/docs/technotes/tools/solaris/java.html - -.. [#ftimelibc] Une description plus détaillée des différentes possibilités de mesure du temps via les fonctions de la librairie standard est disponible dans le chapitre `21 <http://www.gnu.org/software/libc/manual/html_node/Date-and-Time.html>`_ du `manuel <http://www.gnu.org/software/libc/manual/html_node/Date-and-Time.html>`_ de la :term:`libc`. - -.. [#fdirent] Voir notamment `fs(5)`_ pour des exemples relatifs aux systèmes de fichiers. Une analyse détaillée des systèmes de fichiers sort du cadre de ce cours. - -.. spelling:: - - IP - -.. [#freseau] Parmi les exemples simples, on peut citer la structure ``struct ipv6hdr`` qui correspond à l'entête du protocole IP version 6 et est définie dans `linux/ipv6.h`_. - -.. [#fegal] Cette définition de l'égalité entre fractions suppose que les fractions à comparer sont sous forme irréductible. Le lecteur est invité à écrire la fonction générale permettant de tester l'égalité entre fractions réductibles. diff --git a/Theorie/C/figures/figures-001-c.png b/Theorie/C/figures/figures-001-c.png deleted file mode 100644 index 99354a4e0b5a8d096dda4ede22f501ff937d0e5f..0000000000000000000000000000000000000000 Binary files a/Theorie/C/figures/figures-001-c.png and /dev/null differ diff --git a/Theorie/C/figures/figures-007-c.png b/Theorie/C/figures/figures-007-c.png deleted file mode 100644 index 79332d99e8efb28736d8d949a0e7505f33a46306..0000000000000000000000000000000000000000 Binary files a/Theorie/C/figures/figures-007-c.png and /dev/null differ diff --git a/Theorie/C/intro-C.rst b/Theorie/C/intro-C.rst deleted file mode 100644 index 566d3e500b2bb2fc32d4886fafef0d7251ea8125..0000000000000000000000000000000000000000 --- a/Theorie/C/intro-C.rst +++ /dev/null @@ -1,229 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012, 2019 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Le langage C -============ - - -Différents langages permettent au programmeur de construire des programmes qui seront exécutés par le processeur. En réalité, le processeur ne comprend qu'un langage : le langage machine. Ce langage est un langage binaire dans lequel toutes les commandes et toutes les données sont représentés sous la forme de séquences de bits. - -.. commentaire Sur certains processeurs, ces séquences ont une taille fixe (par exemple 32 ou 64 bits). C'est le cas par exemple sur certains processeurs de type :term:`RISC`. D'autres processeurs supportent des instructions en langage machine qui sont encodées sous la forme d'un nombre variables de bits. C'est le cas de processeurs de type :term:`CISC` et notamment les processeurs de la famille :term:`x86` développés initialement par intel et qui sont largement utilisés de nos jours. - -Le langage machine est peu adapté aux humains et il est extrêmement rare qu'un informaticien doive manipuler des programmes directement en langage machine. Par contre, pour certaines tâches bien spécifiques, comme par exemple le développement de routines spéciales qui doivent être les plus rapides possibles ou qui doivent interagir directement avec le matériel, il est important de pouvoir efficacement générer du langage machine. Cela peut se faire en utilisant un langage d'assemblage. Chaque famille de processeurs a un langage d'assemblage qui lui est propre. Le langage d'assemblage permet d'exprimer de façon symbolique les différentes instructions qu'un processeur doit exécuter. Nous aurons l'occasion de traiter à plusieurs reprises des exemples en langage d'assemblage dans le cadre de ce cours. Cela nous permettra de mieux comprendre la façon dont le processeur fonctionne et exécute les programmes. Le langage d'assemblage est converti en langage machine grâce à un :term:`assembleur`. - -Le langage d'assemblage est le plus proche du processeur. Il permet d'écrire des programmes compacts et efficaces. C'est aussi souvent la seule façon d'utiliser des instructions spéciales du processeur qui permettent d'interagir directement avec le matériel pour par exemple commander les dispositifs d'entrée/sortie. C'est essentiellement dans les systèmes embarqués qui disposent de peu de mémoire et pour quelques fonctions spécifiques des systèmes d'exploitation que le langage d'assemblage est utilisé de nos jours. La plupart des programmes applicatifs et la grande majorité des systèmes d'exploitation sont écrits dans des langages de plus haut niveau. - -Le langage :term:`C` [KernighanRitchie1998]_, développé dans les années 70 pour écrire les premières versions du système d'exploitation :term:`Unix`, est aujourd'hui l'un des langages de programmation les plus utilisés pour développer des programmes qui doivent être rapides ou doivent interagir avec le matériel. La plupart des systèmes d'exploitation sont écrits en langage C. - -Le langage C a été conçu à l'origine comme un langage proche du processeur qui peut être facilement compilé, c'est-à -dire traduit en langage machine, tout en conservant de bonnes performances. - -La plupart des livres qui abordent la programmation en langage C commencent par présenter un programme très simple qui affiche à l'écran le message `Hello, world!`. - -.. literalinclude:: src/hello.c - :language: c - -Pour être exécuté, ce programme doit être compilé. Il existe de nombreux compilateurs permettant de transformer le langage C en langage machine. Dans le cadre de ce cours, nous utiliserons `gcc(1)`_. Dans certains cas, nous pourrons être amenés à utiliser d'autres compilateurs comme :term:`llvm`. - -La compilation du programme :download:`src/hello.c` peut s'effectuer comme suit sur une machine de type Unix : - -.. code-block:: console - - $ gcc -Wall -o hello hello.c - $ ls -l - total 80 - -rwxr-xr-x 1 obo obo 8704 15 jan 22:32 hello - -rw-r--r-- 1 obo obo 288 15 jan 22:32 hello.c - -`gcc(1)`_ supporte de très nombreuses options et nous aurons l'occasion de discuter de plusieurs d'entre elles dans le cadre de ce cours. Pour cette première utilisation, nous avons choisi l'option `-Wall` qui force `gcc(1)`_ à afficher tous les messages de type :term:`warning` (dans cet exemple il n'y en a pas) et l'option `-o` suivie du nom de fichier `hello` qui indique le nom du fichier dans lequel le programme exécutable doit être sauvegardé par le compilateur [#fgccaout]_. - -Lorsqu'il est exécuté, le programme `hello` affiche simplement le message suivant sur la sortie standard : - -.. code-block:: console - - $ ./hello - Hello, world! - $ - -Même si ce programme est très simple, il illustre quelques concepts de base en langage C. Tout d'abord comme en Java, les compilateurs récents supportent deux façons d'indiquer des commentaires en C : - - - un commentaire sur une ligne est précédé des caractères `//` - - un commentaire qui comprend plusieurs lignes débute par `/*` et se termine par `*/` - -Ensuite, un programme écrit en langage C comprend principalement des expressions en langage C mais également des expressions qui doivent être traduites par le :term:`préprocesseur`. Lors de la compilation d'un fichier en langage C, le compilateur commence toujours par exécuter le préprocesseur. Celui-ci implémente différentes formes de macros qui permettent notamment d'inclure des fichiers (directives ``#include``), de compiler de façon conditionnelle certaines lignes ou de définir des constantes. Nous verrons différentes utilisations du préprocesseur C dans le cadre de ce cours. À ce stade, les trois principales fonctions du préprocesseur sont : - - - définir des substitutions via la macro ``#define``. Cette macro est très fréquemment utilisée pour définir des constantes ou des substitutions qui sont valables dans l'ensemble du programme. - - .. code-block:: c - - #define ZERO 0 - #define STRING "SINF1252" - - - importer (directive ``#include``) un fichier. Ce fichier contient généralement des prototypes de fonctions et des constantes. En langage C, ces fichiers qui sont inclus dans un programme sont appelés des `header files` et ont par convention un nom se terminant par ``.h``. Le programme :download:`src/hello.c` ci-dessus importe deux fichiers `headers` standards : - - - ``<stdio.h>`` : contient la définition des principales fonctions de la librairie standard permettant l'interaction avec l'entrée et la sortie standard, et notamment `printf(3)`_ - - ``<stdlib.h>``: contient la définition de différentes fonctions et constantes de la librairie standard et notamment ``EXIT_SUCCESS`` et ``EXIT_FAILURE``. Ces constantes sont définies en utilisant la macro ``#define`` du préprocesseur - - .. code-block:: c - - #define EXIT_FAILURE 1 - #define EXIT_SUCCESS 0 - - - inclure du code sur base de la valeur d'une constante définie par un ``#define``. Ce contrôle de l'inclusion de code sur base de la valeur de constantes est fréquemment utilisé pour ajouter des lignes qui ne doivent être exécutées que lorsque l'on veut déboguer un programme. C'est aussi souvent utilisé pour faciliter la portabilité d'un programme entre différentes variantes de Unix, mais cette utilisation sort du cadre de ce cours. - - .. code-block:: c - - #define DEBUG - /* ... */ - #ifdef DEBUG - printf("debug : ..."); - #endif /* DEBUG */ - -Il est également possible de définir des macros qui prennent un ou plusieurs paramètres [CPP]_. - - -Les `headers` standards sont placés dans des répertoires bien connus du système. Sur la plupart des variantes de Unix ils se trouvent dans le répertoire ``/usr/include/``. Nous aurons l'occasion d'utiliser régulièrement ces fichiers standards dans le cadre du cours. - -Le langage Java a été largement inspiré du langage C et de nombreuses constructions syntaxiques sont similaires en Java et en C. Un grand nombre de mots clés en C ont le même rôle qu'en Java. Les principaux types de données primitifs supportés par le C sont : - - - ``int`` et ``long`` : utilisés lors de la déclaration d'une variable de type entier - - ``char`` : utilisé lors de la déclaration d'une variable permettant de stocker un caractère - - ``double`` et ``float`` : utilisés lors de la déclaration d'une variable permettant de stocker un nombre représenté en virgule flottante. - -Notez que dans les premières versions du langage C, contrairement à Java, il n'y avait pas de type spécifique permettant de représenter un booléen. Dans de nombreux programmes écrits en C, les booléens sont représentés par des entiers et les valeurs booléennes sont définies [#fbool]_ comme suit. - -.. code-block:: c - - #define false 0 - #define true 1 - -Les compilateurs récents qui supportent le type booléen permettent de déclarer des variables de type ``bool`` et contiennent les définitions suivantes [#fbool]_ dans le header standard `stdbool.h`_ de [C99]_. - -.. code-block:: c - - #define false (bool)0 - #define true (bool)1 - -Au-delà des types de données primitifs, Java et C diffèrent et nous aurons l'occasion d'y revenir dans un prochain chapitre. Le langage C n'est pas un langage orienté objet et il n'est donc pas possible de définir d'objet avec des méthodes spécifiques en C. C permet la définition de structures, d'unions et d'énumérations sur lesquelles nous reviendrons. - -En Java, les chaînes de caractères sont représentées grâce à l'objet ``String``. En C, une chaîne de caractères est représentée sous la forme d'un tableau de caractères dont le dernier élément contient la valeur ``\0``. Alors que Java stocke les chaînes de caractères dans un objet avec une indication de leur longueur, en C il n'y a pas de longueur explicite pour les chaînes de caractères mais le caractère ``\0`` sert de marqueur de fin de chaîne de caractères. Lorsque le langage C a été développé, ce choix semblait pertinent, notamment pour des raisons de performance. Avec le recul, ce choix pose question [Kamp2011]_ et nous y reviendrons lorsque nous aborderons certains problèmes de sécurité. - -.. literalinclude:: src/string.c - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -L'exemple ci-dessus illustre l'utilisation d'un tableau de caractères pour stocker une chaîne de caractères. Lors de son exécution, ce fragment de code affiche ``String : java`` sur la sortie standard. Le caractère spécial ``\n`` indique un passage à la ligne. `printf(3)`_ supporte d'autres caractères spéciaux qui sont décrits dans sa page de manuel. - -Au niveau des constructions syntaxiques, on retrouve les mêmes boucles et tests en C et en Java : - - - test ``if (condition) { ... } else { ... }`` - - boucle ``while (condition) { ... }`` - - boucle ``do { ... } while (condition);`` - - boucle ``for (init; condition; incr) { ... }`` - -En Java, les conditions sont des expressions qui doivent retourner un résultat de type ``boolean``. Le langage C est beaucoup plus permissif puisqu'une condition est une expression qui retourne un nombre entier. - -La plupart des expressions et conditions en C s'écrivent de la même façon qu'en Java. - -Après ce rapide survol du langage C, revenons à notre programme :download:`src/hello.c`. Tout programme C doit contenir une fonction nommée ``main`` dont la signature [#fmain]_ est : - -.. code-block:: c - - int main(int argc, char *argv[]) - -Lorsque le système d'exploitation exécute un programme C compilé, il démarre son exécution par la fonction ``main`` et passe à cette fonction les arguments fournis en ligne de commande [#fenvp]_. Comme l'utilisateur peut passer un nombre quelconque d'arguments, il faut que le programme puisse déterminer combien d'arguments sont utilisés. En Java, la méthode ``main`` a comme signature ``public static void main(String args[])`` et l'attribut ``args.length`` permet de connaître le nombres de paramètres passés en arguments d'un programme. En C, le nombre de paramètres est passé dans la variable entière ``argc`` et le tableau de chaînes de caractères ``char *argv[]`` contient tous les arguments. Le programme :download:`src/cmdline.c` illustre comment un programme peut accéder à ses arguments. - - -.. literalinclude:: src/cmdline.c - :language: c - -Par convention, en C le premier argument (se trouvant à l'indice ``0`` du tableau ``argv``) est le nom du programme qui a été exécuté par l'utilisateur. Une exécution de ce programme est illustrée ci-dessous. - -.. literalinclude:: src/cmdline.out - :language: console - -Outre le traitement des arguments, une autre différence importante entre Java et C est la valeur de retour de la fonction ``main``. En C, la fonction ``main`` retourne un entier. Cette valeur de retour est passée par le système d'exploitation au programme (typiquement un :term:`shell` ou interpréteur de commandes) qui a demandé l'exécution du programme. Grâce à cette valeur de retour il est possible à un programme d'indiquer s'il s'est exécuté correctement ou non. Par convention, un programme qui s'exécute sous Unix doit retourner ``EXIT_SUCCESS`` lorsqu'il se termine correctement et ``EXIT_FAILURE`` en cas d'échec. La plupart des programmes fournis avec un Unix standard respectent cette convention. Dans certains cas, d'autres valeurs de retour non nulles sont utilisées pour fournir plus d'informations sur la raison de l'échec. -En pratique, l'échec d'un programme peut être dû aux arguments incorrects fournis par l'utilisateur ou à des fichiers qui sont inaccessibles. - -À titre d'illustration, le programme :download:`src/failure.c` est le programme le plus simple qui échoue lors de son exécution. - -.. literalinclude:: src/failure.c - :language: c - -Enfin, le dernier point à mentionner concernant notre programme :download:`src/hello.c` est la fonction ``printf``. Cette fonction de la librairie standard se retrouve dans la plupart des programmes écrits en C. Elle permet l'affichage de différentes formes de textes sur la sortie standard. Comme toutes les fonctions de la librairie standard, elle est documentée dans sa page de manuel `printf(3)`_. `printf(3)`_ prend un nombre variable d'arguments. Le premier argument est une chaîne de caractères qui spécifie le format de la chaîne de caractères à afficher. Une présentation détaillée de `printf(3)`_ prendrait de nombreuses pages. À titre d'exemple, voici un petit programme utilisant `printf(3)`_ - -.. literalinclude:: src/printf.c - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Lors de son exécution, ce programme affiche : - -.. literalinclude:: src/printf.out - :language: console - -.. todo: expliquer les fonctions au minimum void et int -.. todo: prendre comme exemple un filtre qui fait isdigit et extrait d'un stream les chiffres uniquement. faisable avec getchar - - -Le langage C permet bien entendu la définition de fonctions. Outre la fonction ``main`` qui doit être présente dans tout programme, le langage C permet la définition de fonctions qui retournent ou non une valeur. En C, comme en Java, une fonction de type ``void`` ne retourne aucun résultat tandis qu'une fonction de type ``int`` retournera un entier. Le programme ci-dessous présente deux fonctions simples. La première, ``usage`` ne retourne aucun résultat. Elle affiche un message d'erreur sur la sortie d'erreur standard et termine le programme via `exit(2)`_ avec un code de retour indiquant un échec. La seconde, ``digit`` prend comme argument un caractère et retourne ``1`` si c'est un chiffre et ``0`` sinon. Le code de cette fonction peut paraître bizarre à un programmeur habitué à Java. En C, les `char` sont représentés par l'entier qui correspond au caractère dans la table des caractères utilisées (voir :rfc:`20` pour une table ASCII simple). -Toutes les tables de caractères placent les chiffres ``0`` à ``9`` à des positions consécutives. En outre, en C une expression a priori booléenne comme ``a < b`` est définie comme ayant la valeur ``1`` si elle est vraie et ``0`` sinon. Il en va de même pour les expressions qui sont combinées en utilisant ``&&`` ou ``||``. Enfin, les fonctions `getchar(3)`_ et `putchar(3)`_ sont des fonctions de la librairie standard qui permettent respectivement de lire (écrire) un caractère sur l'entrée (la sortie) standard. - - -.. literalinclude:: src/filterdigit.c - :language: c - - - - - -.. topic:: Pages de manuel - - Les systèmes d'exploitation de la famille Unix contiennent un grand nombre de librairies, d'appels systèmes et d'utilitaires. Toutes ces fonctions et tous ces programmes sont documentés dans des pages de manuel qui sont accessibles via la commande ``man``. Les pages de manuel sont organisées en 8 sections. - - - Section 1: Utilitaires disponibles pour tous les utilisateurs - - Section 2: Appels systèmes en C - - Section 3: Fonctions de la librairie - - Section 4: Fichiers spéciaux - - Section 5: Formats de fichiers et conventions pour certains types de fichiers - - Section 6: Jeux - - Section 7: Utilitaires de manipulation de fichiers textes - - Section 8: Commandes et procédure de gestion du système - - Dans le cadre de ce cours, nous aborderons principalement les fonctionnalités décrites dans les trois premières sections des pages de manuel. L'accès à une page de manuel se fait via la commande ``man`` avec comme argument le nom de la commande concernée. Vous pouvez par exemple obtenir la page de manuel de ``gcc`` en tapant ``man gcc``. ``man`` supporte plusieurs paramètres qui sont décrits dans sa page de manuel accessible via ``man man``. Dans certains cas, il est nécessaire de spécifier la section du manuel demandée. C'est le cas par exemple pour ``printf`` qui existe comme utilitaire (section 1) et comme fonction de la librairie (section 3 - accessible via ``man 3 printf``). - - Outre ces pages de manuel locales, il existe également de nombreux sites web où l'on peut accéder aux pages de manuels de différentes versions de Unix dont notamment : - - - les pages de manuel de `Debian GNU/Linux <http://manpages.debian.net/>`_ - - les pages de manuel de `FreeBSD <http://www.freebsd.org/cgi/man.cgi>`_ - - les pages de manuel de `MacOS <http://developer.apple.com/documentation/Darwin/Reference/ManPages/index.html>`_ - - Dans la version en-ligne de ces notes, toutes les références vers un programme Unix, un appel système ou une fonction de la librairie pointent vers la page de manuel Linux correspondante. - -.. spelling:: - - Kernighan - Ritchie - -Il existe de nombreux livres consacrés au langage C. La référence la plus classique est [KernighanRitchie1998]_, mais certains éléments commencent à dater. Un tutoriel intéressant a été publié par Brian Kernighan [Kernighan]_. [King2008]_ propose une présentation plus moderne du langage C. - -.. rubric:: Footnotes - - -.. [#fgccaout] Si cette option n'était pas spécifiée, le compilateur aurait placé le programme compilé dans le fichier baptisé `a.out`. - -.. [#fbool] Formellement, le standard [C99]_ ne définit pas de type ``bool`` mais un type ``_Bool`` qui est en pratique renommé en type ``bool`` dans la plupart des compilateurs. La définition précise et complète se trouve dans `stdbool.h`_ - -.. [#fmain] Il est également possible d'utiliser dans un programme C une fonction ``main`` qui ne prend pas d'argument. Sa signature sera alors ``int main (void)``. - -.. spelling:: - - Darwin - MacOS - Windows - -.. [#fenvp] En pratique, le système d'exploitation passe également les variables d'environnement à la fonction ``main``. Nous verrons plus tard comment ces variables d'environnement sont passées du système au programme et comment celui-ci peut y accéder. Sachez cependant que sous certaines variantes de Unix, et notamment Darwin/MacOS ainsi que sous certaines versions de Windows, le prototype de la fonction ``main`` inclut explicitement ces variables d'environnement (``int main(int argc, char *argv[], char *envp[])``) - - diff --git a/Theorie/C/linker.rst b/Theorie/C/linker.rst deleted file mode 100644 index 41112ec1386d5e7043aaf317d8633406edcb8ded..0000000000000000000000000000000000000000 --- a/Theorie/C/linker.rst +++ /dev/null @@ -1,247 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012, 2019 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. _complementsC: - - -Compléments de C -================ - - -Dans les sections précédentes, nous n'avons pas pu couvrir l'ensemble des concepts avancés qui sont relatifs à une bonne utilisation du langage C. Cette section contient quelques notions plus avancées qui sont importantes en pratique. - - -Pointeurs ---------- - -Les pointeurs sont très largement utilisés dans les programmes écrits en langage C. Nous avons utilisé des pointeurs vers des types de données primitifs tel que les ``int``, ``char`` ou ``float`` et des pointeurs vers des structures. En pratique, il est possible en C de définir des pointeurs vers n'importe quel type d'information qui est manipulée par un programme C. - -Un premier exemple sont les pointeurs vers des fonctions. Comme nous l'avons vu dans le chapitre précédent, une fonction est une séquence d'instructions assembleur qui sont stockées à un endroit bien précis de la mémoire. Cette localisation précise des instructions qui implémentent la fonction permet d'appeler une fonction avec l'instruction ``calll``. En C, il est parfois aussi souhaitable de pouvoir appeler une fonction via un pointeur vers cette fonction plutôt qu'en nommant la fonction directement. Cela peut rendre le code plus flexible et plus facile à adapter. Nous avons déjà utilisé des pointeurs vers des fonctions sans le savoir lorsque nous avons utilisé ``printf("fct : %p\n",f)`` où ``f`` est un nom de fonction. L'exemple ci-dessous montre une autre utilisation intéressante des pointeurs vers des fonctions. Lorsque l'on écrit du code C, il est parfois utile d'ajouter des commandes qui permettent d'afficher à l'écran des informations de débogage. L'exemple ci-dessous est une application qui supporte trois niveaux de débogage. Rien n'est affiché au niveau ``0``, une ligne s'affiche au niveau ``1`` et des informations plus détaillées sont affichées au niveau ``2``. Lors de son exécution , l'application affiche la sortie suivante. - -.. code-block:: console - - $./fctptr 0 - fct debug_print : 0x100000d28 - $ ./fctptr 1 - fct debug_print : 0x100000d32 - debug: Hello - $ ./fctptr 2 - fct debug_print : 0x100000d5f - debug: Hello - g=1 - -Cette application qui supporte plusieurs niveaux de débogage utilise pourtant toujours le même appel pour afficher l'information de débogage : ``(debug_print[debug_level])(...);``. Cet appel profite des pointeurs vers les fonctions. Le tableau ``debug_print`` est un tableau de pointeurs vers des fonctions qui chacune prend comme argument un ``char *``. La variable globale ``debug_level`` est initialisée sur base de l'argument passé au programme. - -.. literalinclude:: /C/S5-src/fctptr.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -Ce n'est pas la seule utilisation des pointeurs vers des fonctions. Il y a notamment la fonction de la librairie `qsort(3)`_ qui permet de trier un tableau contenant n'importe quel type d'information. Cette fonction prend plusieurs arguments : - -.. code-block:: c - - void qsort(void *base, size_t nel, size_t width, - int (*compar)(const void *, const void *)); - -Le premier est un pointeur vers le début de la zone mémoire à trier. Le second est le nombre d'éléments à trier. Le troisième contient la taille des éléments stockés dans le tableau. Le quatrième argument est un pointeur vers la fonction qui permet de comparer deux éléments du tableau. Cette fonction retourne un entier négatif si son premier argument est inférieur au second et positif ou nul sinon. Un exemple de fonction de comparaison est la fonction `strcmp(3)`_ de la librairie standard. Un autre exemple est repris ci-dessous avec une fonction de comparaison simple qui permet d'utiliser `qsort(3)`_ pour trier un tableau de ``double``. - -.. literalinclude:: /C/S5-src/qsort.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Il est utile d'analyser en détails les arguments de la fonction de comparaison utilisée par `qsort(3)`_. Celle-ci prend deux arguments de type ``const void *``. L'utilisation de pointeurs ``void *`` est nécessaire car la fonction doit être générique et pouvoir traiter n'importe quel type de pointeurs. ``void *`` est un pointeur vers une zone quelconque de mémoire qui peut être casté vers n'importe quel type de pointeur par la fonction de comparaison. ``const`` indique que la fonction n'a pas le droit de modifier la donnée référencée par ce pointeur, même si elle reçoit un pointeur vers cette donnée. On retrouvera régulièrement cette utilisation de ``const`` dans les signatures des fonctions de la librairie pour spécifier des contraintes sur les arguments passés à une fonction [#frestrict]_. - - -Le second type de pointeurs que nous n'avons pas encore abordé en détails sont les pointeurs vers des pointeurs. En fait, nous les avons utilisés sans vraiment le savoir dans la fonction ``main``. En effet, le second argument de cette fonction est un tableau de pointeurs qui pointent chacun vers des chaînes de caractères différentes. La notation ``char *argv[]`` est équivalente à la notation ``char **argv``. ``**argv`` est donc un pointeur vers une zone qui contient des pointeurs vers des chaînes de caractères. Ce pointeur vers un pointeur doit être utilisé avec précaution. ``argv[0]`` est un pointeur vers une chaîne de caractères. La construction ``&(argv[0])`` permet donc d'obtenir un pointeur vers un pointeur vers une chaîne de caractères, ce qui correspond bien à la déclaration ``char **``. Ensuite, l'utilisation de ``*p`` pourrait surprendre. ``*p`` est un pointeur vers une chaîne de caractères. Il peut donc être comparé à ``NULL`` qui est aussi un pointeur, incrémenté et la chaîne de caractères qu'il référence peut être affichée par `printf(3)`_. - -.. literalinclude:: /C/S5-src/ptrptr.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -En pratique, ces pointeurs vers des pointeurs se retrouveront lorsque l'on doit manipuler des structures multidimensionnelles, mais aussi lorsqu'il faut qu'une fonction puisse modifier une adresse qu'elle a reçue en argument. - - - -Un autre exemple d'utilisation de pointeurs vers des pointeurs est la fonction `strtol(3)`_ de la librairie standard. Cette fonction est une généralisation des fonctions comme `atoi(3)`_. Elle permet de convertir une chaîne de caractères en un nombre. La fonction `strtol(3)`_ prend trois arguments et retourne un ``long``. Le premier argument est un pointeur vers la chaîne de caractères à convertir. Le troisième argument est la base utilisée pour cette conversion. - -.. code-block:: c - - #include <stdlib.h> - long - strtol(const char *restrict str, char **restrict endptr, int base); - -L'utilisation principale de `strtol(3)`_ est de convertir une chaîne de caractères en un nombre. La fonction `atoi(3)`_ fait de même et l'expression ``atoi("1252")`` retourne l'entier ``1252``. Malheureusement, la fonction `atoi(3)`_ ne traite pas correctement les chaînes de caractères qui ne contiennent pas un nombre. Elle ne retourne pas de code d'erreur et ne permet pas de savoir quelle partie de la chaîne de caractères passée en argument était en erreur. - -`strtol(3)`_ est un exemple de fonction qui doit retourner deux types d'informations. Tout d'abord, `strtol(3)`_ retourne un résultat (dans ce cas un nombre). Si la chaîne de caractères à convertir est erronée, `strtol(3)`_ convertit le début de la chaîne et retourne un pointeur indiquant le premier caractère en erreur. Pour bien comprendre le fonctionnement de `strtol(3)`_, considérons l'exemple ci-dessous. - -.. literalinclude:: /C/S5-src/strtol.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - -Lors de son exécution, ce programme affiche la sortie suivante. - -.. literalinclude:: /C/S5-src/strtol.out - :encoding: utf-8 - :language: console - -L'appel à `strtol(3)`_ prend trois arguments. Tout d'abord un pointeur vers la chaîne de caractères à convertir. Ensuite l'adresse d'un pointeur vers une chaîne de caractères. Enfin la base de conversion. La première chaîne de caractères est correcte. Elle est convertie directement. La seconde par contre contient un caractère erroné. Lors de son exécution, `strtol(3)`_ va détecter la présence du caractère ``m`` et placera un pointeur vers ce caractère dans ``*p``. Pour que la fonction `strtol(3)`_ puisse retourner un pointeur de cette façon, il est nécessaire que son second argument soit de type ``char **``. Si le second argument était de type ``char *``, la fonction `strtol(3)`_ recevrait l'adresse d'une zone mémoire contenant un caractère. Comme le langage C utilise le passage par valeur, `strtol(3)`_ pourrait modifier la caractère pointé par ce pointeur mais pas son adresse. En utilisant un second argument de type ``char **``, `strtol(3)`_ a la possibilité de modifier la valeur pointée par ce pointeur. - -Une implémentation partielle de `strtol(3)`_ pourrait être la suivante. - -.. literalinclude:: /C/S5-src/mystrtol.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Cette partie de code utilise la fonction `isdigit(3)`_ pour vérifier si les caractères présents dans la chaîne de caractères sont des chiffres. Sinon, elle fixe via son second argument la valeur du pointeur vers le caractère en erreur. Cela est réalisé par l'expression ``*endptr=(char *)(str+i);``. Il faut noter que ``*endptr`` est bien une zone mémoire pointée par le pointeur ``endptr`` reçu comme second argument. Cette valeur peut donc être modifiée. - -Il existe d'autres fonctions de la librairie standard qui utilisent des pointeurs vers des pointeurs comme arguments dont notamment `strsep(3)`_ et `strtok_r(3)`_. - - - -De grands programmes en C -------------------------- - -Lorsque l'on développe de grands programmes en C, il est préférable de découper le programme en modules. Chaque module contient des fonctions qui traitent d'un même type de problème et sont fortement couplées. A titre d'exemple, un module ``stack`` pourrait regrouper différentes fonctions de manipulation d'une pile. Un autre module pourrait regrouper les fonctions relatives au dialogue avec l'utilisateur, un autre les fonctions de gestion des fichiers, ... - -Pour comprendre l'utilisation de ces modules, considérons d'abord un programme trivial composé de deux modules. Le premier module est celui qui contient la fonction ``main``. Tout programme C doit contenir une fonction ``main`` pour pouvoir être exécuté. C'est en général l'interface avec l'utilisateur. Le second module contient une fonction générique qui est utilisée par le module principal. - -.. literalinclude:: /C/S5-src/main.c - :encoding: utf-8 - :language: c - -Un module d'un programme C est en général décomposé en deux parties. Tout d'abord, le fichier :term:`fichier header` contient les définitions de certaines constantes et les signatures des fonctions exportées par ce module. Ce fichier est en quelque sorte un résumé du module, ou plus précisément de son interface externe. Il doit être inclus dans tout fichier qui utilise les fonctions du module correspondant. Dans un tel fichier :term:`fichier header`, on retrouve généralement trois types d'informations : - - - les signatures des fonctions qui sont définies dans le module. En général, seules les fonctions qui sont destinées à être utilisées par des modules extérieures sont reprises dans le :term:`fichier header` - - les constantes qui sont utilisées à l'intérieur du module et doivent être visibles en dehors de celui-ci, notamment par les modules qui utilisent les fonctions du module. Ces constantes peuvent être définies en utilisant des directives ``#define`` du préprocesseur - - les variables globales qui sont utilisées par les fonctions du module et doivent être accessibles en dehors de celui-ci - -.. literalinclude:: /C/S5-src/min.h - :encoding: utf-8 - :language: c - -.. note:: Un :term:`fichier header` ne doit être inclus qu'une seule fois - - L'exemple de :term:`fichier header` ci-dessus illustre une convention courante dans l'écriture de ces fichiers. Parfois, il est nécessaire d'inclure un :term:`fichier header` dans un autre fichier header. Suite à cela, il est possible que les mêmes définitions d'un :term:`fichier header` soient incluses deux fois ou plus dans le même module. Cela peut causer des erreurs de compilation qui risquent de perturber certains programmeurs. Une règle de bonne pratique pour éviter ce problème est d'inclure le contenu du :term:`fichier header` de façon conditionnelle comme présenté ci-dessus. Une constante, dans ce cas ``_MIN_H_``, est définie pour le :term:`fichier header` concerné. Cette constante est définie dans la première ligne effective du :term:`fichier header`. Celui-ci n'est inclus dans un module que si cette constante n'a pas été préalablement définie. Si cette constante est connue par le préprocesseur, cela indique qu'un autre :term:`fichier header` a déjà inclus les définitions de ce fichier et qu'elles ne doivent pas être incluses une seconde fois. - -.. literalinclude:: /C/S5-src/min.c - :encoding: utf-8 - :language: c - -.. note:: Localisation des fichiers header - - Un programmeur C peut utiliser deux types de fichiers header. Il y a tout d'abord les fichiers headers standards qui sont fournis avec le système. Ce sont ceux que nous avons utilisés jusque maintenant. Ces headers standards se reconnaissent car ils sont entourés des caractères ``<`` et ``>`` dans la directive ``#include``. Ceux-ci se trouvent dans des répertoires connus par le compilateur, normalement ``/usr/include``. Les fichiers headers qui accompagnent un module se trouvent eux généralement dans le même répertoire que le module. Dans l'exemple ci-dessus, le header ``min.h`` est inclus via la directive ``#include "min.h"``. Lorsque le préprocesseur rencontre une telle directive, il cherche le fichier dans le répertoire courant. Il est possible de spécifier des répertoires qui contiennent des fichiers headers via l'argument ``-I`` de `gcc(1)`_ ou en utilisant les variables d'environnement ``GCC_INCLUDE_DIR`` ou ``CPATH``. - -Lorsque l'on doit compiler un programme qui fait appel à plusieurs modules, quelle que soit sa taille, il est préférable d'utiliser `make(1)`_ pour automatiser sa compilation. Le fichier ci-dessous est un petit exemple de :term:`Makefile` utilisable pour un tel projet. - -.. literalinclude:: /C/S5-src/Makefile2 - :encoding: utf-8 - :language: makefile - :start-after: ###AAA - :end-before: ###BBB - -La compilation d'un tel programme se déroule en plusieurs étapes. La première étape est celle du préprocesseur. Celui-ci est directement appelé par le compilateur `gcc(1)`_ mais il est également possible de l'invoquer directement via `cpp(1)`_. Le préprocesseur remplace toutes les macros telles que les ``#define`` et insère les fichiers headers sur base des directives ``#include``. La sortie du préprocesseur est utilisée directement par le compilateur. Celui-ci transforme le module en langage C en langage assembleur. Ce module en assembleur est ensuite assemblé par `as(1)`_ pour produire un :term:`fichier objet`. Ce :term:`fichier objet` n'est pas directement exécutable. Il contient les instructions en langage machine pour les différentes fonctions définies dans le module, les définitions des constantes et variables globales ainsi qu'une table reprenant tous les symboles (noms de fonction, noms de variables globales, ...) définis dans ce module. Ces phases sont exécutées pour chaque module utilisé. Par convention, les fichiers objets ont en général l'extension ``.o``. Ces fichiers objet sont créés par les deux dernières cibles du fichier ``Makefile`` ci-dessus. L'option ``-c`` passée à `gcc(1)`_ indique à `gcc(1)`_ qu'il doit générer un fichier objet sans le transformer en exécutable. Cette dernière opération est réalisée par la première cible du ``Makefile``. Dans cette cible, `gcc(1)`_ fait office d'éditeur de liens ou de :term:`linker` en anglais. Le :term:`linker` combine différents fichiers objets en faisant les liens nécessaires entre les fichiers. Dans notre exemple, le fichier ``main.o`` contient une référence vers la fonction ``min`` qui n'est pas connue lors de la compilation de ``main.c``. Par contre, cette référence est connue dans le fichier ``min.o``. L'éditeur de liens va combiner ces références de façon à permettre aux fonctions d'un module d'exécuter n'importe quelle fonction définie dans un autre module. - -La figure ci-dessous représente graphiquement les différentes étapes de compilation des modules ``min.c`` et ``main.c``. - -.. figure:: /C/figures/figures-007-c.png - :align: center - :scale: 60 - - Etapes de compilation - - -Lorsque plusieurs modules, potentiellement développés par des programmeurs qui ne se sont pas concertés, doivent être intégrés dans un grand programme, il y a des risques de conflits entre des variables et fonctions qui pourraient être définies dans plusieurs modules différents. Ainsi, deux modules pourraient définir la fonction ``int min(int, int)`` ou la variable globale ``float dist``. Le langage C intègre des facilités qui permettent d'éviter ou de contrôler ces problèmes. - -Tout d'abord, les variables locales sont locales au bloc dans lequel elles sont définies. Ce principe permet d'utiliser le même nom de variable dans plusieurs blocs d'un même fichier. Il s'étend naturellement à l'utilisation de variables locales dans des fichiers différents. - -Pour les variables globales, la situation est différente. Si une variable est définie en dehors d'un bloc dans un fichier, cette variable est considérée comme étant globale. Par défaut, elle est donc accessible depuis tous les modules qui composent le programme. Cela peut en pratique poser des difficultés si le même nom de variable est utilisé dans deux modules différents. Pour contourner ce problème, le langage C utilise ``static``. Lorsque ``static`` est placé devant une déclaration de variable en dehors d'un bloc dans un module, il indique que la variable doit être accessible à toutes les fonctions du module mais pas en dehors du module. Lorsqu'un module utilise des variables qui sont communes à plusieurs fonctions mais ne doivent pas être visibles en dehors du module, il est important de les déclarer comme étant ``static``. Lorsqu'une déclaration de variable globale est préfixée par ``extern``, cela indique au compilateur que la variable est définie dans un autre module qui sera lié ultérieurement. Le compilateur réserve une place pour cette variable dans la table des symboles du fichier objet, mais cette place ne pourra être liée à la zone mémoire qui correspond à cette variable que lorsque l'éditeur de liens combinera les différents fichiers objet entre eux. - -.. note:: Les deux utilisations de ``static`` pour des variables - - ``static`` peut être utilisé à la fois pour des variables qui sont définies en dehors d'un bloc et dans un bloc. Lorsqu'une variable est définie comme étant ``static`` hors d'un bloc dans un module, elle n'est accessible qu'aux fonctions de ce module. Par contre, lorsqu'une variable est définie comme étant ``static`` à l'intérieur d'un bloc, par exemple dans une fonction, cela indique que cette variable doit toujours se trouver à la même localisation en mémoire, quel que soit le moment où elle est appelée. Ces variables ``static`` sont placées par le compilateur dans le bas de la mémoire, avec les variables globales. Contrairement aux variables locales traditionnelles, une variable locale ``static`` garde sa valeur d'une invocation de la fonction à l'autre. En pratique, les variables locales ``static`` doivent être utilisées avec précaution et bien documentées. Un de leurs intérêt est qu'elles ne sont initialisées qu'au lancement du programme et pas à chaque invocation de la fonction où elles sont définies. - - -Il faut noter que ``static`` peut aussi précéder des déclarations de fonctions. Dans ce cas, il indique que la fonction ne doit pas être visible en dehors du module dans lequel elle est définie. Sans ``static``, une fonction déclarée dans un module est accessible depuis n'importe quel autre module. - -Afin d'illustrer l'utilisation de ``static`` et ``extern``, considérons le programme ``prog.c`` ci-dessous qui inclut le module ``module.c`` et également le module ``min.c`` présenté plus haut. - -.. literalinclude:: /C/S5-src/module.h - :encoding: utf-8 - :language: c - -.. literalinclude:: /C/S5-src/module.c - :encoding: utf-8 - :language: c - -Ce module contient deux fonctions, ``vmin`` et ``min``. ``vmin`` est accessible depuis n'importe quel module. Sa signature est reprise dans le :term:`fichier header` ``module.h``. La fonction ``min`` par contre est déclarée comme étant ``static``. Cela implique qu'elle n'est utilisable qu'à l'intérieur de ce module et invisible de tout autre module. La variable globale ``num1`` est accessible depuis n'importe quel module. La variable ``num2`` également, mais elle est initialisée dans un autre module. Enfin, la variable ``num3`` n'est accessible qu'à l'intérieur de ce module. - -.. literalinclude:: /C/S5-src/prog.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - -Ce module inclus les fichiers ``min.h`` et ``module.h`` qui contiennent les signatures des fonctions se trouvant dans ces deux modules. Trois variables globales sont utilisées par ce module. ``num1`` est définie dans un autre module (dans ce cas ``module.c``). ``num2`` est initialisée dans ce module mais accessible depuis n'importe quel autre module. ``num3`` est une variable globale qui est accessible uniquement depuis le module ``prog.c``. Même si cette variable porte le même nom qu'une autre variable déclarée dans ``module.c``, il n'y aura pas de conflit puisque ces deux variables sont ``static``. - -La fonction ``f`` mérite que l'on s'y attarde un peu. Cette fonction contient la définition de la variable ``static n``. Même si cette variable est locale à la fonction ``f`` et donc invisible en dehors de cette fonction, le compilateur va lui réserver une place dans la même zone que les variables globales. La valeur de cette variable ``static`` sera initialisée une seule fois : au démarrage du programme. Même si cette variable parait être locale, elle ne sera jamais réinitialisée lors d'un appel à la fonction ``f``. Comme cette variable est stockée en dehors de la pile, elle conserve sa valeur d'une invocation à l'autre de la fonction ``f``. Ceci est illustré par l'exécution du programme qui produit la sortie suivante. - -.. literalinclude:: /C/S5-src/prog.out - :encoding: utf-8 - :language: console - -Le dernier point à mentionner concernant cet exemple est relatif à la fonction ``min`` qui est utilisée dans la fonction ``main``. Le module ``prog.c`` étant lié avec ``module.c`` et ``min.c``, le linker associe à ce nom de fonction la déclaration qui se trouve dans le fichier ``min.c``. La déclaration de la fonction ``min`` qui se trouve dans ``module.c`` est ``static``, elle ne peut donc pas être utilisée en dehors de ce module. - - -Traitement des erreurs ----------------------- - -Certaines fonctions de la librairie et certains appels systèmes réussissent toujours. C'est le cas par exemple pour `getpid(2)`_. D'autres fonctions peuvent échouer et il est important de tester la valeur de retour de chaque fonction/appel système utilisé pour pouvoir réagir correctement à toute erreur. Pour certaines fonctions ou appels systèmes, il est parfois nécessaire de fournir à l'utilisateur plus d'information sur l'erreur qui s'est produite. La valeur de retour utilisée pour la plupart des fonctions de la libraire et appels systèmes (souvent un ``int`` ou un pointeur), ne permet pas de fournir de l'information précise sur l'erreur qui s'est produite. - -Les systèmes Unix utilisent la variable globale :term:`errno` pour résoudre ce problème et permettre à une fonction de la librairie ou un appel système qui a échoué de donner plus de détails sur les raisons de l'échec. Cette variable globale est définie dans `errno.h`_ qui doit être inclus par tout programme voulant tester ces codes d'erreur. Cette variable est de type ``int`` et `errno.h` contient les définitions des constantes correspondants aux cas d'erreurs possibles. Il faut noter que la librairie standard fournit également les fonctions `perror(3)`_ et `strerror(3)`_ qui facilitent l'écriture de messages d'erreur compréhensibles pour l'utilisateur. - -A titre d'exemple, le programme ci-dessous utilise `strerror(3)`_ pour afficher un message d'erreur plus parlant lors d'appels erronés à la fonction `setenv(3)`_. - -.. literalinclude:: /C/S5-src/errno.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - -.. note:: La valeur de ``errno`` n'indique pas la réussite ou l'échec d'une fonction - - Il faut noter que la variable ``errno`` n'est modifiée par les fonctions de la librairie ou les appels systèmes que si l'appel échoue. Si l'appel réussit, la valeur de ``errno`` n'est pas modifiée. Cela implique qu'il ne faut surtout pas tester la valeur de ``errno`` pour déterminer si une fonction de la librairie a échoué ou réussi. Il ne faut surtout pas utiliser le pattern suivant : - - .. code-block:: c - - setenv("PATH","/usr/bin",1); - if(errno!=0) { - fprintf(stderr,"Erreur : errno=%d %s\n",errno,strerror(errno); - } - - Le code ci-dessus est erroné car il ne teste pas la valeur de retour de `setenv(3)`_. Comme les fonctions de la librairie et les appels systèmes ne modifient ``errno`` que lorsqu'une erreur survient, le code ci-dessus pourrait afficher un message d'erreur relatif à un appel système précédent qui n'a absolument rien à voir avec l'appel à la fonction `setenv(3)`_. Le code correct est évidemment de tester la valeur de retour de `setenv(3)`_ : - - .. code-block:: c - - err=setenv("PATH","/usr/bin",1); - if(err!=0) { - fprintf(stderr,"Erreur : errno=%d %s\n",errno,strerror(errno)); - } - - - -.. rubric:: Footnotes - - -.. [#frestrict] ``restrict`` est également parfois utilisé pour indiquer des contraintes sur les pointeurs passés en argument à une fonction [Walls2006]_. - - - diff --git a/Theorie/C/malloc.rst b/Theorie/C/malloc.rst deleted file mode 100644 index 4a3e263161ff3e78b4a96d8463fc6a99a014340b..0000000000000000000000000000000000000000 --- a/Theorie/C/malloc.rst +++ /dev/null @@ -1,408 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012, 2019 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -Déclarations -============= - -Durant les chapitres précédents, nous avons principalement utilisé des variables locales. Celles-ci sont déclarées à l'intérieur des fonctions où elles sont utilisées. La façon dont les variables sont déclarées est importante dans un programme écrit en langage C. Dans cette section nous nous concentrerons sur des programmes C qui sont écrits sous la forme d'un seul fichier source. Nous verrons plus tard comment découper un programme en plusieurs modules qui sont répartis dans des fichiers différents et comment les variables peuvent y être déclarées. - -La première notion importante concernant la déclaration des variables est leur :term:`portée`. La portée d'une variable peut être définie comme étant la partie du programme où la variable est accessible et où sa valeur peut être modifiée. Le langage C définit deux types de portée à l'intérieur d'un fichier C. La première est la :term:`portée globale`. Une variable qui est définie en dehors de toute définition de fonction a une portée globale. Une telle variable est accessible dans toutes les fonctions présentes dans le fichier. La variable ``g`` dans l'exemple ci-dessous a une portée globale. - -.. code-block:: c - - float g; // variable globale - - int f(int i) { - int n; // variable locale - // ... - for(int j=0;j<n;j++) { // variable locale - // ... - } - //... - for(int j=0;j<n;j++) { // variable locale - // ... - } - } - - -Dans un fichier donné, il ne peut évidemment pas y avoir deux variables globales qui ont le même identifiant. Lorsqu'une variable est définie dans un `bloc`, la portée de cette variable est locale à ce bloc. On parle dans ce cas de :term:`portée locale`. La variable locale n'existe pas avant le début du bloc et n'existe plus à la fin du bloc. Contrairement aux identifiants de variables globales qui doivent être uniques à l'intérieur d'un fichier, il est possible d'avoir plusieurs variables locales qui ont le même identifiant à l'intérieur d'un fichier. C'est fréquent notamment pour les définitions d'arguments de fonction et les variables de boucles. Dans l'exemple ci-dessus, les variables ``n`` et ``j`` ont une portée locale. La variable ``j`` est définie dans deux blocs différents à l'intérieur de la fonction ``f``. - - -Le programme :download:`/C/S3-src/portee.c` illustre la façon dont le compilateur C gère la portée de différentes variables. - -.. literalinclude:: /C/S3-src/portee.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Ce programme contient deux variables qui ont une portée globale : ``g1`` et ``g2``. Ces deux variables sont définies en dehors de tout bloc. En pratique, elles sont généralement déclarées au début du fichier, même si le compilateur C accepte un définition en dehors de tout bloc et donc par exemple en fin de fichier. La variable globale ``g1`` n'est définie qu'une seule fois. Par contre, la variable ``g2`` est définie avec une portée globale et est redéfinie à l'intérieur de la fonction ``f`` ainsi que dans la boucle ``for`` de la fonction ``main``. Redéfinir une variable globale de cette façon n'est pas du tout une bonne pratique, mais cela peut arriver lorsque par mégarde on importe un fichier header qui contient une définition de variable globale. Dans ce cas, le compilateur C utilise la variable qui est définie dans le bloc le plus proche. Pour la variable ``g2``, c'est donc la variable locale ``g2`` qui est utilisée à l'intérieur de la boucle ``for`` ou de la fonction ``f``. - -Lorsqu'un identifiant de variable locale est utilisé à plusieurs endroits dans un fichier, c'est la définition la plus proche qui est utilisée. L'exécution du programme ci-dessus illustre cette utilisation des variables globales et locales. - -.. literalinclude:: /C/S3-src/portee.out - :encoding: utf-8 - :language: console - -.. note:: Utilisation des variables - - En pratique, les variables globales doivent être utilisées de façon parcimonieuse et il faut limiter leur utilisation aux données qui doivent être partagées par plusieurs fonctions à l'intérieur d'un programme. Lorsqu'une variable globale a été définie, il est préférable de ne pas réutiliser son identifiant pour une variable locale. Au niveau des variables locales, les premières versions du langage C imposaient leur définition au début des blocs. Les standards récents [C99]_ autorisent la déclaration de variables juste avant leur première utilisation un peu comme en Java. - -Les versions récentes de C [C99]_ permettent également de définir des variables dont la valeur sera constante durant toute l'exécution du programme. Ces déclarations de ces constants sont préfixées par le mot-clé ``const`` qui joue le même rôle que le mot clé ``final`` en Java. - -.. literalinclude:: /C/S3-src/const.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -Il y a deux façons de définir des constantes dans les versions récentes de C [C99]_. La première est via la macro ``#define`` du préprocesseur. Cette macro permet de remplacer une chaîne de caractères (par exemple ``M_PI`` qui provient de `math.h`_) par un nombre ou une autre chaîne de caractères. Ce remplacement s'effectue avant la compilation. Dans le cas de ``M_PI`` ci-dessus, le préprocesseur remplace toute les occurrences de cette chaîne de caractères par la valeur numérique de :math:`\pi`. Lorsqu'une variable ``const`` est utilisée, la situation est un peu différente. Le préprocesseur n'intervient pas. Par contre, le compilateur réserve une zone mémoire pour la variable qui a été définie comme constante. Cela a deux avantages par rapport à l'utilisation de ``#define``. Premièrement, il est possible de définir comme constante n'importe quel type de données en C, y compris des structures ou des pointeurs alors qu'avec un ``#define`` on ne peut définir que des nombres ou des chaînes de caractères. Ensuite, comme une ``const`` est stockée en mémoire, il est possible d'obtenir son adresse et de l'examiner via un :term:`debugger`. - - -Unions et énumérations -====================== - -Les structures que nous avons présentées précédemment permettent de combiner plusieurs données de types primitifs différents entre elles. Outre ces structures (``struct``), le langage C supporte également les ``enum`` et les ``union``. Le mot-clé ``enum`` est utilisé pour définir un type énuméré, c'est-à -dire un type de donnée qui permet de stocker un nombre fixe de valeurs. Quelques exemples classiques sont repris dans le fragment de programme ci-dessous : - -.. literalinclude:: /C/S3-src/enum.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Le premier ``enum`` permet de définir le type de données ``day`` qui contient une valeur énumérée pour chaque jour de la semaine. L'utilisation d'un type énuméré rend le code plus lisible que simplement l'utilisation de constantes définies via le préprocesseur. - -.. literalinclude:: /C/S3-src/enum.c - :encoding: utf-8 - :language: c - :start-after: ///CCC - :end-before: ///DDD - -En pratique, lors de la définition d'un type énuméré, le compilateur C associe une valeur entière à chacune des valeurs énumérées. Une variable permettant de stocker la valeur d'un type énuméré occupe la même zone mémoire qu'un entier. - -Outre les structures, le langage C supporte également les unions. Alors qu'une structure permet de stocker plusieurs données dans une même zone mémoire, une ``union`` permet de réserver une zone mémoire pour stocker une données parmi plusieurs types possibles. Une ``union`` est parfois utilisée pour minimiser la quantité de mémoire utilisée pour une structure de données qui peut contenir des données de plusieurs types. Pour bien comprendre la différence entre une ``union`` et une ``struct``, considérons l'exemple ci-dessous. - -.. literalinclude:: /C/S3-src/union.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -Une union, ``u`` et une structure, ``s`` sont déclarées dans ce fragment de programme. - -.. literalinclude:: /C/S3-src/union.c - :encoding: utf-8 - :language: c - :start-after: ///CCC - :end-before: ///DDD - -La structure ``s`` peut contenir à la fois un entier et un caractère. Par contre, l'``union`` ``u``, peut elle contenir un entier (``u.i``) *ou* un caractère (``u.c``), mais jamais les deux en même temps. -Le compilateur C alloue la taille pour l'``union`` de façon à ce qu'elle puisse contenir le type de donnée se trouvant dans l'``union`` nécessitant le plus de mémoire. Si les unions sont utiles dans certains cas très particulier, il faut faire très attention à leur utilisation. Lorsqu'une ``union`` est utilisée, le compilateur C fait encore moins de vérifications sur les types de données et le code ci-dessous est considéré comme valide par le compilateur : - -.. literalinclude:: /C/S3-src/union.c - :encoding: utf-8 - :language: c - :start-after: ///EEE - :end-before: ///FFF - -Lors de son exécution, la zone mémoire correspondant à l'union ``u`` sera simplement interprétée comme contenant un ``char``, même si on vient d'y stocker un entier. En pratique, lorsqu'une ``union`` est vraiment nécessaire pour des raisons d'économie de mémoire, on préférera la placer dans une ``struct`` en utilisant un type énuméré qui permet de spécifier le type de données qui est présent dans l'``union``. - -.. literalinclude:: /C/S3-src/union.c - :encoding: utf-8 - :language: c - :start-after: ///BBB - :end-before: ///XXX - -Le programmeur pourra alors utiliser cette structure en indiquant explicitement le type de données qui y est actuellement stocké comme suit. - -.. literalinclude:: /C/S3-src/union.c - :encoding: utf-8 - :language: c - :start-after: ///FFF - :end-before: ///GGG - - -Organisation de la mémoire -========================== - -Lors de l'exécution d'un programme en mémoire, le système d'exploitation charge depuis le système de fichier le programme en langage machine et le place à un endroit convenu en mémoire. Lorsqu'un programme s'exécute sur un système Unix, la mémoire peut être vue comme étant divisée en six zones principales. Ces zones sont représentées schématiquement dans la figure ci-dessous. - -.. figure:: /C/figures/figures-001-c.png - :align: center - - Organisation d'un programme Linux en mémoire - -La figure ci-dessus présente une vision schématique de la façon dont un processus Linux est organisé en mémoire centrale. Il y a d'abord une partie de la mémoire qui est réservée au système d'exploitation (OS dans la figure). Cette zone est représentée en grisé dans la figure. - -Le segment text ---------------- - -La première zone est appelée par convention le :term:`segment text`. Cette zone se situe dans la partie basse de la mémoire [#fetext]_. C'est dans cette zone que sont stockées toutes les instructions qui sont exécutées par le micro-processeur. Elle est généralement considérée par le système d'exploitation comme étant uniquement accessible en lecture. Si un programme tente de modifier son :term:`segment text`, il sera immédiatement interrompu par le système d'exploitation. C'est dans le segment text que l'on retrouvera les instructions de langage machine correspondant aux fonctions de calcul et d'affichage du programme. Nous en reparlerons lorsque nous présenterons le fonctionnement du langage d'assemblage. - -Le segment des données initialisées ------------------------------------ - -La deuxième zone, baptisée :term:`segment des données initialisées`, contient l'ensemble des données et chaînes de caractères qui sont utilisées dans le programme. Ce segment contient deux types de données. Tout d'abord, il comprend l'ensemble des variables globales explicitement initialisées par le programme (dans le cas contraire, elles sont initialisées à zéro par le compilateur et appartiennent alors au :term:`segment des données non-initialisées`). Ensuite, les constantes et les chaînes de caractères utilisées par le programme. - -.. literalinclude:: /C/S3-src/dataseg.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Dans le programme ci-dessus, la variable ``g_init``, la constante ``un`` et les tableaux ``tab`` et ``cours`` sont dans la zone réservée aux variables initialisées. En pratique, leur valeur d'initialisation sera chargée depuis le fichier exécutable lors de son chargement en mémoire. Il en va de même pour toutes les chaînes de caractères qui sont utilisées comme arguments aux appels à ``printf(3)``. - -L'exécution de ce programme produit la sortie standard suivante. - -.. literalinclude:: /C/S3-src/dataseg.out - :encoding: utf-8 - :language: console - - -Cette sortie illustre bien les adresses où les variables globales sont stockées. La variable globale ``msg`` fait notamment partie du :term:`segment des données non-initialisées`. - -Le segment des données non-initialisées ---------------------------------------- - -La troisième zone est le :term:`segment des données non-initialisées`, réservée aux variables non-initialisées. Cette zone mémoire est initialisée à zéro par le système d'exploitation lors du démarrage du programme. Dans l'exemple ci-dessus, c'est dans cette zone que l'on stockera les valeurs de la variable ``g`` et des tableaux ``array`` et ``msg``. - -.. note:: Initialisation des variables - - Un point important auquel tout programmeur C doit faire attention est l'initialisation correcte de l'ensemble des variables utilisées dans un programme. Le compilateur C est nettement plus permissif qu'un compilateur Java et il autorisera l'utilisation de variables avant qu'elles n'aient été explicitement initialisées, ce qui peut donner lieu à des erreurs parfois très difficiles à corriger. - - En C, par défaut les variables globales qui ne sont pas explicitement initialisées dans un programme sont initialisées à la valeur zéro par le compilateur. Plus précisément, la zone mémoire qui correspond à chaque variable globale non-explicitement initialisée contiendra des bits valant 0. Pour les variables locales, le langage C n'impose aucune initialisation par défaut au compilateur. Par souci de performance et sachant qu'un programmeur ne devrait jamais utiliser de variable locale non explicitement initialisée, le compilateur C n'initialise pas par défaut la valeur de ces variables. Cela peut avoir des conséquences ennuyeuses comme le montre l'exemple ci-dessous. - - .. literalinclude:: /C/S3-src/initvar.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - Cet extrait de programme contient deux fonctions erronées. La seconde, baptisée ``read(void)`` déclare un tableau local et retourne la somme des éléments de ce tableau sans l'initialiser. En Java, une telle utilisation d'un tableau non-initialisé serait détectée par le compilateur. En C, elle est malheureusement valide (mais fortement découragée évidemment). La première fonction, ``init(void)`` se contente d'initialiser un tableau local mais ne retourne aucun résultat. Cette fonction ne sert a priori à rien puisqu'elle n'a aucun effet sur les variables globales et ne retourne aucun résultat. L'exécution de ces fonctions via le fragment de code ci-dessous donne cependant un résultat interpellant. - - .. literalinclude:: /C/S3-src/initvar.c - :encoding: utf-8 - :language: c - :start-after: ///CCC - :end-before: ///DDD - - .. literalinclude:: /C/S3-src/initvar.out - :encoding: utf-8 - :language: console - - - - -Le tas (ou `heap`) ------------------- - -La quatrième zone de la mémoire est le :term:`tas` (ou :term:`heap` en anglais). Vu l'importance pratique de la terminologie anglaise, c'est celle-ci que nous utiliserons dans le cadre de ce document. C'est une des deux zones dans laquelle un programme peut obtenir de la mémoire supplémentaire pour stocker de l'information. Un programme peut y réserver une zone permettant de stocker des données et y associer un pointeur. - -Le système d'exploitation mémorise, pour chaque processus en cours d'exécution, la limite supérieure de son :term:`heap`. Le système d'exploitation permet à un processus de modifier la taille de son heap via les appels systèmes `brk(2)`_ et `sbrk(2)`_. Malheureusement, ces deux appels systèmes se contentent de modifier la limite supérieure du :term:`heap` sans fournir une API permettant au processus d'y allouer efficacement des blocs de mémoire. Rares sont les processus qui utilisent directement `brk(2)`_ si ce n'est sous la forme d'un appel à ``sbrk(0)`` de façon à connaître la limite supérieure actuelle du :term:`heap`. - -En C, la plupart des processus allouent et libèrent de la mémoire en utilisant les fonctions `malloc(3)`_ et `free(3)`_ qui font partie de la librairie standard. - -La fonction `malloc(3)`_ prend comme argument la taille (en bytes) de la zone mémoire à allouer. La signature de la fonction `malloc(3)`_ demande que cette taille soit de type ``size_t``, c'est-à -dire le type retourné par l'expression ``sizeof``. Il est important de toujours utiliser ``sizeof`` lors du calcul de la taille d'une zone mémoire à allouer. `malloc(3)`_ retourne normalement un pointeur de type ``(void *)``. Ce type de pointeur est le type par défaut pour représenter dans un programme C une zone mémoire qui ne pointe pas vers un type de données particulier. En pratique, un programme va généralement utiliser `malloc(3)`_ pour allouer de la mémoire pour stocker différents types de données et le pointeur retourné par `malloc(3)`_ sera `casté` dans un pointeur du bon type. - -.. spelling:: - - typecast - -.. note:: ``typecast`` en langage C - - Comme le langage Java, le langage C supporte des conversions implicites et explicites entre les différents types de données. Ces conversions sont possibles entre les types primitifs et les pointeurs. Nous les rencontrerons régulièrement, par exemple lorsqu'il faut récupérer un pointeur alloué par `malloc(3)`_ ou le résultat de ``sizeof``. Contrairement au compilateur Java, le compilateur C n'émet pas toujours de message de :term:`warning` lors de l'utilisation de typecast qui risque d'engendrer une perte de précision. Ce problème est illustré par l'exemple suivant avec les nombres. - - .. literalinclude:: /C/S3-src/typecast.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -La fonction de la librairie `free(3)`_ est le pendant de `malloc(3)`_. Elle permet de libérer la mémoire qui a été allouée par `malloc(3)`_. Elle prend comme argument un pointeur dont la valeur a été initialisée par `malloc(3)`_ et libère la zone mémoire qui avait été allouée par `malloc(3)`_ pour ce pointeur. La valeur du pointeur n'est pas modifiée, mais après libération de la mémoire il n'est évidemment plus possible [#fpossible]_ d'accéder aux données qui étaient stockées dans cette zone. - -Le programme ci-dessous illustre l'utilisation de `malloc(3)`_ et `free(3)`_. - -.. literalinclude:: /C/S3-src/malloc.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Ce programme alloue trois zones mémoires. Le pointeur vers la première est sauvé dans le pointeur ``string``. Elle est destinée à contenir une chaîne de ``size`` caractères (avec un caractère supplémentaire pour stocker le caractère ``\0`` de fin de chaîne). Il y a deux points à remarquer concernant cette allocation. Tout d'abord, le pointeur retourné par `malloc(3)`_ est "casté" en un ``char *``. Cela indique au compilateur que ``string`` va bien contenir un pointeur vers une chaîne de caractères. Cette conversion explicite rend le programme plus clair. Ensuite, la valeur de retour de `malloc(3)`_ est systématiquement testée. `malloc(3)`_ peut en effet retourner ``NULL`` lorsque la mémoire est remplie. Cela a peu de chance d'arriver dans un programme de test tel que celui-ci, mais tester les valeurs de retour des fonctions de la librairie est une bonne habitude à prendre lorsque l'on programme sous Unix. Le second pointeur, ``vector`` pointe vers une zone destiné à contenir un tableau d'entiers. Le dernier pointeur, ``fract_vect`` pointe vers une zone qui pourra stocker un tableau de ``Fraction``. Lors de son exécution, le programme affiche la sortie suivante. - -.. literalinclude:: /C/S3-src/malloc.out - :encoding: utf-8 - :language: console - -Dans cette sortie, on remarque que l'appel à fonction `free(3)`_ libère la zone mémoire, mais ne modifie pas la valeur du pointeur correspondant. Le programmeur doit explicitement remettre le pointeur d'une zone mémoire libérée à ``NULL``. - -Un autre exemple d'utilisation de `malloc(3)`_ est la fonction ``duplicate`` ci-dessous qui permet de retourner une copie d'une chaîne de caractères. Il est important de noter qu'en C la fonction `strlen(3)`_ retourne la longueur de la chaîne de caractères passée en argument sans prendre en compte le caractère ``\0`` qui marque sa fin. C'est la raison pour laquelle `malloc(3)`_ doit réserver un bloc de mémoire en plus. Même si généralement les ``char`` occupent un octet en mémoire, il est préférable d'utiliser explicitement ``sizeof(char)`` lors du calcul de l'espace mémoire nécessaire pour un type de données. - - -.. literalinclude:: /C/S3-src/strcpy.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -`malloc(3)`_ et `free(3)`_ sont fréquemment utilisés dans des programmes qui manipulent des structures de données dont la taille varie dans le temps. C'est le cas pour les différents sortes de listes chaînées, les piles, les queues, les arbres, ... L'exemple ci-dessous (:download:`/C/S3-src/stack.c`) illustre une implémentation d'une pile simple en C. Le pointeur vers le sommet de la pile est défini comme une variable globale. Chaque élément de la pile est représenté comme un pointeur vers une structure qui contient un pointeur vers la donnée stockée (dans cet exemple des fractions) et l'élément suivant sur la pile. Les fonctions ``push`` et ``pop`` permettent respectivement d'ajouter un élément et de retirer un élément au sommet de la pile. La fonction ``push`` alloue la mémoire nécessaire avec `malloc(3)`_ tandis que la fonction ``pop`` utilise `free(3)`_ pour libérer la mémoire dès qu'un élément est retiré. - - -.. literalinclude:: /C/S3-src/stack.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -Ces fonctions peuvent être utilisées pour empiler et dépiler des fractions sur une pile comme dans l'exemple ci-dessous. La fonction ``display`` permet d'afficher sur :term:`stdout` le contenu de la pile. - -.. literalinclude:: /C/S3-src/stack.c - :encoding: utf-8 - :language: c - :start-after: ///BBB - :end-before: ///CCC - -Lors de son exécution le programme :download:`/C/S3-src/stack.c` présenté ci-dessus affiche les lignes suivantes sur sa sortie standard. - -.. literalinclude:: /C/S3-src/stack.out - :encoding: utf-8 - :language: console - - -Le tas (ou :term:`heap`) joue un rôle très important dans les programmes C. Les données qui sont stockées dans cette zone de la mémoire sont accessibles depuis toute fonction qui possède un pointeur vers la zone correspondante - - -.. note:: Ne comptez jamais sur les `free(3)`_ implicites - - Un programmeur débutant qui expérimente avec `malloc(3)`_ pourrait écrire le code ci-dessous et conclure que comme celui-ci s'exécute correctement, il n'est pas nécessaire d'utiliser `free(3)`_. Lors de l'exécution d'un programme, le système d'exploitation réserve de la mémoire pour les différents segments du programme et ajuste si nécessaire cette allocation durant l'exécution du programme. Lorsque le programme se termine, via ``return`` dans la fonction ``main`` ou par un appel explicite à `exit(2)`_, le système d'exploitation libère tous les segments utilisés par le programme, le text, les données, le tas et la pile. Cela implique que le système d'exploitation effectue un appel implicite à `free(3)`_ à la terminaison d'un programme. - - .. literalinclude:: /C/S3-src/nofree.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - - Un programmeur ne doit cependant `jamais` compter sur cet appel implicite à `free(3)`_. Ne pas libérer la mémoire lorsqu'elle n'est plus utilisée est un problème courant qui est généralement baptisé :term:`memory leak`. Ce problème est particulièrement gênant pour les processus tels que les serveurs Internet qui ne se terminent pas ou des processus qui s'exécutent longtemps. Une petite erreur de programmation peut causer un :term:`memory leak` qui peut après quelque temps consommer une grande partie de l'espace mémoire inutilement. Il est important d'être bien attentif à l'utilisation correcte de `malloc(3)`_ et de `free(3)`_ pour toutes les opérations d'allocation et de libération de la mémoire. - - -`malloc(3)` est la fonction d'allocation de mémoire la plus fréquemment utilisée [#fothermalloc]_. La librairie standard contient cependant d'autres fonctions permettant d'allouer de la mémoire mais aussi de modifier des allocations antérieures. `calloc(3)`_ est nettement moins utilisée que `malloc(3)`_. Elle a pourtant un avantage majeur par rapport à `malloc(3)`_ puisqu'elle initialise à zéro la zone de mémoire allouée. `malloc(3)`_ se contente d'allouer la zone de mémoire mais n'effectue aucune initialisation. Cela permet à `malloc(3)`_ d'être plus rapide, mais le programmeur ne doit jamais oublier qu'il ne peut pas utiliser `malloc(3)`_ sans initialiser la zone mémoire allouée. Cela peut s'observer en pratique avec le programme ci-dessous. Il alloue une zone mémoire pour ``v1``, l'initialise puis la libère. Ensuite, le programme alloue une nouvelle zone mémoire pour ``v2`` et y retrouve les valeurs qu'il avait stocké pour ``v1`` précédemment. En pratique, n'importe quelle valeur pourrait se trouver dans la zone retournée par `malloc(3)`. - -.. literalinclude:: /C/S3-src/mallocinit.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - -L'exécution du programme ci-dessus affiche le résultat suivant sur la sortie standard. Ceci illustre bien que la fonction `malloc(3)`_ n'initialise pas les zones de mémoire qu'elle alloue. - -.. literalinclude:: /C/S3-src/mallocinit.out - :encoding: utf-8 - :language: console - -Lors de l'exécution du programme, on remarque que la première zone mémoire retournée par `malloc(3)`_ a été initialisée à zéro. C'est souvent le cas en pratique pour des raisons de sécurité, mais ce serait une erreur de faire cette hypothèse dans un programme. Si la zone de mémoire doit être initialisée, la mémoire doit être allouée par `calloc(3)`_ ou via une initialisation explicite ou en utilisant des fonctions telles que `bzero(3)`_ ou `memset(3)`_. - -Les arguments et variables d'environnement ------------------------------------------- - -Lorsque le système d'exploitation charge un programme Unix en mémoire, il initialise dans le haut de la mémoire une zone qui contient deux types de variables. Cette zone contient tout d'abord les arguments qui ont été passés via la ligne de commande. Le système d'exploitation met dans ``argc`` le nombre d'arguments et place dans ``char *argv[]`` tous les arguments passés avec dans ``argv[0]`` le nom du programme qui est exécuté. - -Cette zone contient également les variables d'environnement. Ces variables sont généralement relatives à la configuration du système. Leurs valeurs sont définies par l'administrateur système ou l'utilisateur. De nombreuses variables d'environnement sont utilisées dans les systèmes Unix. Elles servent à modifier le comportement de certains programmes. Une liste exhaustive de toutes les variables d'environnement est impossible, mais en voici quelques unes qui sont utiles en pratique [#fenvbash]_: - - - ``HOSTNAME`` : le nom de la machine sur laquelle le programme s'exécute. Ce nom est fixé par l'administrateur système via la commande `hostname(1)`_ - - ``SHELL`` : l'interpréteur de commande utilisé par défaut pour l'utilisateur courant. Cet interpréteur est lancé par le système au démarrage d'une session de l'utilisateur. Il est stocké dans le fichier des mots de passe et peut être modifié par l'utilisateur via la commande `passwd(1)`_ - - ``USER`` : le nom de l'utilisateur courant. Sous Unix, chaque utilisateur est identifié par un numéro d'utilisateur et un nom uniques. Ces identifiants sont fixés par l'administrateur système via la commande `passwd(1)`_ - - ``HOME``: le répertoire d'accueil de l'utilisateur courant. Ce répertoire d'accueil appartient à l'utilisateur. C'est dans ce répertoire qu'il peut stocker tous ses fichiers. - - ``PRINTER`` : le nom de l'imprimante par défaut qui est utilisée par la commande `lp(1posix)`_ - - ``PATH``: cette variable d'environnement contient la liste ordonnée des répertoires que le système parcourt pour trouver un programme à exécuter. Cette liste contient généralement les répertoires dans lesquels le système stocke les exécutables standards, comme ``/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:`` ainsi que des répertoires relatifs à des programmes spécialisés comme ``/usr/lib/mozart/bin:/opt/python3/bin``. L'utilisateur peut ajouter des répertoires à son ``PATH`` avec `bash(1)`_ en incluant par exemple la commande ``PATH=$PATH:$HOME/local/bin:.`` dans son fichier ``.profile``. Cette commande ajoute au ``PATH`` par défaut le répertoire ``$HOME/local/bin`` et le répertoire courant. Par convention, Unix utilise le caractère ``.`` pour représenter ce répertoire courant. - -La librairie standard contient plusieurs fonctions qui permettent de manipuler les variables d'environnement d'un processus. La fonction `getenv(3)`_ permet de récupérer la valeur associée à une variable d'environnement. La fonction `unsetenv(3)`_ permet de supprimer une variable de l'environnement du programme courant. La fonction `setenv(3)`_ permet elle de modifier la valeur d'une variable d'environnement. Cette fonction alloue de la mémoire pour stocker la nouvelle variable d'environnement et peut échouer si il n'y a pas assez de mémoire disponible pour stocker de nouvelles variables d'environnement. Ces fonctions sont utilisées notamment par l'interpréteur de commande mais parfois par des programmes dont le comportement dépend de la valeur de certaines variables d'environnement. Par exemple, la commande `man(1)`_ utilise différentes variables d'environnement pour déterminer par exemple où les pages de manuel sont stockées et la langue (variable ``LANG``) dans laquelle il faut afficher les pages de manuel. - -Le programme ci-dessous illustre brièvement l'utilisation de `getenv(3)`_, `unsetenv(3)`_ et `setenv(3)`_. Outre ces fonctions, il existe également `clearenv(3)`_ qui permet d'effacer complètement toutes les variables d'environnement du programme courant et `putenv(3)`_ qui était utilisé avant `setenv(3)`_. - -.. literalinclude:: /C/S3-src/argv-env.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - - -La pile (ou stack) ------------------- - -La :term:`pile` ou :term:`stack` en anglais est la dernière zone de mémoire utilisée par un processus. C'est une zone très importante car c'est dans cette zone que le processus va stocker l'ensemble des variables locales mais également les valeurs de retour de toutes les fonctions qui sont appelées. Cette zone est gérée comme une pile, d'où son nom. Pour comprendre son fonctionnement, nous utiliserons le programme :download:`/C/S3-src/fact.c` qui permet de calculer une factorielle de façon récursive. - -.. literalinclude:: /C/S3-src/fact.c - :encoding: utf-8 - :language: c - :start-after: ///BBB - :end-before: ///AAA - -Lors de l'exécution de la fonction ``compute()``, le programme ci-dessus produit la sortie suivante. - - -.. literalinclude:: /C/S3-src/fact.out - :encoding: utf-8 - :language: console - :start-after: ///FACT - -Il est intéressant d'analyser en détails ce calcul récursif de la factorielle car il illustre bien le fonctionnement du stack et son utilisation. - -Tout d'abord, il faut noter que les fonctions ``fact`` et ``times`` se trouvent, comme toutes les fonctions définies dans le programme, à l'intérieur du :term:`segment text`. La variable ``nombre`` quant à elle se trouve sur la pile en haut de la mémoire. Il s'agit d'une variable locale qui est allouée lors de l'exécution de la fonction ``compute``. Il en va de même des arguments qui sont passés aux fonctions. Ceux-ci sont également stockés sur la pile. C'est le cas par exemple de l'argument ``n`` de la fonction ``fact``. Lors de l'exécution de l'appel à ``fact(3)``, la valeur ``3`` est stockée sur la pile pour permettre à la fonction ``fact`` d'y accéder. Ces accès sont relatifs au sommet de la pile comme nous aurons l'occasion de le voir dans la présentation du langage d'assemblage. Le premier appel récursif se fait en calculant la valeur de l'argument (``2``) et en appelant la fonction. L'argument est placé sur la pile, mais à une autre adresse que celle utilisée pour ``fact(3)``. Durant son exécution, la fonction ``fact(2)`` accède à ses variables locales sur la pile sans interférer avec les variables locales de l'exécution de ``fact(3)`` qui attend le résultat de ``fact(2)``. Lorsque ``fact(2)`` fait l'appel récursif, la valeur de son argument (``1``) est placée sur la pile et l'exécution de ``fact(1)`` démarre. Celle-ci a comme environnement d'exécution le sommet de la pile qui contient la valeur ``1`` comme argument et la fonction retourne la valeur ``1`` à l'exécution de ``fact(2)`` qui l'avait lancée. Dès la fin de ``fact(1)``, ``fact(2)`` reprend son exécution où elle avait été interrompue et applique la fonction ``times`` avec ``2`` et ``1`` comme arguments. Ces deux arguments sont placés sur le pile et ``times`` peut y accéder au début de son exécution pour calculer la valeur ``2`` et retourner le résultat à la fonction qui l'a appelé, c'est-à -dire ``fact(2)``. Cette dernière retrouve son environnement d'exécution sur la pile. Elle peut maintenant retourner son résultat à la fonction ``fact(3)`` qui l'avait appelée. Celle-ci va appeler la fonction ``times`` avec ``3`` et ``2`` comme arguments et finira par retourner la valeur ``6``. - -La pile joue un rôle essentiel lors de l'exécution de programmes en C puisque toutes les variables locales, y compris celles de la fonction ``main`` y sont stockées. Comme nous le verrons lorsque nous aborderons le langage assembleur, la pile sert aussi à stocker l'adresse de retour des fonctions. C'est ce qui permet à l'exécution de ``fact(2)`` de se poursuivre correctement après avoir récupéré la valeur calculée par l'appel à ``fact(1)``. L'utilisation de la pile pour stocker les variables locales et les arguments de fonctions a une conséquence importante. Lorsqu'une variable est définie comme argument ou localement à une fonction ``f``, elle n'est accessible que durant l'exécution de la fonction ``f``. Avant l'exécution de ``f`` cette variable n'existe pas et si ``f`` appelle la fonction ``g``, la variable définie dans ``f`` n'est plus accessible à partir de la fonction ``g``. - -En outre, comme le langage C utilise le passage par valeur, les valeurs des arguments d'une fonction sont copiés sur la pile avant de démarrer l'exécution de cette fonction. Lorsque la fonction prend comme argument un entier, cette copie prend un temps très faible. Par contre, lorsque la fonction prend comme argument une ou plusieurs structures de grand taille, celles-ci doivent être entièrement copiées sur la pile. A titre d'exemple, le programme ci-dessous définit une très grande structure contenant un entier et une zone permettant de stocker un million de caractères. Lors de l'appel à la fonction ``sum``, les structures ``one`` et ``two`` sont entièrement copiées sur la pile. Comme chaque structure occupe plus d'un million d'octets, cela prend plusieurs centaines de microsecondes. Cette copie est nécessaire pour respecter le passage par valeur des structures à la fonction ``sum``. Celle-ci ne peut pas modifier le contenu des structures qui lui sont passées en argument. Par comparaison, lors de l'appel à ``sumptr``, seules les adresses de ces deux structures sont copiées sur la pile. Un appel à ``sumptr`` prend moins d'une microseconde, mais bien entendu la fonction ``sumptr`` a accès via les pointeurs passés en argument à toute la zone de mémoire qui leur est associée. - -.. literalinclude:: /C/S3-src/structargs.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -Certaines variantes de Unix et certains compilateurs permettent l'allocation de mémoire sur la pile via la fonction `alloca(3)`_. Contrairement à la mémoire allouée par `malloc(3)`_ qui doit être explicitement libérée en utilisant `free(3)`_, la mémoire allouée par `alloca(3)`_ est libérée automatiquement à la fin de l'exécution de la fonction dans laquelle la mémoire a été allouée. Cette façon d'allouer de la mémoire sur la pile n'est pas portable et il est préférable de n'allouer de la mémoire que sur le tas en utilisant `malloc(3)`_. - -Les versions récentes du C et notamment [C99]_ permettent d'allouer de façon dynamique un tableau sur la pile. Cette fonctionnalité peut être utile dans certains cas, mais elle peut aussi être la source de nombreuses erreurs et difficultés. Pour bien comprendre ce problème, considérons à nouveau la fonction ``duplicate`` qui a été définie précédemment en utilisant `malloc(3)`_ et des pointeurs. - -.. literalinclude:: /C/S3-src/strcpy.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -Un étudiant pourrait vouloir éviter d'utiliser `malloc(3)`_ et écrire plutôt la fonction suivante. - -.. literalinclude:: /C/S3-src/strcpy.c - :encoding: utf-8 - :language: c - :start-after: ///BBB - :end-before: ///CCC - -.. spelling:: - - warning - -Lors de la compilation, `gcc(1)`_ affiche le :term:`warning` ``In function ‘duplicate2’: warning: function returns address of local variable``. Ce warning indique que la ligne ``return str2;`` retourne l'adresse d'une variable locale qui n'est plus accessible à la fin de la fonction ``duplicate2``. En effet, l'utilisation de tableaux alloués dynamiquement sur la pile est équivalent à une utilisation implicite de `alloca(3)`_. La déclaration ``char str2[len];`` est équivalente à ``char *str2 =(char *)alloca(len*sizeof(char));`` et la zone mémoire allouée sur la pile pour ``str2`` est libérée lors de l'exécution de ``return str2;`` puisque toute mémoire allouée sur la pile est implicitement libérée à la fin de l'exécution de la fonction durant laquelle elle a été allouée. Donc, une fonction qui appelle ``duplicate2`` ne peut pas récupérer les données se trouvant dans la zone mémoire qui a été allouée par ``duplicate2``. - - - -.. rubric:: Footnotes - -.. [#fpossible] Pour des raisons de performance, le compilateur C ne génère pas de code permettant de vérifier automatiquement qu'un accès via un pointeur pointe vers une zone de mémoire qui est libre. Il est donc parfois possible d'accéder à une zone mémoire qui a été libérée, mais le programme n'a aucune garantie sur la valeur qu'il y trouvera. Ce genre d'accès à des zones mémoires libérées doit bien entendu être complètement proscrit. - -.. [#ggetrlimit] Sur de nombreuses variantes de Unix, cette limite à la taille du stack dépend du matériel utilisé et peut être configurée par l'administrateur système. Un processus peut connaître la taille maximale de son stack en utilisant l'appel système `getrlimit(2)`_. L'administrateur système peut modifier ces limites via l'appel système `setrlimit(2)`_. La commande ``ulimit`` de `bash(1)`_ permet également de manipuler ces limites. - -.. [#fetext] Dans de nombreuses variantes de Unix, il est possible de connaître le sommet du segment :term:`text` d'un processus grâce à la variable :term:`etext`. Cette variable, de type ``char`` est initialisée par le système au chargement du processus. Elle doit être déclarée comme variable de type ``extern char etext`` et son adresse (``&etext``) correspond au sommet du segment text. - -.. [#fvmem] Nous verrons ultérieurement que grâce à l'utilisation de la mémoire virtuelle, il est possible pour un processus d'utiliser des zones de mémoire qui ne sont pas contiguës. - -.. [#fothermalloc] Il existe différentes alternatives à l'utilisation de `malloc(3)`_ pour l'allocation de mémoire comme `Hoard <http://www.hoard.org/>`_ ou `gperftools <http://code.google.com/p/gperftools/>`_ - -.. [#fenvbash] Il possible de lister les définitions actuelles des variables d'environnement via la commande `printenv(1)`_. Les interpréteurs de commande tels que `bash(1)`_ permettent de facilement modifier les valeurs de ces variables. La plupart d'entre elles sont initialisées par le système ou via les fichiers qui sont chargés automatiquement au démarrage de l'interpréteur comme ``/etc/profile`` qui contient les variables fixées par l'administrateur système ou le fichier ``.profile`` du répertoire d'accueil de l'utilisateur qui contient les variables d'environnement propres à cet utilisateur. - - - diff --git a/Theorie/C/src/cmdline.c b/Theorie/C/src/cmdline.c deleted file mode 100644 index 9d9ec77ec8633c2c38cad7829629ae8fdcb674c5..0000000000000000000000000000000000000000 --- a/Theorie/C/src/cmdline.c +++ /dev/null @@ -1,19 +0,0 @@ -/************************************** - * cmdline.c - * - * Programme affichant ses arguments - * sur la sortie standard - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) -{ - int i; - printf("Ce programme a %d argument(s)\n", argc); - for (i = 0; i < argc; i++) - printf("argument[%d] : %s\n", i, argv[i]); - return EXIT_SUCCESS; -} diff --git a/Theorie/C/src/cmdline.out b/Theorie/C/src/cmdline.out deleted file mode 100644 index 90ce18288d15f0de91ab646132fd7b5b5da9c186..0000000000000000000000000000000000000000 --- a/Theorie/C/src/cmdline.out +++ /dev/null @@ -1,6 +0,0 @@ -Ce programme a 5 argument(s) -argument[0] : ./cmdline -argument[1] : 1 -argument[2] : -list -argument[3] : abcdef -argument[4] : sinf1252 diff --git a/Theorie/C/src/failure.c b/Theorie/C/src/failure.c deleted file mode 100644 index 321885bf51dee70fcb61f2959e7145ea0da70476..0000000000000000000000000000000000000000 --- a/Theorie/C/src/failure.c +++ /dev/null @@ -1,13 +0,0 @@ -/************************************** - * failure.c - * - * Programme minimal qui échoue toujours - * - **************************************/ - -#include <stdlib.h> - -int main(int argc, char *argv[]) -{ - return EXIT_FAILURE; -} diff --git a/Theorie/C/src/filterdigit.c b/Theorie/C/src/filterdigit.c deleted file mode 100644 index f242bef2aacceec6c8fb990f213498cc434af4e3..0000000000000000000000000000000000000000 --- a/Theorie/C/src/filterdigit.c +++ /dev/null @@ -1,41 +0,0 @@ -/************************************** - * filterdigit.c - * - * Programme qui extrait de l'entrée - * standard les caractères représentant - * des chiffres - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -// retourne vrai si c est un chiffre, faux sinon -// exemple simplifié, voir isdigit dans la librarire standard -// pour une solution complète -int digit(char c) -{ - return ((c >= '0') && (c <= '9')); -} - -// affiche un message d'erreur -void usage() -{ - fprintf(stderr, "Ce programme ne prend pas d'argument\n"); - exit(EXIT_FAILURE); -} - -int main(int argc, char *argv[]) -{ - char c; - - if (argc > 1) - usage(); - - while ((c = getchar()) != EOF) { - if (digit(c)) - putchar(c); - } - - return EXIT_SUCCESS; -} - diff --git a/Theorie/C/src/hello.c b/Theorie/C/src/hello.c deleted file mode 100644 index a616435889fe024f86372035270f10f245e443ef..0000000000000000000000000000000000000000 --- a/Theorie/C/src/hello.c +++ /dev/null @@ -1,18 +0,0 @@ -/************************************** - * Hello.c - * - * Programme affichant sur la sortie - * standard le message "Hello, world!" - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) -{ - // affiche sur la sortie standard - printf("Hello, world!\n"); - - return EXIT_SUCCESS; -} diff --git a/Theorie/C/src/printf.c b/Theorie/C/src/printf.c deleted file mode 100644 index a10b63583210a468cb32cadf440af5192ef3eb1f..0000000000000000000000000000000000000000 --- a/Theorie/C/src/printf.c +++ /dev/null @@ -1,37 +0,0 @@ -/************************************** - * printf.c - * - * Exemples d'utilisation de printfProgramme qui a réussi - * - **************************************/ - -#include <stdlib.h> -#include <stdio.h> -#include <math.h> - -int main(int argc, char *argv[]) -{ - ///AAA - - char weekday[] = "Monday"; - char month[] = "April"; - int day = 1; - int hour = 12; - int min = 42; - char str[] = "SINF1252"; - int i; - - // affichage de la date et l'heure - printf("%s, %s %d, %d:%d\n", weekday, month, day, hour, min); - - // affichage de la valeur de PI - printf("PI = %f\n", 4 * atan(1.0)); - - // affichage d'un caractère par ligne - for(i = 0; str[i] != '\0'; i++) - printf("%c\n", str[i]); - - ///BBB - - return EXIT_SUCCESS; -} diff --git a/Theorie/C/src/printf.out b/Theorie/C/src/printf.out deleted file mode 100644 index 52d6f66f96fec16dcee9f506fd22d0dfbc4dfa1f..0000000000000000000000000000000000000000 --- a/Theorie/C/src/printf.out +++ /dev/null @@ -1,10 +0,0 @@ -Monday, April 1, 12:42 -PI = 3.141593 -S -I -N -F -1 -2 -5 -2 diff --git a/Theorie/C/src/ptr_arith.c b/Theorie/C/src/ptr_arith.c deleted file mode 100644 index a4fe502d3f8e3240fbda0ae56bc75c33d923fa66..0000000000000000000000000000000000000000 --- a/Theorie/C/src/ptr_arith.c +++ /dev/null @@ -1,46 +0,0 @@ -// arithmétique des pointeurs - -#include <stdio.h> - -int main(int argc, char *argv[]) -{ -///AAA - -#define SIZE 3 -unsigned int tab[3]; -tab[0] = 0x01020304; -tab[1] = 0x05060708; -tab[2] = 0x090A0B0C; - -///BBB - -///CCC - -int i; -for (i = 0; i < SIZE; i++) { - printf("%X est à l'adresse %p\n", tab[i], &(tab[i])); -} - -///DDD - -///EEE - -unsigned int* ptr = tab; -for (i = 0; i < SIZE; i++) { - printf("%X est à l'adresse %p\n", *ptr, ptr); - ptr++; -} - -///FFF - -///GGG - -unsigned char* ptr_char = (unsigned char *) tab; -printf("ptr_char contient %p\n", ptr_char); -for (i = 0; i < SIZE + 1; i++) { - printf("%X est à l'adresse %p\n", *ptr_char, ptr_char); - ptr_char++; -} - -///HHH -} diff --git a/Theorie/C/src/string.c b/Theorie/C/src/string.c deleted file mode 100644 index 7970ef7065d43a5a19c23e586b86e79cb248ced2..0000000000000000000000000000000000000000 --- a/Theorie/C/src/string.c +++ /dev/null @@ -1,26 +0,0 @@ -/************************************** - * string.c - * - * Programme d'expemple avec les strings - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) -{ - ///AAA - - char string[10]; - string[0] = 'j'; - string[1] = 'a'; - string[2] = 'v'; - string[3] = 'a'; - string[4] = '\0'; - printf("String : %s\n", string); - - ///BBB - - return EXIT_SUCCESS; -} diff --git a/Theorie/C/svg/Float_example.png b/Theorie/C/svg/Float_example.png deleted file mode 100644 index fde60d9ec96ab8eefb67dc7be3c7c8094df637fe..0000000000000000000000000000000000000000 Binary files a/Theorie/C/svg/Float_example.png and /dev/null differ diff --git a/Theorie/C/svg/Float_example.svg b/Theorie/C/svg/Float_example.svg deleted file mode 100644 index 4e875ef641eacf30a336cd6169fbfdf9e65e339d..0000000000000000000000000000000000000000 --- a/Theorie/C/svg/Float_example.svg +++ /dev/null @@ -1,715 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> -<svg - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - version="1.0" - width="590" - height="75" - id="svg2"> - <defs - id="defs4"> - <marker - refX="0" - refY="0" - orient="auto" - style="overflow:visible" - id="Arrow2Mend"> - <path - d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z " - transform="scale(-0.6,-0.6)" - style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" - id="path3321" /> - </marker> - </defs> - <rect - width="120.00082" - height="26.023895" - x="29.259886" - y="28.699614" - style="fill:none;fill-opacity:0.39473685;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3147" /> - <rect - width="14.999176" - height="26.023895" - x="134.26152" - y="28.699369" - style="fill:#10ff2e;fill-opacity:0.39607843;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3522" /> - <path - d="M 30.239243,25.223251 L 30.239243,15.797501 L 148.37786,15.797501 L 148.37786,25.223251" - style="fill:none;fill-rule:evenodd;stroke:#008000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - id="path2170" /> - <path - d="M 150.26069,25.223251 L 150.26069,15.797501 L 493.40792,15.797501 L 493.40792,25.223251" - style="fill:none;fill-rule:evenodd;stroke:#800000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - id="path2172" /> - <rect - width="345.97119" - height="26.023642" - x="149.25989" - y="28.66995" - style="fill:none;fill-opacity:0.36078431;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect2174" /> - <rect - width="14.999176" - height="26.023895" - x="14.260694" - y="28.699369" - style="fill:#0af5ff;fill-opacity:0.23684214;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3149" /> - <text - x="28.313053" - y="11.141996" - style="font-size:14.64121246px;font-style:normal;text-align:end;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Gill Sans MT" - id="text3151" - xml:space="preserve"><tspan - x="28.313053" - y="11.141996" - style="font-weight:normal;text-align:end;text-anchor:end;font-family:Arial" - id="tspan3153">sign</tspan></text> - <text - x="89.090508" - y="11.141996" - style="font-size:14.64121246px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Gill Sans MT" - id="text3369" - xml:space="preserve"><tspan - x="89.090508" - y="11.141996" - style="font-weight:normal;font-family:Arial" - id="tspan3371">exponent (8 bits)</tspan></text> - <text - x="322.27396" - y="11.141996" - style="font-size:14.64121246px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Gill Sans MT" - id="text3377" - xml:space="preserve"><tspan - x="322.27396" - y="11.141996" - style="font-weight:normal;font-family:Arial" - id="tspan3379">fraction (23 bits)</tspan></text> - <path - d="M 489.73149,59.223243 C 489.73224,59.938278 489.35121,60.599322 488.7321,60.957058 C 488.11299,61.314795 487.34999,61.314795 486.73088,60.957058 C 486.11176,60.599322 485.73074,59.938278 485.73149,59.223243 C 485.73074,58.508207 486.11176,57.847163 486.73088,57.489428 C 487.34999,57.131691 488.11299,57.131691 488.7321,57.489428 C 489.35121,57.847163 489.73224,58.508207 489.73149,59.223243 L 489.73149,59.223243 z " - style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="path3381" /> - <text - x="487.77948" - y="74.338959" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3383" - xml:space="preserve"><tspan - x="487.77948" - y="74.338959" - style="font-weight:normal" - id="tspan3385">0</tspan></text> - <path - d="M 143.7611,59.223253 C 143.76185,59.938288 143.38082,60.599332 142.76171,60.957068 C 142.1426,61.314805 141.3796,61.314805 140.76049,60.957068 C 140.14137,60.599332 139.76035,59.938288 139.7611,59.223253 C 139.76035,58.508217 140.14137,57.847173 140.76049,57.489438 C 141.3796,57.131701 142.1426,57.131701 142.76171,57.489438 C 143.38082,57.847173 143.76185,58.508217 143.7611,59.223253 L 143.7611,59.223253 z " - style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="path3397" /> - <text - x="139.87766" - y="74.338959" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3399" - xml:space="preserve"><tspan - x="139.87766" - y="74.338959" - style="font-weight:normal" - id="tspan3401">23</tspan></text> - <path - d="M 23.760282,59.223253 C 23.761036,59.938288 23.380007,60.599332 22.760896,60.957068 C 22.141785,61.314805 21.37878,61.314805 20.759669,60.957068 C 20.140558,60.599332 19.75953,59.938288 19.760284,59.223253 C 19.75953,58.508217 20.140558,57.847173 20.759669,57.489438 C 21.37878,57.131701 22.141785,57.131701 22.760896,57.489438 C 23.380007,57.847173 23.761036,58.508217 23.760282,59.223253 L 23.760282,59.223253 z " - style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="path3413" /> - <text - x="19.256382" - y="74.338959" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3415" - xml:space="preserve"><tspan - x="19.256382" - y="74.338959" - style="font-weight:normal" - id="tspan3417">31</tspan></text> - <path - d="M 21.760283,25.223251 L 21.760283,15.797501" - style="fill:none;fill-rule:evenodd;stroke:#008080;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - id="path2232" /> - <rect - width="14.999176" - height="26.023895" - x="119.26128" - y="28.699369" - style="fill:#10ff2e;fill-opacity:0.39607843;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3508" /> - <rect - width="14.999176" - height="26.023895" - x="104.26105" - y="28.699369" - style="fill:#10ff2e;fill-opacity:0.39607843;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3510" /> - <rect - width="14.999176" - height="26.023895" - x="89.260818" - y="28.699369" - style="fill:#10ff2e;fill-opacity:0.39607843;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3512" /> - <rect - width="14.999176" - height="26.023895" - x="74.260582" - y="28.699369" - style="fill:#10ff2e;fill-opacity:0.39607843;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3514" /> - <rect - width="14.999176" - height="26.023895" - x="59.260353" - y="28.699369" - style="fill:#10ff2e;fill-opacity:0.39607843;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3516" /> - <rect - width="14.999176" - height="26.023895" - x="44.260117" - y="28.699369" - style="fill:#10ff2e;fill-opacity:0.39607843;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3518" /> - <rect - width="14.999176" - height="26.023895" - x="29.259886" - y="28.699369" - style="fill:#10ff2e;fill-opacity:0.39607843;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3520" /> - <rect - width="14.999176" - height="26.023895" - x="149.25989" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3525" /> - <rect - width="14.999176" - height="26.023895" - x="164.30408" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3533" /> - <rect - width="14.999176" - height="26.023895" - x="179.34825" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3535" /> - <rect - width="14.999176" - height="26.023895" - x="194.39244" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3537" /> - <rect - width="14.999176" - height="26.023895" - x="209.43661" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3539" /> - <rect - width="14.999176" - height="26.023895" - x="224.4808" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3541" /> - <rect - width="14.999176" - height="26.023895" - x="239.52499" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3543" /> - <rect - width="14.999176" - height="26.023895" - x="254.56917" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3545" /> - <rect - width="14.999176" - height="26.023895" - x="269.61334" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3547" /> - <rect - width="14.999176" - height="26.023895" - x="284.65753" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3549" /> - <rect - width="14.999176" - height="26.023895" - x="299.70172" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3551" /> - <rect - width="14.999176" - height="26.023895" - x="314.74591" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3553" /> - <rect - width="14.999176" - height="26.023895" - x="329.7901" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3555" /> - <rect - width="14.999176" - height="26.023895" - x="344.83429" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3557" /> - <rect - width="14.999176" - height="26.023895" - x="359.87845" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3559" /> - <rect - width="14.999176" - height="26.023895" - x="374.92264" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3561" /> - <rect - width="14.999176" - height="26.023895" - x="389.96683" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3563" /> - <rect - width="14.999176" - height="26.023895" - x="405.01102" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3565" /> - <rect - width="14.999176" - height="26.023895" - x="420.05521" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3567" /> - <rect - width="14.999176" - height="26.023895" - x="435.09937" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3569" /> - <rect - width="14.999176" - height="26.023895" - x="450.14355" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3571" /> - <rect - width="14.999176" - height="26.023895" - x="465.18774" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3573" /> - <rect - width="14.999176" - height="26.023895" - x="480.2319" - y="28.699369" - style="fill:#ff1e1e;fill-opacity:0.36078431;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3575" /> - <text - x="22.288181" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3581" - xml:space="preserve"><tspan - x="22.288181" - y="46.757179" - style="font-weight:normal" - id="tspan3583">0</tspan></text> - <text - x="37.319508" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3585" - xml:space="preserve"><tspan - x="37.319508" - y="46.757179" - style="font-weight:normal" - id="tspan3587">0</tspan></text> - <text - x="52.350842" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3589" - xml:space="preserve"><tspan - x="52.350842" - y="46.757179" - style="font-weight:normal" - id="tspan3591">1</tspan></text> - <text - x="67.382164" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3593" - xml:space="preserve"><tspan - x="67.382164" - y="46.757179" - style="font-weight:normal" - id="tspan3595">1</tspan></text> - <text - x="82.413498" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3597" - xml:space="preserve"><tspan - x="82.413498" - y="46.757179" - style="font-weight:normal" - id="tspan3599">1</tspan></text> - <text - x="97.444824" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3601" - xml:space="preserve"><tspan - x="97.444824" - y="46.757179" - style="font-weight:normal" - id="tspan3603">1</tspan></text> - <text - x="112.47616" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3605" - xml:space="preserve"><tspan - x="112.47616" - y="46.757179" - style="font-weight:normal" - id="tspan3607">1</tspan></text> - <text - x="127.50748" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3609" - xml:space="preserve"><tspan - x="127.50748" - y="46.757179" - style="font-weight:normal" - id="tspan3611">0</tspan></text> - <text - x="142.53882" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3613" - xml:space="preserve"><tspan - x="142.53882" - y="46.757179" - style="font-weight:normal" - id="tspan3615">0</tspan></text> - <text - x="157.57016" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3617" - xml:space="preserve"><tspan - x="157.57016" - y="46.757179" - style="font-weight:normal" - id="tspan3619">0</tspan></text> - <text - x="172.60149" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3621" - xml:space="preserve"><tspan - x="172.60149" - y="46.757179" - style="font-weight:normal" - id="tspan3623">1</tspan></text> - <text - x="187.63281" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3625" - xml:space="preserve"><tspan - x="187.63281" - y="46.757179" - style="font-weight:normal" - id="tspan3627">0</tspan></text> - <text - x="202.66414" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3629" - xml:space="preserve"><tspan - x="202.66414" - y="46.757179" - style="font-weight:normal" - id="tspan3631">0</tspan></text> - <text - x="217.69548" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3633" - xml:space="preserve"><tspan - x="217.69548" - y="46.757179" - style="font-weight:normal" - id="tspan3635">0</tspan></text> - <text - x="232.72681" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3637" - xml:space="preserve"><tspan - x="232.72681" - y="46.757179" - style="font-weight:normal" - id="tspan3639">0</tspan></text> - <text - x="247.75813" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3641" - xml:space="preserve"><tspan - x="247.75813" - y="46.757179" - style="font-weight:normal" - id="tspan3643">0</tspan></text> - <text - x="262.78946" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3645" - xml:space="preserve"><tspan - x="262.78946" - y="46.757179" - style="font-weight:normal" - id="tspan3647">0</tspan></text> - <text - x="277.82077" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3649" - xml:space="preserve"><tspan - x="277.82077" - y="46.757179" - style="font-weight:normal" - id="tspan3651">0</tspan></text> - <text - x="292.85211" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3653" - xml:space="preserve"><tspan - x="292.85211" - y="46.757179" - style="font-weight:normal" - id="tspan3655">0</tspan></text> - <text - x="307.88345" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3657" - xml:space="preserve"><tspan - x="307.88345" - y="46.757179" - style="font-weight:normal" - id="tspan3659">0</tspan></text> - <text - x="322.91476" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3661" - xml:space="preserve"><tspan - x="322.91476" - y="46.757179" - style="font-weight:normal" - id="tspan3663">0</tspan></text> - <text - x="337.94611" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3665" - xml:space="preserve"><tspan - x="337.94611" - y="46.757179" - style="font-weight:normal" - id="tspan3667">0</tspan></text> - <text - x="352.97742" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3669" - xml:space="preserve"><tspan - x="352.97742" - y="46.757179" - style="font-weight:normal" - id="tspan3671">0</tspan></text> - <text - x="368.00876" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3673" - xml:space="preserve"><tspan - x="368.00876" - y="46.757179" - style="font-weight:normal" - id="tspan3675">0</tspan></text> - <text - x="383.0401" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3677" - xml:space="preserve"><tspan - x="383.0401" - y="46.757179" - style="font-weight:normal" - id="tspan3679">0</tspan></text> - <text - x="398.07141" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3681" - xml:space="preserve"><tspan - x="398.07141" - y="46.757179" - style="font-weight:normal" - id="tspan3683">0</tspan></text> - <text - x="413.10275" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3685" - xml:space="preserve"><tspan - x="413.10275" - y="46.757179" - style="font-weight:normal" - id="tspan3687">0</tspan></text> - <text - x="428.13409" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3689" - xml:space="preserve"><tspan - x="428.13409" - y="46.757179" - style="font-weight:normal" - id="tspan3691">0</tspan></text> - <text - x="443.16541" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3693" - xml:space="preserve"><tspan - x="443.16541" - y="46.757179" - style="font-weight:normal" - id="tspan3695">0</tspan></text> - <text - x="458.19675" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3697" - xml:space="preserve"><tspan - x="458.19675" - y="46.757179" - style="font-weight:normal" - id="tspan3699">0</tspan></text> - <text - x="473.22806" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3701" - xml:space="preserve"><tspan - x="473.22806" - y="46.757179" - style="font-weight:normal" - id="tspan3703">0</tspan></text> - <text - x="488.2594" - y="46.757179" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3705" - xml:space="preserve"><tspan - x="488.2594" - y="46.757179" - style="font-weight:normal" - id="tspan3707">0</tspan></text> - <text - x="504.2641" - y="48.399105" - style="font-size:18.6884346px;font-style:normal;text-align:start;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3709" - xml:space="preserve"><tspan - x="504.2641" - y="48.399105" - style="font-weight:normal;text-align:start;text-anchor:start" - id="tspan3711">= 0.15625</tspan></text> - <path - d="M 38.759473,59.223253 C 38.760227,59.938288 38.379198,60.599332 37.760087,60.957068 C 37.140976,61.314805 36.377971,61.314805 35.75886,60.957068 C 35.139749,60.599332 34.758721,59.938288 34.759475,59.223253 C 34.758721,58.508217 35.139749,57.847173 35.75886,57.489438 C 36.377971,57.131701 37.140976,57.131701 37.760087,57.489438 C 38.379198,57.847173 38.760227,58.508217 38.759473,59.223253 L 38.759473,59.223253 z " - style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="path3959" /> - <text - x="39.756992" - y="74.338959" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3961" - xml:space="preserve"><tspan - x="39.756992" - y="74.338959" - style="font-weight:normal" - id="tspan3963">30</tspan></text> - <path - d="M 158.75948,59.223253 C 158.76023,59.938288 158.3792,60.599332 157.76009,60.957068 C 157.14098,61.314805 156.37798,61.314805 155.75887,60.957068 C 155.13975,60.599332 154.75873,59.938288 154.75948,59.223253 C 154.75873,58.508217 155.13975,57.847173 155.75887,57.489438 C 156.37798,57.131701 157.14098,57.131701 157.76009,57.489438 C 158.3792,57.847173 158.76023,58.508217 158.75948,59.223253 L 158.75948,59.223253 z " - style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="path3965" /> - <text - x="158.87602" - y="74.338959" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3967" - xml:space="preserve"><tspan - x="158.87602" - y="74.338959" - style="font-weight:normal" - id="tspan3969">22</tspan></text> - <text - x="255.87602" - y="74.338959" - style="font-size:14.04066658px;font-style:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial" - id="text3971" - xml:space="preserve"><tspan - x="255.87602" - y="74.338959" - style="font-weight:normal" - id="tspan3973">(bit index)</tspan></text> -</svg> diff --git a/Theorie/Fichiers/fichiers-signaux.rst b/Theorie/Fichiers/fichiers-signaux.rst deleted file mode 100644 index 1dc29d8a3bacc6710baff4b40e12da7589ac87e2..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/fichiers-signaux.rst +++ /dev/null @@ -1,566 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Sur un système Unix, il est fréquent que des processus différents doivent communiquer entre eux et coordonner leurs activités. Dans ce chapitre, nous détaillons plusieurs mécanismes permettant à des processus ayant un ancêtre commun ou non de coordonner leurs activités. - -Historiquement, le premier mécanisme de coordination entre processus a été l'utilisation des signaux. Nous avons déjà utilisé des signaux sans les avoir détaillés explicitement pour terminer des processus avec la commande `kill(1)`_. Nous décrivons plus en détails les principales utilisations des signaux dans ce chapitre. - -Lorsque deux processus ont un ancêtre commun, il est possible de les relier en utilisant un `pipe(2)`_. Si ils n'ont pas d'ancêtre commun, il est possible d'utiliser une :term:`fifo` pour obtenir un effet similaire. Une :term:`fifo` peut être créée en utilisant la commande `mkfifo(1)`_ ou la fonction `mkfifo(3)`_. `mkfifo(3)`_ s'utilise comme l'appel système `open(2)`_. Pour créer une nouvelle :term:`fifo`, il suffit de lui donner un nom sous la forme d'une chaîne de caractères et tout processus qui connait le nom de la :term:`fifo` pourra l'utiliser. - -.. todo:: expliquer plus en détails les fifo dans une prochaine version - -Les sémaphores que nous avons utilisés pour coordonner plusieurs threads sont également utilisables entre processus moyennant quelques différences que nous détaillerons. - -Enfin, des processus liés ou non doivent parfois accéder aux mêmes fichiers. Ces accès concurrents, si ils ne sont pas correctement coordonnés, peuvent conduire à des corruptions de fichiers. Nous présenterons les mécanismes de locking qui sont utilisés dans Unix et Linux pour coordonner l'accès à des fichiers. - -.. _signaux: - -Signaux -======= - -L'envoi et la réception de signaux est le mécanisme de communication entre processus le plus primitif sous Unix. Un :term:`signal` est une forme d'interruption logicielle [StevensRago2008]. Comme nous l'avons vu précédemment, un microprocesseur utilise les interruptions pour permettre au système d'exploitation de réagir aux événements imprévus qui surviennent. Un :term:`signal` Unix est un mécanisme qui permet à un processus de réagir de façon asynchrone à un événement qui s'est produit. Certains de ces événements sont directement liés au fonctionnement du matériel. D'autres sont provoqués par le processus lui-même ou un autre processus s'exécutant sur le système. - -Pour être capable d'utiliser les signaux à bon escient, il est important de bien comprendre comment ceux-ci sont implémentés dans le système d'exploitation. - -Il existe deux types de signaux. - - - Un :term:`signal synchrone` est un :term:`signal` qui a été directement causé par l'exécution d'une instruction du processus. Un exemple typique de :term:`signal synchrone` est le signal ``SIGFPE`` qui est généré par le système d'exploitation lorsqu'un processus provoque une exception lors du calcul d'expressions mathématiques. C'est le cas notamment lors d'une division par zéro. La sortie ci-dessous illustre ce qu'il se produit lors de l'exécution du programme :download:`/Fichiers/src/sigfpe.c`. - - .. code-block:: console - - $ ./sigfpe - Calcul de : 1252/0 - Floating point exception - - - Un :term:`signal asynchrone` est un :term:`signal` qui n'a pas été directement causé par l'exécution d'une instruction du processus. Il peut être produit par le système d'exploitation ou généré par un autre processus comme lorsque nous avons utilisé `kill(1)`_ dans un shell pour terminer un processus. - -Le système Unix fournit plusieurs appels systèmes qui permettent de manipuler les signaux. Un processus peut recevoir des signaux synchrones ou asynchrones. Pour chaque signal, le système d'exploitation définit un traitement par défaut. Pour certains signaux, leur réception provoque l'arrêt du processus. Pour d'autres, le signal est ignoré et le processus peut continuer son exécution. Un processus peut redéfinir le traitement des signaux qu'il reçoit en utilisant l'appel système `signal(2)`_. Celui-ci permet d'associer un :term:`handler` ou fonction de traitement de signal à chaque signal. Lorsqu'un :term:`handler` a été associé à un signal, le système d'exploitation exécute ce :term:`handler` dès que ce signal survient. Unix permet également à un processus d'envoyer un signal à un autre processus en utilisant l'appel système `kill(2)`_. - -.. .. index:: SIGALARM, SIGBUS, SIGFPE, SIGUSR1 -.. .. index:: SIGUSR2, SIGSEGV, SIGHUP, SIGCHLD - -Avant d'analyser en détails le fonctionnement des appels systèmes `signal(2)`_ et `kill(2)`_, il est utile de parcourir les principaux signaux. Chaque :term:`signal` est identifié par un entier positif et `signal.h`_ définit des constantes pour chaque signal reconnu par le système. Sous Linux, les principaux signaux sont : - - - ``SIGALRM``. Ce signal survient lorsqu'une alarme définie par la fonction `alarm(3posix)`_ ou l'appel système `setitimer(2)`_ a expiré. Par défaut, la réception de ce signal provoque la terminaison du processus. - - ``SIGBUS``. Ce signal correspond à une erreur au niveau matériel. Par défaut, la réception de ce signal provoque la terminaison du processus. - - ``SIGSEGV``. Ce signal correspond à une erreur dans l'accès à la mémoire, typiquement une tentative d'accès en dehors de la zone mémoire allouée au processus. Par défaut, la réception de ce signal provoque la terminaison du processus. - - ``SIGFPE``. Ce signal correspond à une erreur au niveau de l'utilisation des fonctions mathématiques, notamment en virgule flottante mais pas seulement. Par défaut, la réception de ce signal provoque la terminaison du processus. - - ``SIGTERM``. Ce signal est le signal utilisé par défaut par la commande `kill(1)`_ pour demander la fin d'un processus. Par défaut, la réception de ce signal provoque la terminaison du processus. - - ``SIGKILL``. Ce signal permet de forcer la fin d'un processus. Alors qu'un processus peut définir un handler pour le signal ``SIGTERM``, il n'est pas possible d'en définir un pour ``SIGKILL``. Ce signal est le seul qui ne peut être traité et ignoré par un processus. - - ``SIGUSR1`` et ``SIGUSR2`` sont deux signaux qui peuvent être utilisés par des processus sans conditions particulières. Par défaut, la réception d'un tel signal provoque la terminaison du processus. - - ``SIGCHLD``. Ce signal indique qu'un processus fils s'est arrêté ou a fini son exécution. Par défaut ce signal est ignoré. - - ``SIGHUP``. Aux débuts de Unix, ce signal servait à indiquer que la connexion avec le terminal avait été rompue. Aujourd'hui, il est parfois utilisé par des processus serveurs qui rechargent leur fichier de configuration lorsqu'ils reçoivent ce signal. - - ``SIGINT``. Ce signal est envoyé par le shell lorsque l'utilisateur tape `Ctrl-C` pendant l'exécution d'un programme. Il provoque normalement la terminaison du processus. - -Une description détaillée des différents signaux sous Unix et Linux peut se trouver dans `signal(7)`_, [BryantOHallaron2011]_, [StevensRago2008]_ ou encore [Kerrisk2010]_. - -.. note:: Comment arrêter proprement un processus ? - - Trois signaux permettent d'arrêter un processus : ``SIGTERM``, ``SIGINT`` et ``SIGKILL``. Lorsque l'on doit forcer l'arrêt d'un processus, il est préférable d'utiliser le signal ``SIGTERM`` car le processus peut prévoir une routine de traitement de ce signal. Cette routine peut par exemple fermer proprement toutes les ressources (fichiers, ...) utilisées par le processus. Lorsque l'on tape `Ctrl-C` dans le shell, c'est le signal ``SIGINT`` qui est envoyé au processus qui est en train de s'exécuter. Le signal ``SIGKILL`` ne peut pas être traité par le processus. Lorsque l'on envoie ce signal à un processus, on est donc certain que celui-ci s'arrêtera. Malheureusement, cet arrêt sera brutal et le processus n'aura pas eu le temps de libérer proprement toutes les ressources qu'il utilisait. Quand un processus ne répond plus, il est donc préférable de d'abord essayer ``SIGINT`` ou ``SIGTERM`` et de n'utiliser ``SIGKILL`` qu'en dernier recours. - -Envoi de signaux ----------------- - -Un processus peut envoyer un signal à un autre processus en utilisant l'appel système `kill(2)`_. - -.. code-block:: c - - #include <sys/types.h> - #include <signal.h> - - int kill(pid_t pid, int sig); - -Cet appel système prend deux arguments. Le second est toujours le numéro du signal à délivrer ou la constante définissant ce signal dans `signal.h`_. Le premier argument indique à quel(s) processus le signal doit être délivré : - - - ``pid>0``. Dans ce cas, le signal est délivré au processus ayant comme identifiant ``pid``. - - ``pid==0``. Dans ce cas, le signal est délivré à tous les processus qui font partie du même groupe de processus [#fpgrp]_ que le processus qui exécute l'appel système `kill(2)`_. - - ``pid==-1``. Dans ce cas, le signal est délivré à tous les processus pour lesquels le processus qui exécute `kill(2)`_ a les permissions suffisantes pour leur envoyer un signal. - - ``pid<-1``. Dans ce cas, le signal est délivré à tous les processus qui font partie du groupe ``abs(pid)``. - -Par défaut, un processus ne peut envoyer un signal qu'à un processus qui s'exécute avec les mêmes permissions que le processus qui exécute l'appel système `kill(2)`_. - -Traitement de signaux ---------------------- - -Pour des raisons historiques, il existe deux appels systèmes permettant à un processus de spécifier comment un signal particulier doit être traité. Le premier est l'appel système `signal(2)`_. Il prend deux arguments : le numéro du signal dont le traitement doit être modifié et la fonction à exécuter lorsque ce signal est reçu. Le second est `sigaction(2)`_. Cet appel système est nettement plus générique et plus complet que `signal(2)`_ mais il ne sera pas traité en détails dans ces notes. Des informations complémentaires sur l'utilisation de `sigaction(2)`_ peuvent être obtenues dans [Kerrisk2010]_ ou [StevensRago2008]_. - -.. code-block:: c - - #include <signal.h> - typedef void (*sighandler_t)(int); - - sighandler_t signal(int signum, sighandler_t handler); - -.. index:: SIG_DLF, SIG_IGN - -Le premier argument de l'appel système `signal(2)`_ est généralement spécifié en utilisant les constantes définies dans `signal.h`_. Le second argument est un pointeur vers une fonction de type ``void`` qui prend comme argument un entier. Cette fonction est la fonction qui sera exécutée par le système d'exploitation à la réception du signal. Ce second argument peut également être la constante ``SIG_DFL`` si le signal doit être traité avec le traitement par défaut documenté dans `signal(7)`_ et ``SIG_IGN`` si le signal doit être ignoré. La valeur de retour de l'appel système `signal(2)`_ est la façon dont le système d'exploitation gérait le signal passé en argument avant l'exécution de l'appel système (typiquement ``SIG_DFL`` ou ``SIG_IGN``) ou ``SIG_ERR`` en cas d'erreur. - -L'exemple ci-dessous est un programme simple qui compte le nombre de signaux ``SIGUSR1`` et ``SIGUSR2`` qu'il reçoit et se termine dès qu'il a reçu cinq signaux. - -.. literalinclude:: /Fichiers/src/sigusr.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Lors de son exécution, ce programme affiche : - -.. code-block:: console - - $ ./sigusr & - [1] 45602 - $ kill -s SIGUSR1 45602 - $ kill -s SIGUSR2 45602 - $ kill -s SIGUSR2 45602 - $ kill -s SIGUSR1 45602 - $ kill -s SIGUSR1 45602 - $ Fin du processus - Reçu 3 SIGUSR1 et 2 SIGUSR2 - [1]+ Done ./sigusr - -Il est intéressant d'analyser le code source du programme ci-dessus. Commençons d'abord par une lecture rapide pour comprendre la logique du programme sans s'attarder sur les détails. La fonction ``main`` utilise l'appel système `signal(2)`_ pour enregistrer un handler pour les signaux ``SIGUSR1`` et ``SIGUSR2``. La fonction ``sig_handler`` sera exécutée dès réception d'un de ces signaux. Cette fonction prend comme argument le numéro du signal reçu. Cela permet, de traiter plusieurs signaux dans la même fonction. Ensuite, la boucle ``while`` est une boucle active qui ne se terminera que lorsque la somme des variables ``n_sigusr1`` et ``n_sigusr2`` sera égale à 5. Ces deux variables sont modifiées uniquement dans la fonction ``sig_handler``. Elles permettent de compter le nombre de signaux de chaque type qui ont été reçus. - -Une lecture plus attentive du code ci-dessus révèle plusieurs points importants auxquels il faut être attentif lorsque l'on utilise les signaux. - -Tout d'abord, lorsqu'un processus comprend une (ou plusieurs) fonction(s) de traitement de signaux, il y a plusieurs séquences d'instructions qui peuvent être exécutées par le processus. La première est la suite d'instructions du processus lui-même qui démarre à la fonction ``main``. Dès qu'un signal est reçu, cette séquence d'instructions est interrompue pour exécuter la séquence d'instructions de la fonction de traitement du signal. Ce n'est que lorsque cette fonction se termine que la séquence principale peut reprendre son exécution à l'endroit où elle a été interrompue. - -L'existence de deux ou plusieurs séquences d'instructions peut avoir des conséquences importantes sur le bon fonctionnement du programme et peut poser de nombreuses difficultés d'implémentation. En effet, une fonction de traitement de signal doit pouvoir être exécutée à n'importe quel moment. Elle peut donc démarrer à n'importe quel endroit de la séquence d'instructions du processus. Si le processus et une fonction de traitement de signal accèdent à la même variable, il y a un risque que celle-ci soit modifiée par la fonction de traitement du signal pendant qu'elle est utilisée dans le processus. Si l'on n'y prend garde, ces accès venant de différentes séquences d'instructions peuvent poser des problèmes similaires à ceux posés par l'utilisation de threads. Une routine de traitement de signal est cependant moins générale qu'un thread et les techniques utilisables dans les threads ne sont pas applicables aux fonctions de traitement des signaux. En effet, quand la fonction de traitement de signal démarre, il est impossible de bloquer son exécution sur un mutex pour revenir au processus principal. Celle-ci doit s'exécuter jusqu'à sa dernière instruction. - -.. index:: sig_atomic_t - -Lorsque l'on écrit une routine de traitement de signal, plusieurs précautions importantes doivent être prises. Tout d'abord, une fonction de traitement de signal doit manipuler les variables avec précautions. Comme elle est potentiellement exécutée depuis n'importe quel endroit du code, elle ne peut pas s'appuyer sur le stack. Elle ne peut utiliser que des variables globales pour influencer le processus principal. Comme ces variables peuvent être utilisées à la fois dans le processus et la routine de traitement de signal, il est important de les déclarer en utilisant le mot-clé ``volatile``. Cela force le compilateur à recharger la valeur de la variable de la mémoire à chaque fois que celle-ci est utilisée. Mais cela ne suffit pas car il est possible que le processus exécute l'instruction de chargement de la valeur de la variable puis qu'un signal lui soit délivré, ce qui provoquera l'exécution de la fonction de traitement du signal. Lorsque celle-ci se terminera le processus poursuivra son exécution sans recharger la valeur de la variable potentiellement modifiée par la fonction de traitement du signal. Face à ce problème, il est préférable d'utiliser uniquement des variables de types ``sig_atomic_t`` dans les fonctions de traitement de signaux. Ce type permet de stocker un entier. Lorsque ce type est utilisé, le compilateur garantit que tous les accès à la variable se feront de façon atomique sans accès concurrent possible entre le processus et la fonction de traitement des signaux. - -L'utilisation de ``sig_atomic_t`` n'est pas la seule précaution à prendre lorsque l'on écrit une fonction de traitement des signaux. Il faut également faire attention aux fonctions de la librairie et aux appels systèmes que l'on utilise. Sachant qu'un signal peut être reçu à n'importe quel moment, il est possible qu'un processus reçoive un signal et exécute une fonction de traitement du signal pendant l'exécution de la fonction ``fct`` de la librairie standard. Si la fonction de traitement du signal utilise également la fonction ``fct``, il y a un risque d'interférence entre l'exécution de ces deux fonctions. Ce sera le cas notamment si la fonction utilise un buffer statique ou modifie la variable ``errno``. Dans ces cas, la fonction de traitement du signal risque de modifier une valeur ou une zone mémoire qui a déjà été modifiée par le processus principal et cela donnera un résultat incohérent. Pour éviter ces problèmes, il ne faut utiliser que des fonctions "réentrantes" à l'intérieur des fonctions de traitement des signaux. Des fonctions comme `printf(3)`_, `scanf(3)`_ ne sont pas réentrantes et ne doivent pas être utilisées dans une section de traitement des signaux. La (courte) liste des fonctions qui peuvent être utilisées sans risque est disponible dans la section `2.4 de l'Open Group Base Specification <http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html>`_ - -Ces restrictions sur les instructions qui peuvent être utilisées dans une fonction de traitement des signaux ne sont pas les seules qui affectent l'utilisation des signaux. Ceux-ci souffrent d'autres limitations. - -Pour bien les comprendre, il est utile d'analyser comment ceux-ci sont supportés par le noyau. Il y a deux stratégies possibles pour implémenter les signaux sous Unix. La première stratégie est de considérer qu'un signal est un message qui est envoyé depuis le noyau ou un processus à un autre processus. Pour traiter ces messages, le noyau contient une queue qui stocke tous les signaux destinés à un processus donné. Avec cette stratégie d'implémentation, l'appel système `kill(2)`_ génère un message et le place dans la queue associée au processus destination. Le noyau stocke pour chaque processus un tableau de pointeurs vers les fonctions de traitement de chacun des signaux. Ce tableau est modifié par l'appel système `signal(2)`_. Chaque fois que le noyau réactive un processus, il vérifie si la queue associée à ce processus contient un ou plusieurs messages concernant des signaux. Si un message est présent, le noyau appelle la fonction de traitement du signal correspondant. Lorsque la fonction se termine, l'exécution du processus reprend à l'instruction qui avait été interrompue. - -La seconde stratégie est de représenter l'ensemble des signaux qu'un processus peut recevoir sous la forme de drapeaux binaires. En pratique, il y a un drapeau par signal. Avec cette stratégie d'implémentation, l'appel système `kill(2)`_ modifie le drapeau correspondant du processus destination du signal (sauf si ce signal est ignoré par le processus, dans ce cas le drapeau n'est pas modifié). L'appel système `signal(2)`_ modifie également le tableau contenant les fonctions de traitement des signaux associé au processus. Chaque fois que le noyau réactive un processus, que ce soit après un changement de contexte ou après l'exécution d'un appel système, il vérifie les drapeaux relatifs aux signaux du processus. Si un des drapeaux est vrai, le noyau appelle la fonction de traitement associée à ce signal. - -La plupart des variantes de Unix, y compris Linux, utilisent la seconde stratégie d'implémentation pour les signaux. L'avantage principal de l'utilisation de drapeaux pour représenter les signaux reçus par un processus est qu'il suffit d'un bit par signal qui peut être reçu par le processus. La première stratégie nécessite de maintenir une queue par processus et la taille de cette queue varie en fonction du nombre de signaux reçus. Par contre, l'utilisation de drapeaux a un inconvénient majeur : il n'y a pas de garantie sur la délivrance des signaux. Lorsqu'un processus reçoit un signal, cela signifie qu'il y a au moins un signal de ce type qui a été envoyé au processus, mais il est très possible que plus d'un signal ont été envoyés au processus. - -Pour illustrer ce problème, considérons le programme ci-dessous qui compte simplement le nombre de signaux ``SIGUSR1`` reçus. - -.. literalinclude:: /Fichiers/src/sigusrcount.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Depuis un shell, il est possible d'envoyer plusieurs fois le signal ``SIGUSR1`` rapidement avec le script :download:`/Fichiers/src/nkill.sh`. Ce script prend deux arguments : le nombre de signaux à envoyer et le processus destination. - -.. literalinclude:: /Fichiers/src/nkill.sh - :encoding: utf-8 - :language: console - - -La sortie ci-dessous présente une exécution de ce script avec le processus :download:`/Fichiers/src/sigusrcount.c` en tâche de fond. - -.. code-block:: console - - $ ./sigusrcount & - [1] 47845 - $ Exécution de sleep(60) - $./nkill.sh 10 47845 - Exécution de sleep(52) - $ ./nkill.sh 10 47845 - Exécution de sleep(46) - $ ./nkill.sh 10 47845 - Exécution de sleep(31) - $ Fin du processus - Reçu 3 SIGUSR1 - - -Il y a plusieurs points intéressants à noter concernant l'exécution de ce programme. Tout d'abord, même si 30 signaux ``SIGUSR1`` ont été générés, seuls 3 de ces signaux ont effectivement étés reçus. Les signaux ne sont manifestement pas fiables sous Unix et cela peut s'expliquer de deux façons. Premièrement, les signaux sont implémentés sous la forme de bitmaps. La réception d'un signal modifie simplement la valeur d'un bit dans le bitmap du processus. En outre, durant l'exécution de la fonction qui traite le signal ``SIGUSR1``, ce signal est bloqué par le système d'exploitation pour éviter qu'un nouveau signal n'arrive pendant que le premier est traité. - -Un deuxième point important à relever est l'utilisation de `sleep(3)`_. Par défaut, cette fonction de la librairie permet d'attendre un nombre de secondes passé en argument. Si `sleep(3)`_ a mis le processus en attente pendant au moins le temps demandé, elle retourne ``0`` comme valeur de retour. Mais `sleep(3)`_ est un des exemples de fonctions ou appels systèmes qui sont dits `lents`. Un :term:`appel système lent` est un appel système dont l'exécution peut être interrompue par la réception d'un signal. C'est notamment le cas pour l'appel système `read(2)`_ [#flent]_. Lorsqu'un signal survient pendant l'exécution d'un tel appel système, celui-ci est interrompu pour permettre l'exécution de la fonction de traitement du signal. Après l'exécution de cette fonction, l'appel système se termine [#frestart]_ en retournant une erreur et met ``errno`` à ``EINTR`` de façon à indiquer que l'appel système a été interrompu. Le processus doit bien entendu traiter ces interruptions d'appels systèmes si il utilise des signaux. - -Nous terminons cette section en analysant deux cas pratiques d'utilisation des signaux. Le premier est relatif aux signaux synchrones et nous développons une fonction de traitement du signal ``SIGFPE`` pour éviter qu'un programme ne s'arrête suite à une division par zéro. Ensuite, nous utilisons `alarm(3posix)`_ pour implémenter un temporisateur simple. - -Traitement de signaux synchrones ---------------------------------- - -Le programme ci-dessous prend en arguments en ligne de commande une séquence d'entiers et divise la valeur ``1252`` par chaque entier passé en argument. Il enregistre la fonction ``sigfpe_handler`` comme fonction de traitement du signal ``SIGFPE``. - - -.. literalinclude:: /Fichiers/src/sigfpe2.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Lors de son exécution, ce programme affiche la sortie ci-dessous : - - -.. code-block:: console - - $ ./sigfpe2 1 2 aa 0 9 - Traitement de argv[1]=1 - 1252/1=1252 - Traitement de argv[2]=2 - 1252/2=626 - Traitement de argv[3]=aa - Argument incorrect : aa - Traitement de argv[4]=0 - Signal SIGFPE reçu - Signal SIGFPE reçu - ... - -La fonction ``sigfpe_handler`` traite bien le signal ``SIGPFE`` reçu, mais après son exécution, elle tente de recommencer l'exécution de la ligne ``int resultat=n/(int) val;``, ce qui provoque à nouveau un signal ``SIGPFE``. Pour éviter ce problème, il faut permettre à la fonction de traitement du signal de modifier la séquence d'exécution de la fonction ``main`` après la réception du signal. Une solution pourrait être d'utiliser l'instruction ``goto`` comme suit : - - -.. code-block:: c - - if(*endptr=='\0') { - int resultat=n/(int) val; - printf("%d/%d=%d\n",n,(int) val,resultat); - goto fin: - erreur: - printf("%d/%d=NaN\n",n,(int) val); - fin: - } - else { - printf("Argument incorrect : %s\n",argv[i]); - } - // ... - - static void sigfpe_handler(int signum) { - goto erreur: - } - -En C, ce genre de construction n'est pas possible car l'étiquette d'un ``goto`` doit nécessairement se trouver dans la même fonction que l'invocation de ``goto``. La seule possibilité pour faire ce genre de saut entre fonctions en C, est d'utiliser les fonctions `setjmp(3)`_ et `longjmp(3)`_. Dans un programme normal, ces fonctions sont à éviter encore plus que les ``goto`` car elles rendent le code très difficile à lire. - -.. todo:: ajouter des exemples avec des variables qui changent de valeur pour montrer l'environnement - -.. code-block:: c - - #include <setjmp.h> - - int setjmp(jmp_buf env); - - void longjmp(jmp_buf env, int val); - - -La fonction `setjmp(3)`_ est équivalente à la déclaration d'une étiquette. Elle prend comme argument un ``jmp_buf``. Cette structure de données, définie dans `setjmp.h`_ permet de sauvegarder l'environnement d'exécution, c'est-à -dire les valeurs des registres y compris ``%eip`` et ``%esp`` au moment où elle est exécutée. Lorsque `setjmp(3)`_ est exécutée dans le flot normal des instructions du programme, elle retourne la valeur ``0``. La fonction `longjmp(3)`_ prend deux arguments. Le premier est une structure de type ``jmp_buf`` et le second un entier. Le ``jmp_buf`` est l'environnement d'exécution qu'il faut restaurer lors de l'exécution de `longjmp(3)`_ et le second argument la valeur de retour que doit avoir la fonction `setjmp(3)`_ correspondante après l'exécution de `longjmp(3)`_. - -Le programme ci-dessous illustre l'utilisation de `setjmp(3)`_ et `longjmp(3)`_. - -.. literalinclude:: /Fichiers/src/longjmp.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Le programme débute en exécutant la fonction ``f``. Dans cette exécution, la fonction `setjmp(3)`_ retourne la valeur ``0``. Ensuite, la fonction ``main`` appelle la fonction ``g`` qui elle exécute ``longjmp(label,1)``. Cela provoque un retour à la fonction ``f`` à l'endroit de l'exécution de ``setjmp(label)`` qui cette fois-ci va retourner la valeur ``1``. Lors de son exécution, le programme ci-dessus affiche : - -.. literalinclude:: /Fichiers/src/longjmp.out - :encoding: utf-8 - :language: console - -Avec les fonctions `setjmp(3)`_ et `longjmp(3)`_, il est presque possible d'implémenter le traitement attendu pour le signal ``SIGFPE``. Il reste un problème à résoudre. Lorsque la routine de traitement du signal ``SIGFPE`` s'exécute, ce signal est bloqué par le système d'exploitation jusqu'à ce que cette fonction se termine. Si elle effectue un `longjmp(3)`_, elle ne se terminera jamais et le signal continuera à être bloqué. Pour éviter ce problème, il faut utiliser les fonctions `sigsetjmp(3)`_ et `siglongjmp(3)`_. Ces fonctions sauvegardent dans une structure de données ``sigjmp_buf`` non seulement l'environnement d'exécution mais aussi la liste des signaux qui sont actuellement bloqués. La fonction `sigsetjmp(3)`_ prend un argument supplémentaire : un entier qui doit être non nul si l'on veut effectivement sauvegarder la liste des signaux bloqués. Lorsque `siglongjmp(3)`_ s'exécute, l'environnement et la liste des signaux bloqués sont restaurés. - -Le programme ci-dessous présente l'utilisation de `sigsetjmp(3)`_ et `siglongjmp(3)`_. - -.. literalinclude:: /Fichiers/src/sigfpe3.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Lors de son exécution, il affiche la sortie standard suivante. - -.. code-block:: console - - ./sigfpe3 1 2 3 0 a 0 3 - Traitement de argv[1]=1 - 1252/1=1252 - Traitement de argv[2]=2 - 1252/2=626 - Traitement de argv[3]=3 - 1252/3=417 - Traitement de argv[4]=0 - 1252/0=NaN - Traitement de argv[5]=a - Argument incorrect : a - Traitement de argv[6]=0 - 1252/0=NaN - Traitement de argv[7]=3 - 1252/3=417 - - -Temporisateurs --------------- - -.. index:: SIGALRM, siginterrupt - -Parfois il est nécessaire dans un programme de limiter le temps d'attente pour réaliser une opération. Un exemple simple est lorsqu'un programme attend l'entrée d'un paramètre via l'entrée standard mais peut remplacer ce paramètre par une valeur par défaut si celui-ci n'est pas entré endéans quelques secondes. Lorsqu'un programme attend une information via l'entrée standard, il exécute l'appel système `read(2)`_ directement ou via des fonctions de la librairie comme `fgets(3)`_ ou `getchar(3)`_. Par défaut, celui-ci est bloquant, cela signifie qu'il ne se terminera que lorsqu'une donnée aura été lue. Si `read(2)`_ est utilisé seul, il n'est pas possible de borner le temps d'attente du programme et d'interrompre l'appel à `read(2)`_ après quelques secondes. Pour obtenir ce résultat, une possibilité est d'utiliser un signal. En effet, `read(2)`_ est un appel système lent qui peut être interrompu par la réception d'un signal. Il y a plusieurs façons de demander qu'un signal soit généré après un certain temps. Le plus général est `setitimer(2)`_. Cet appel système permet de générer un signal ``SIGALRM`` après un certain temps ou périodiquement. L'appel système `alarm(3posix)`_ est plus ancien mais plus simple à utiliser que `setitimer(2)`_. Nous l'utilisons afin d'illustrer comment un signal peut permettre de limiter la durée d'attente d'un appel système. - -.. literalinclude:: /Fichiers/src/alarm.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Ce programme utilise `alarm(3posix)`_ pour limiter la durée d'un appel système `read(2)`_. Pour ce faire, il enregistre d'abord une fonction pour traiter le signal ``SIGALRM``. Cette fonction est vide dans l'exemple, son exécution permet juste d'interrompre l'appel système `read(2)`_. Par défaut, lorsqu'un signal survient durant l'exécution d'un appel système, celui-ci est automatiquement redémarré par le système d'exploitation pour éviter à l'application de devoir traiter tous les cas possibles d'interruption d'appels système. La fonction `siginterrupt(3)`_ permet de modifier ce comportement par défaut et nous l'utilisons pour forcer l'interruption d'appels systèmes lorsque le signal ``SIGALRM`` est reçu. L'appel à ``alarm(0)`` permet de désactiver l'alarme qui était en cours. - -Lors de son exécution, ce programme affiche la sortie suivante. - - -.. literalinclude:: /Fichiers/src/alarm.out - :encoding: utf-8 - :language: console - -En essayant le programme ci-dessus, on pourrait conclure qu'il fonctionne parfaitement. Il a cependant un petit défaut qui peut s'avérer genant si par exemple on utilise la même logique pour écrire une fonction ``read_time`` qui se comporte comme `read(2)`_ sauf que son dernier argument est un délai maximal. Sur un système fort chargé, il est possible qu'après l'exécution de ``alarm(5)`` le processus soit mis en attente par le système d'exploitation qui exécute d'autres processus. Lorsque l'alarme expire, la fonction de traitement de ``SIGALRM`` est exécutée puis seulement l'appel à `read(2)`_ s'effectue. Celui-ci étant bloquant, le processus restera bloqué jusqu'à ce que les données arrivent ce qui n'est pas le comportement attendu. - -Pour éviter ce problème, il faut empêcher l'exécution de `read(2)`_ si le signal ``SIGALRM`` a déjà été reçu. Cela peut se réaliser en utilisant `sigsetjmp(3)`_ pour définir une étiquette avant l'exécution du bloc contenant l'appel à `alarm(3posix)`_ et l'appel à `read(2)`_. Si le signal n'est pas reçu, l'appel à `read(2)`_ s'effectue normalement. Si par contre le signal ``SIGALRM`` est reçu entre l'appel à `alarm(3posix)`_ et l'appel à `read(2)`_, alors l'exécution de `siglongjmp(3)`_ dans ``sig_handler`` empêchera l'exécution de l'appel système `read(2)`_ ce qui est bien le comportement attendu. - -.. literalinclude:: /Fichiers/src/alarm2.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -L'appel système `alarm(3posix)`_ s'appuie sur `setitimer(2)`_, mais les deux types d'alarmes ne doivent pas être combinés. Il en va de même pour `sleep(3)`_ qui peut être implémenté en utilisant ``SIGALRM``. Linux contient d'autres appels systèmes et fonctions pour gérer différents types de temporisateurs. Ceux-ci sont décrits de façon détaillée dans [Kerrisk2010]_. - -.. note:: Signaux, threads, `fork(2)`_ et `execve(2)`_ - - Le noyau du système d'exploitation maintient pour chaque processus une structure de données contenant la liste des signaux qui sont ignorés, ont été reçus et les pointeurs vers les fonctions de traitement pour chaque signal. Cette structure de données est associée à chaque processus. La création de threads ne modifie pas cette structure de données et lorsqu'un signal est délivré à un processus utilisant des threads, c'est généralement le thread principal qui recevra et devra traiter le signal. Lors de l'exécution de `fork(2)`_, la structure de données relative aux signaux du processus père est copiée dans le processus fils. Après `fork(2)`_, les deux processus peuvent évoluer séparément et le fils peut par exemple modifier la façon dont il traite un signal sans que cela n'affecte le processus père. Lors de l'exécution de `execve(2)`_, la structure de données relative aux signaux est réinitialisée avec les traitements par défaut pour chacun des signaux. - - - .. _semname: - -Sémaphores nommés -================= - -Nous avons présenté les sémaphores lors de l'étude du fonctionnement des threads et les mécanismes qui permettent de les coordonner. Chaque sémaphore utilise une structure de données qui est dans une mémoire accessible aux différents threads/processus qui doivent se coordonner. Lorsque des sémaphores sont utilisés pour coordonner des threads, cette structure de données est soit stockée dans la zone réservée aux variables globales, soit sur le tas. Lorsque des processus doivent se coordonner, il ne partagent pas nécessairement [#fshmem]_ de la mémoire. Dans ce cas, la fonction `sem_init(3)`_ ne peut pas être utilisée pour créer de sémaphore. Par contre, il est possible d'utiliser des sémaphores "nommés" (named semaphores). Ces sémaphores utilisent une zone de mémoire qui est gérée par le noyau et qui peut être utilisée par plusieurs processus. Un :term:`sémaphore nommé` est identifié par un `nom`. Sous Linux, ce nom correspond à un fichier sur un système de fichiers et tout processus qui connait le nom d'un sémaphore et possède les permissions l'autorisant à y accéder peut l'utiliser. Trois appels systèmes sont utilisés pour créer, utiliser et supprimer un sémaphore nommé. Une présentation générale des sémaphores est disponible dans la page de manuel `sem_overview(7)`_. - -.. code-block:: c - - #include <fcntl.h> /* For O_* constants */ - #include <sys/stat.h> /* For mode constants */ - #include <semaphore.h> - - sem_t *sem_open(const char *name, int oflag); - sem_t *sem_open(const char *name, int oflag, - mode_t mode, unsigned int value); - int sem_close(sem_t *sem); - int sem_unlink(const char *name); - -.. index:: sem_open, sem_close, sem_unlink - -`sem_open(3)`_ permet d'ouvrir ou de créer un :term:`sémaphore nommé`. Tout comme l'appel système `open(2)`_, il existe deux variantes de `sem_open(3)`_. La première prend 2 arguments et permet d'utiliser un :term:`sémaphore nommé` déjà existant. La seconde prend quatre arguments et permet de créer un nouveau :term:`sémaphore nommé` et l'initialise à la valeur du quatrième argument. La fonction `sem_open(3)`_ s'utilise de la même façon que l'appel système `open(2)`_ sauf qu'elle retourne un pointeur vers une structure de type ``sem_t`` et qu'en cas d'erreur elle retourne ``SEM_FAILED`` et utilise ``errno`` pour fournir une information sur le type d'erreur. La fonction `sem_close(3)`_ permet à un processus d'arrêter d'utiliser un :term:`sémaphore nommé`. Enfin, la fonction `sem_unlink(3)`_ permet de supprimer un sémaphore qui avait été créé avec `sem_open(3)`_. Tout comme il est possible d'utiliser l'appel système `unlink(2)`_ sur un fichier ouvert par un processus, il est possible d'appeler `sem_unlink(3)`_ avec comme argument un nom de sémaphore utilisé actuellement par un processus. Dans ce cas, le sémaphore sera complètement libéré lorsque le dernier processus qui l'utilise aura effectué `sem_close(3)`_. Les fonctions `sem_post(3)`_ et `sem_wait(3)`_ s'utilisent de la même façon qu'avec les sémaphores non-nommés que nous avons utilisé précédemment. - -A titre d'exemple, considérons un exemple simple d'utilisation de sémaphores nommés dans lequel un processus doit attendre la fin de l'exécution d'une fonction dans un autre processus pour pouvoir s'exécuter. Avec les threads, nous avions résolu ce problème en initialisant un sémaphore à ``0`` dans le premier thread alors que le second démarrait par un `sem_wait(3)`_. Le première exécute `sem_post(3)`_ dès qu'il a fini l'exécution de sa fonction critique. - -Le programme ci-dessous illustre le processus qui s'exécute en premier. - -.. literalinclude:: /Fichiers/src/process-sem-before.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -Ce processus commence par utiliser `sem_open(3)`_ pour créer un sémaphore qui porte le nom ``lsinf1252`` et est initialisé à zéro puis se met en veille pendant vingt secondes. Ensuite il exécute la fonction ``before`` qui se termine par l'exécution de ``sem_post(semaphore)``. Cet appel a pour résultat de libérer le second processus dont le code est présenté ci-dessous : - -.. literalinclude:: /Fichiers/src/process-sem-after.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Ce processus utilise le sémaphore qui a été créé par un autre processus pour se coordonner. La fonction ``after`` démarre par l'exécution de `sem_wait(3)`_ qui permet d'attendre que l'autre processus ait terminé l'exécution de la fonction ``before``. Les sémaphores nommés peuvent être créés et supprimés comme des fichiers. Il est donc normal que le sémaphore soit créé par le premier processus et supprimé par le second. Sous Linux, les sémaphores nommés sont créés comme des fichiers dans le système de fichiers virtuel ``/dev/shm`` : - -.. code-block:: console - - $ ls -l /dev/shm/ - -rw------- 1 obo stafinfo 32 Apr 10 15:37 sem.lsinf1252 - -Les permissions du fichier virtuel représentent les permissions associées au sémaphore. La sortie ci-dessous présente une exécution des deux processus présentés plus haut. - -.. code-block:: console - - $ ./process-sem-before & - [1] 5222 - $ ./process-sem-after - before done, pid=5222 - after done, pid=5223 - [1]+ Done ./process-sem-before - -Il est important de noter que les sémaphores nommés sont une ressource généralement limitée. Lorsqu'il a été créé, un sémaphore nommé utilise des ressources du système jusqu'à ce qu'il soit explicitement supprimé avec `sem_unlink(3)`_. Il est très important de toujours bien effacer les sémaphores nommés dès qu'ils ne sont plus nécessaires. Sans cela, l'espace réservé pour ces sémaphores risque d'être rempli et d'empêcher la création de nouveaux sémaphores par d'autres processus. - -.. _fileshare: - -Partage de fichiers -=================== - -Les fichiers sont l'un des principaux moyens de communication entre processus. L'avantage majeur des fichiers est leur persistence. Les données sauvegardées dans un fichier persistent sur le système de fichiers après la fin du processus qui les a écrites. L'inconvénient majeur de l'utilisation de fichiers par rapport à d'autres techniques de communication entre processus est la relative lenteur des dispositifs de stockage en comparaison avec les accès à la mémoire. Face à cette lenteur des dispositifs de stockage, la majorité des systèmes d'exploitation utilisent des buffers qui servent de tampons entre les processus et les dispositifs de stockage. Lorsqu'un processus écrit une donnée sur un dispositif de stockage, celle-ci est d'abord écrite dans un buffer géré par le système d'exploitation et le processus peut poursuivre son exécution sans devoir attendre l'exécution complète de l'écriture sur le dispositif de stockage. La taille de ces buffers varie généralement dynamiquement en fonction de la charge du système. Les données peuvent y rester entre quelques fractions de seconde et quelques dizaines de secondes. Un processus peut contrôler l'utilisation de ce buffer en utilisant l'appel système `fsync(2)`_. Celui-ci permet de forcer l'écriture sur le dispositif de stockage des données du fichier identifié par le descripteur de fichiers passé en argument. L'appel système `sync(2)`_ force quant à lui l'écriture de toutes les données actuellement stockées dans les buffers du noyau sur les dispositifs de stockage. Cet appel système est notamment utilisé par un processus système qui l'exécute toutes les trente secondes afin d'éviter que des données ne restent trop longtemps dans les buffers du noyau. - -.. index:: open file object - -L'utilisation d'un même fichier par plusieurs processus est une des plus anciennes techniques de communication entre processus. Pour comprendre son fonctionnement, il est utile d'analyser les structures de données qui sont maintenues par le noyau du système d'exploitation pour chaque fichier et chaque processus. Comme nous l'avons présenté dans le chapitre précédent, le système de fichiers utilise des inodes pour stocker les méta-données et la liste des blocs de chaque fichier. Lorsqu'un processus ouvre un fichier, le noyau du système d'exploitation lui associe le premier descripteur de fichier libre dans la table des descripteurs de fichiers du processus. Ce descripteur de fichier pointe alors vers une structure maintenue par le noyau qui est souvent appelée un :term:`open file object`. Un :term:`open file object` contient toutes les informations qui sont nécessaires au noyau pour pouvoir effectuer les opérations de manipulation d'un fichier ouvert par un processus. Parmi celles-ci, on trouve notamment : - - - le mode dans lequel le fichier a été ouvert (lecture seule, écriture, lecture/écriture). Ce mode est initialisé à l'ouverture du fichier. Le noyau vérifie le mode lors de l'exécution des appels systèmes `read(2)`_ et `write(2)`_ mais pas les permissions du fichier sur le système de fichiers. - - l'offset pointer qui est la tête de lecture/écriture dans le fichier - - une référence vers le fichier sur le système de fichiers. Dans un système de fichiers Unix, il s'agit généralement du numéro de l':term:`inode` du fichier ou d'un pointeur vers une structure contenant cet :term:`inode` et des informations comme le dispositif de stockage sur lequel il est stocké. - - -A titre d'exemple, considérons l'exécution de la commande suivante depuis le shell : - -.. code-block:: console - - $ cat < /tmp/t > /tmp/out - -Lors de son exécution, deux open file objects sont créés dans le noyau. Le premier est relatif au fichier ``/tmp/t`` qui est associé au descripteur ``stdin``. Le second est lié au fichier ``/tmp/out`` et est associé au descripteur ``stdout``. Ces open-file objects sont représentés graphiquement dans la figure ci-dessous. - -.. figure:: /Fichiers/fig/figures-10-001-c.png - :align: center - :scale: 60 - - -Les open file objects sont également utilisés lorsque plusieurs processus ouvrent le même fichier. Considérons l'exécution simultanée des deux commandes suivantes : - -.. code-block:: console - - $ prog1 file & - $ prog2 file & - -Lors de l'exécution de ces deux processus, le noyau va attribuer un descripteur de fichier à chacun d'eux. Si ``file`` est le premier fichier ouvert par chaque processus, il sera associé au descripteur ``3``. Le noyau créera un open-file object pour le fichier ``file`` utilisé par le processus ``prog1`` et un autre open-file object pour le fichier ``file`` utilisé par le processus ``prog2``. Ces deux open-file objects référencient le même inode et donc le même fichier, mais ils peuvent avoir des modes et des offset pointers qui sont totalement indépendants. Tous les accès faits par le processus ``prog2`` sont complètement indépendants des accès faits par le processus ``prog1``. Cette utilisation d'un même fichier par deux processus distincts est représentée graphiquement dans la figure ci-dessous. - -.. figure:: /Fichiers/fig/figures-10-002-c.png - :align: center - :scale: 60 - - -Sous Unix et Linux, il est important d'analyser également ce qu'il se passe lors de la création d'un processus en utilisant l'appel système `fork(2)`_. Imaginons que le processus ``prog1`` discuté ci-dessous effectue `fork(2)`_ après avoir ouvert le fichier ``file``. Dans ce cas, le noyau du système d'exploitation va dupliquer la table des descripteurs de fichiers du processus père pour créer celle du processus fils. Le processus père et le processus fils ont donc chacun une table des descripteurs de fichiers qui leur est propre. Cela permet, comme nous l'avons vu lorsque nous avons présenté les pipes, que le fils ferme un de ses descripteurs de fichiers sans que cela n'ait d'impact sur l'utilisation de ce descripteur de fichier par le processus père. Par contre, l'exécution de l'appel système `fork(2)`_ ne copie pas les open-file objects. Après exécution de `fork(2)`_ le descripteur de fichiers ``3`` dans le processus père pointe vers l'open-file object associé au fichier ``file`` et le même descripteur dans le processus fils pointe vers le même open-file object. Cette situation est représentée schématiquement dans la figure ci-dessous. - - -.. figure:: /Fichiers/fig/figures-10-003-c.png - :align: center - :scale: 80 - - -Cette utilisation d'un même open-file object par le processus père et le processus fils est une particularité importante de Unix. Elle permet aux deux processus d'écrire des données séquentiellement dans un fichier qui avait été initialement ouvert par le processus père, mais pose régulièrement des problèmes lors de la manipulation de fichiers. - -Lorsqu'un fichier est utilisé par plusieurs processus simultanément, il est nécessaire de coordonner les activités de ces processus pour éviter que le fichier ne devienne corrompu. Outre les appels systèmes classiques `open(2)`_, `read(2)`_, `write(2)`_ et `close(2)`_, Unix offre plusieurs appels systèmes qui sont utiles lorsque plusieurs processus accèdent au même fichier. - -Considérons d'abord un processus père et un processus fils qui doivent lire des données à des endroits particuliers dans un fichier. Pour cela, il est naturel d'utiliser l'appel système `lseek(2)`_ pour déplacer l'offset pointer et d'ensuite réaliser la lecture avec `read(2)`_. Malheureusement lorsqu'un père et un ou plusieurs fils [#fthreads]_ utilisent ces appels systèmes, il est possible qu'un appel à `lseek(2)`_ fait par le fils soit immédiatement suivi d'un appel à `lseek(2)`_ fait par le père avant que le fils ne puisse exécuter l'appel système `read(2)`_. Dans ce cas, le processus fils ne lira pas les données qu'il souhaitait lire dans le fichier. Les appels systèmes `pread(2)`_ et `pwrite(2)`_ permettent d'éviter ce problème. Ils complètent les appels systèmes `read(2)`_ et `write(2)`_ en prenant comme argument l'offset auquel la lecture ou l'écriture demandée doit être effectuée. `pread(2)`_ et `pwrite(2)`_ garantissent que les opérations d'écriture et de lecture qui sont effectuées avec ces appels systèmes seront atomiques. - - .. code-block:: c - - #include <unistd.h> - ssize_t pread(int fd, void *buf, size_t count, off_t offset); - - ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset); - -Ce n'est pas le seul problème qui se pose lorsque plusieurs processus manipulent un même fichier. Considérons un logiciel de base de données qui comprend des processus qui lisent dans des fichiers qui constituent la base de données et d'autres qui modifient le contenu de ces fichiers. Ces opérations d'écritures et de lectures dans des fichiers partagés risquent de provoquer des problèmes d'accès concurrent similaires aux problèmes que nous avons dû traiter lorsque plusieurs threads se partagent une même mémoire. Pour réguler ces accès à des fichiers, Unix et Linux supportent des verrous (locks en anglais) que l'on peut associer à des fichiers. A première vue, un :term:`lock` peut être comparé à un :term:`mutex`. Un :term:`lock` permet à un processus d'obtenir l'accès exclusif à un fichier ou une partie de fichier tout comme un :term:`mutex` est utilisé pour réguler les accès à une variable. En théorie, il existe deux techniques d'utilisation de locks qui peuvent être utilisées sur un système Unix : - - - :term:`mandatory locking`. Dans ce cas, les processus placent des locks sur certains fichiers ou zones de fichiers et le système d'exploitation vérifie qu'aucun accès fait aux fichiers avec les appels systèmes standards ne viole ces locks. - - :term:`advisory locking`. Dans ce cas, les processus doivent vérifier eux-mêmes que les accès qu'ils effectuent ne violent pas les locks qui ont été associés aux différents fichiers. - -Certains systèmes Unix supportent les deux stratégies de locking, mais la plupart ne supportent que l':term:`advisory locking`. L':term:`advisory locking` est la stratégie la plus facile à implémenter dans le système d'exploitation. C'est aussi celle qui donne les meilleures performances. Nous limitons notre description à l':term:`advisory locking`. Le :term:`mandatory locking` nécessite un support spécifique du système de fichiers qui sort du cadre de ce cours. - -Deux appels systèmes sont utilisés pour manipuler les locks qui peuvent être associés aux fichiers : `flock(2)`_ et `fcntl(2)`_. `flock(2)`_ est la solution la plus simple. Cet appel système permet d'associer un verrou à un fichier complet. - -.. code-block:: c - - #include <sys/file.h> - int flock(int fd, int operation); - - -Il prend comme argument un descripteur de fichier et une opération. Deux types de locks sont supportés. Un lock est dit partagé (shared lock, ``operation==LOCK_SH``) lorsque plusieurs processus peuvent posséder un même lock vers un fichier. Un lock est dit exclusif (exclusive lock, ``operation==LOCK_EX``) lorsqu'un seul processus peut posséder un lock vers un fichier à un moment donné. Il faut noter que les locks sont associés aux fichiers (et donc indirectement aux inodes) et non aux descripteurs de fichiers. Pour retirer un lock associé à un fichier, il faut utiliser ``LOCK_UN`` comme second argument à l'appel `flock(2)`_. - - - -L'appel système `fcntl(2)`_ et la fonction `lockf(3)`_ sont nettement plus flexibles. Ils permettent de placer des locks sur une partie d'un fichier. `lockf(3)`_ prend trois arguments : un descripteur de fichiers, une commande et un entier qui indique la longueur de la section du fichier à associer au lock. - -.. code-block:: c - - #include <unistd.h> - int lockf(int fd, int cmd, off_t len); - - -`lockf(3)`_ supporte plusieurs commandes qui sont chacune spécifiées par une constante définie dans `unistd.h`_. La commande ``F_LOCK`` permet de placer un lock exclusif sur une section du fichier dont le descripteur est le premier argument. Le troisième argument est la longueur de la section sur laquelle le lock doit être appliqué. Par convention, la section s'étend de la position actuelle de l'offset pointer (``pos``) jusqu'à ``pos+len-1`` si ``len`` est positif et va de ``pos-len`` à ``pos-1`` si ``len`` est négatif. Si ``len`` est nul, alors la section concernée par le lock va de ``pos`` à l'infini (c'est-à -dire jusqu'à la fin du fichier, même si celle-ci change après l'application du lock). - -L'appel à `lockf(3)`_ bloque si un autre processus a déjà un lock sur une partie du fichier qui comprend celle pour laquelle le lock est demandé. La commande ``F_TLOCK`` est équivalente à ``F_LOCK`` avec comme différence qu'elle ne bloque pas si un lock existe déjà sur le fichier mais retourne une erreur. ``F_TEST`` permet de tester la présence d'un lock sans tenter d'acquérir ce lock contrairement à ``F_TLOCK``. Enfin, la commande ``F_ULOCK`` permet de retirer un lock placé précédemment. - -En pratique, `lockf(3)`_ doit s'utiliser de la même façon qu'un mutex. C'est-à -dire qu'un processus qui souhaite écrire de façon exclusive dans un fichier doit d'abord obtenir via `lockf(3)`_ un lock sur la partie du fichier dans laquelle il souhaite écrire. Lorsque l'appel à `lockf(3)`_ réussit, il peut effectuer l'écriture via `write(2)`_ et ensuite libérer le lock en utilisant `lockf(3)`_. Tout comme avec les mutex, si un processus n'utilise pas `lockf(3)`_ avant d'écrire ou de lire, cela causera des problèmes. - -L'appel système `fcntl(2)`_ est un appel "fourre-tout" qui regroupe de nombreuses opérations qu'un processus peut vouloir faire sur un fichier. L'application de locks est une de ces opérations, mais la page de manuel en détaille de nombreuses autres. Lorsqu'il est utilisé pour manipuler des locks, l'appel système `fcntl(2)`_ utilise trois arguments : - -.. code-block:: c - - #include <unistd.h> - #include <fcntl.h> - - int fcntl(int fd, int cmd, struct flock* ); - -Le premier argument est le descripteur de fichiers sur lequel le lock doit être appliqué. Le second est la commande. Tout comme `lockf(3)`_, `fcntl(2)`_ supporte différentes commandes qui sont spécifiées dans la page de manuel. Le troisième argument est un pointeur vers une structure ``flock`` qui doit contenir au minimum les champs suivants : - -.. code-block:: c - - struct flock { - ... - short l_type; /* Type of lock: F_RDLCK, - F_WRLCK, F_UNLCK */ - short l_whence; /* How to interpret l_start: - SEEK_SET, SEEK_CUR, SEEK_END */ - off_t l_start; /* Starting offset for lock */ - off_t l_len; /* Number of bytes to lock */ - pid_t l_pid; /* PID of process blocking our lock - (F_GETLK only) */ - ... - }; - -Cette structure permet de spécifier plus finement qu'avec la fonction `lockf(3)`_ la section du fichier sur laquelle le lock doit être placé. L'utilisation de locks force le noyau à maintenir des structures de données supplémentaires pour stocker ces locks et les processus qui peuvent être en attente sur chacun de ces locks. Conceptuellement, cette structure de données est associée à chaque fichier comme représenté dans la figure ci-dessous. - -.. figure:: /Fichiers/fig/figures-10-004-c.png - :align: center - :scale: 80 - - Gestion des locks par le kernel - -Comme les locks sont associés à des fichiers, le noyau doit maintenir pour chaque fichier ouvert une liste de locks. Celle-ci peut être implémentée sous la forme d'une liste chaînée comme représenté ci-dessus ou sous la forme d'une autre structure de données. Le point important est que le noyau doit mémoriser pour chaque fichier utilisant des locks quelles sont les sections du fichier qui sont concernées par chaque lock, quel est le type de lock, quel est le processus qui possède le lock (pour autoriser uniquement ce processus à le retirer) et enfin une liste ou une queue des processus qui sont en attente sur ce lock. - -Sous Linux, le système de fichiers virtuel ``/proc`` fournit une interface permettant de visualiser l'état des locks. Il suffit pour cela de lire le contenu du fichier ``/proc/locks``. - -.. code-block:: console - - cat /proc/locks - 1: POSIX ADVISORY WRITE 12367 00:17:20628657 0 0 - 2: POSIX ADVISORY WRITE 12367 00:17:7996086 0 0 - 3: POSIX ADVISORY WRITE 12367 00:17:24084665 0 0 - 4: POSIX ADVISORY WRITE 12367 00:17:12634137 0 0 - 5: POSIX ADVISORY WRITE 30677 00:17:14534587 1073741824 1073742335 - 6: POSIX ADVISORY READ 30677 00:17:25756362 128 128 - 7: POSIX ADVISORY READ 30677 00:17:25756359 1073741826 1073742335 - 8: POSIX ADVISORY READ 30677 00:17:25756319 128 128 - 9: POSIX ADVISORY READ 30677 00:17:25756372 1073741826 1073742335 - 10: POSIX ADVISORY WRITE 30677 00:17:25757269 1073741824 1073742335 - 11: POSIX ADVISORY WRITE 30677 00:17:25756354 0 EOF - 12: FLOCK ADVISORY WRITE 22677 00:18:49578023 0 EOF - 13: POSIX ADVISORY WRITE 3023 08:01:652873 0 EOF - 14: POSIX ADVISORY WRITE 3014 08:01:652855 0 EOF - 15: POSIX ADVISORY WRITE 2994 08:01:652854 0 EOF - 16: FLOCK ADVISORY WRITE 2967 08:01:798437 0 EOF - 17: FLOCK ADVISORY WRITE 2967 08:01:797391 0 EOF - 18: FLOCK ADVISORY WRITE 1278 08:01:652815 0 EOF - -Dans ce fichier, la première colonne indique le type de lock (``POSIX`` pour un lock placé avec `fcntl(2)`_ ou `lockf(3)`_ et ``FLOCK`` pour un lock placé avec `flock(2)`_). La deuxième indique si le lock est un :term:`advisory lock` ou un :term:`mandatory lock`. La troisième spécifie si le lock protège l'écriture et/ou la lecture. La quatrième colonne est l'identifiant du processus qui possède le lock. La cinquième précise le dispositif de stockage et le fichier concerné par ce lock (le dernier nombre est l'inode du fichier). Enfin, les deux dernières colonnes spécifient la section qui est couverte par le lock avec ``EOF`` qui indique la fin du fichier. - -.. rubric:: Footnotes - -.. [#fpgrp] Chaque processus appartient à groupe de processus. Ce groupe de processus peut être récupéré via l'appel système `getpgrp(2)`_. Par défaut, lorsqu'un processus est créé, il appartient au même groupe de processus que son processus père, mais il est possible de changer de groupe de - processus en utilisant l'appel système `setpgid(2)`_. En pratique, les groupes de processus sont surtout utilisés par le shell. Lorsqu'un utilisateur exécute une commande combinée telle que ``cat /tmp/t | ./a.out``, il souhaite pouvoir l'arrêter en tapant sur `Ctrl-C` si nécessaire. Pour cela, il faut pouvoir délivrer le signal ``SIGINT`` aux processus ``cat`` et ``a.out``. - -.. [#flent] Les autres appels systèmes lents sont `open(2)`_, `write(2)`_, `sendto(2)`_, `recvfrom(2)`_, `sendmsg(2)`_, `recvmsg(2)`_, `wait(2)`_ `ioctl(2)`_. - -.. [#frestart] L'appel système `sigaction(2)`_ permet notamment de spécifier pour chaque signal si un appel système interrompu par ce signal doit être automatiquement redémarré lorsque le signal survient ou non. - -.. [#fshmem] Nous verrons dans le prochain chapitre comment plusieurs processus peuvent partager une même zone mémoire. - -.. [#fthreads] Même si il n'a pas été mentionné lors de l'utilisation de threads, ce problème se pose également lorsque plusieurs threads accèdent directement aux données dans un même fichier. - - diff --git a/Theorie/Fichiers/fichiers.rst b/Theorie/Fichiers/fichiers.rst deleted file mode 100644 index 1544bec2c7a201f31465a1836aae94d3fc680f2e..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/fichiers.rst +++ /dev/null @@ -1,445 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012, 2019 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. _utilisateurs: - - -Gestion des utilisateurs -======================== - -.. spelling:: - - multi - -Unix est un système d'exploitation multi-utilisateurs. Un tel système impose des contraintes de sécurité qui n'existent pas sur un système mono-utilisateur. Il est intéressant de passer en revue quelques unes de ces contraintes : - - - il doit être possible d'identifier et/ou d'authentifier les utilisateurs du système - - il doit être possible d'exécuter des processus appartenant à plusieurs utilisateurs simultanément et de déterminer quel utilisateur est responsable de chaque opération - - le système d'exploitation doit fournir des mécanismes simples qui permettent de contrôler l'accès aux différentes ressources (mémoire, stockage, ...). - - il doit être possible d'allouer certaines ressources à un utilisateur particulier à un moment donné - - -Aujourd'hui, la plupart des systèmes informatiques demandent une authentification de l'utilisateur sous la forme d'un mot de passe, d'une manipulation particulière voire d'une identification biométrique comme une empreinte digitale. Cette authentification permet de vérifier que l'utilisateur est autorisé à manipuler le système informatique. Cela n'a pas toujours été le cas et de nombreux systèmes informatiques plus anciens étaient conçus pour être utilisés par un seul utilisateur qui était simplement celui qui interagissait physiquement avec l'ordinateur. - -Les systèmes Unix supportent différents mécanismes d'authentification. Le plus simple et le plus utilisé est l'authentification par mot de passe. Chaque utilisateur est identifié par un nom d'utilisateur et il doit prouver son identité en tapant son mot de passe au démarrage de toute session sur le système. En pratique, une session peut s'établir localement sur l'ordinateur via son interface graphique par exemple ou à distance en faisant tourner un serveur tel que `sshd(8)`_ sur le système Unix et en permettant aux utilisateurs de s'y connecter via Internet en utilisant un client `ssh(1)`_. Dans les deux cas, le système d'exploitation lance un processus `login(1)`_ qui permet de vérifier le nom d'utilisateur et le mot de passe fourni par l'utilisateur. Si le mot de passe correspond à celui qui est stocké sur le système, l'utilisateur est authentifié et son shell peut démarrer. Sinon, l'accès au système est refusé. - - -.. spelling:: - - username - inode - inodes - -Lorsqu'un utilisateur se connecte sur un système Unix, il fournit son nom d'utilisateur ou `username`. Ce nom d'utilisateur est une chaîne de caractères qui est facile à mémoriser par l'utilisateur. D'un point de vue implémentation, un système d'exploitation préfère manipuler des nombres plutôt que des chaînes de caractères. Unix associe à chaque utilisateur un identifiant qui est stocké sous la forme d'un nombre entier positif. La table de correspondance entre l'identifiant d'utilisateur et le nom d'utilisateur est le fichier `/etc/passwd`. Ce fichier texte, comme la grande majorité des fichiers de configuration d'un système Unix, comprend pour chaque utilisateur l'information suivante : - - - nom d'utilisateur (`username`) - - mot de passe (sur les anciennes versions de Unix) - - identifiant de l'utilisateur (:term:`userid`) - - identifiant du groupe principal auquel l'utilisateur appartient - - nom et prénom de l'utilisateur - - répertoire de démarrage de l'utilisateur - - shell de l'utilisateur - -L'extrait ci-dessous présente un exemple de fichier ``/etc/passwd``. Des détails complémentaires sont disponibles dans la page de manuel `passwd(5)`_. Un utilisateur peut modifier les informations le concernant dans ce fichier avec la commande `passwd(1)`_. - -.. code-block:: console - - # Exemple de /etc/passwd - nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false - root:*:0:0:System Administrator:/var/root:/bin/sh - daemon:*:1:1:System Services:/var/root:/usr/bin/false - slampion:*:1252:1252:Séraphin Lampion:/home/slampion:/bin/bash - -Il y a en pratique trois types d'utilisateurs sur un système Unix. L'utilisateur :term:`root` est l'administrateur du système. C'est l'utilisateur qui a le droit de réaliser toutes les opérations sur le système. Il peut créer de nouveaux utilisateurs, mais aussi formatter les disques, arrêter le système, interrompre des processus utilisateurs ou accéder à l'ensemble des fichiers sans restriction. Par convention, cet utilisateur a l'identifiant ``0``. Ensuite, il y a tous les utilisateurs `normaux` du système Unix. Ceux-ci ont le droit d'accéder à leurs fichiers, d'interagir avec leurs processus mais en général ne peuvent pas manipuler les fichiers d'autres utilisateurs ou interrompre leurs processus. L'utilisateur `slampion` dans l'exemple ci-dessus est un utilisateur `normal`. Enfin, pour faciliter l'administration du système, certains systèmes Unix utilisent des utilisateurs qui correspondent à un service particulier comme l'utilisateur `daemon` dans l'exemple ci-dessus. Une discussion de ce type d'utilisateur sort du cadre de ces notes. Le lecteur intéressé pourra consulter une référence sur l'administration des système Unix telle que [AdelsteinLubanovic2007]_ ou [Nemeth+2010]_. - -Unix associe à chaque processus un identifiant d'utilisateur. Cet identifiant est stocké dans l'entrée du processus dans la table des processus. Un processus peut récupérer son identifiant d'utilisateur via l'appel système `getuid(2)`_. Outre cet appel système, il existe également l'appel système `setuid(2)`_ qui permet de modifier le :term:`userid` du processus en cours d'exécution. Pour des raisons évidentes de sécurité, seul un processus appartenant à l'administrateur système (:term:`root`) peut exécuter cet appel système. C'est le cas par exemple du processus `login(1)`_ qui appartient initialement à :term:`root` puis exécute `setuid(2)`_ afin d'appartenir à l'utilisateur authentifié puis exécute `execve(2)`_ pour lancer le premier shell appartenant à l'utilisateur. - -En pratique, il est parfois utile d'associer des droits d'accès à des groupes d'utilisateurs plutôt qu'à un utilisateur particulier. Par exemple, un département universitaire peut avoir un groupe correspondant à tous les étudiants et un autre aux membres du staff pour leur donner des permissions différentes. Un utilisateur peut appartenir à un groupe principal et plusieurs groupes secondaires. Le groupe principal est spécifié dans le fichier `passwd(5)`_ tandis que le fichier ``/etc/group`` décrit dans `group(5)`_ contient les groupes secondaires. - - -.. _fichiers: - -Systèmes de fichiers -==================== - -Outre un processeur et une mémoire, la plupart des ordinateurs actuels sont en général équipés d'un ou plusieurs dispositifs de stockage. Les dispositifs les plus courants sont le disque dur, le lecteur de CD/DVD, la clé USB, la carte mémoire, ... Ces dispositifs de stockage ont des caractéristiques techniques très différentes. Certains stockent l'information sous forme magnétique, d'autres sous forme électrique ou en creusant via un laser des trous dans un support physique. D'un point de vue logique, ils offrent tous une interface très similaire au système d'exploitation qui veut les utiliser. - -Dans un système de fichiers Unix, l'ensemble des répertoires et fichiers est organisé sous la forme d'un arbre. La racine de cet arbre est le répertoire ``/``. Il est localisé sur un des dispositifs de stockage du système. Le système de fichiers Unix permet d'intégrer facilement des systèmes de fichiers qui se trouvent sur différents dispositifs de stockage. Cette opération est en général réalisée par l'administrateur système en utilisant la commande `mount(8)`_. A titre d'exemple, voici quelques répertoires qui sont montés sur un système Linux. - -.. code-block:: console - - $ df -k - Filesystem 1K-blocks Used Available Use% Mounted on - /dev/sda1 15116836 9425020 4923912 66% / - tmpfs 1559516 4724 1554792 1% /dev/shm - /dev/sda2 19840924 4374616 14442168 24% /xendomains - xenstore 1972388 40 1972348 1% /var/lib/xenstored - david:/mnt/student 258547072 188106176 59935296 76% /etinfo/users - david:/mnt/staff 254696800 177422400 64136160 74% /etinfo/users2 - -Dans l'exemple ci-dessus, la première colonne correspond au dispositif de stockage qui contient les fichiers et répertoires. Le premier dispositif de stockage ``/dev/sda1/`` est un disque local et contient le répertoire racine du système de fichiers. Le système de fichiers ``david://mnt/student`` est stocké sur le serveur ``david`` et est monté via `mount(8)`_ dans le répertoire ``/etinfo/users``. Ainsi, tout accès à un fichier dans le répertoire ``/etinfo/users`` se fera via le serveur ``david``. - -Chaque répertoire du système de fichiers contient un ou plusieurs répertoires et un ou plusieurs fichiers. A titre d'exemple, il est intéressant de regarder le contenu de deux répertoires. Le premier est un extrait au contenu du répertoire racine obtenu avec la commande `ls(1)`_ - -.. code-block:: console - - $ ls -la / - dr-xr-xr-x. 26 root root 233472 Feb 23 03:18 . - dr-xr-xr-x. 26 root root 233472 Feb 23 03:18 .. - -rw-r--r-- 1 root root 0 Feb 13 16:45 .autofsck - -rw-r--r-- 1 root root 0 Jul 27 2011 .autorelabel - dr-xr-xr-x. 4 root root 4096 Dec 15 05:50 boot - drwxr-xr-x 19 root root 4160 Mar 22 12:04 dev - drwxr-xr-x. 125 root root 12288 Mar 22 12:04 etc - drwxr-xr-x 4 root root 0 Mar 22 10:22 etinfo - drwxr-xr-x. 2 root root 4096 Jan 6 2011 home - dr-xr-xr-x. 14 root root 4096 Mar 22 03:26 lib - dr-xr-xr-x. 10 root root 12288 Mar 22 03:26 lib64 - drwx------. 2 root root 16384 Jul 27 2011 lost+found - ... - drwxrwxrwt. 104 root root 4096 Mar 22 12:05 tmp - drwxr-xr-x. 13 root root 4096 Jul 19 2011 usr - drwxr-xr-x. 23 root root 4096 Jul 27 2011 var - -Le répertoire racine contient quelques fichiers et des répertoires. Tout répertoire contient deux répertoires spéciaux. Le premier répertoire, identifié par le caractère ``.`` (un seul point) est un alias vers le répertoire lui-même. Cette entrée de répertoire est présente dans chaque répertoire dès qu'il est créé avec une commande telle que `mkdir(1)`_. Le deuxième répertoire spécial est ``..`` (deux points consécutifs). Ce répertoire est un alias vers le répertoire parent du répertoire courant. - -Les méta-données qui sont associées à chaque fichier ou répertoire contiennent, outre les informations de type, les bits de permission. Ceux-ci permettent d'encoder trois types de permissions et d'autorisation : - - - ``r`` : autorisation de lecture - - ``w`` : autorisation d'écriture ou de modification - - ``x`` : autorisation d'exécution - -Ces bits de permissions sont regroupés en trois blocs. Le premier bloc correspond aux bits de permission qui sont applicables pour les accès qui sont effectués par un processus qui appartient à l'utilisateur qui est propriétaire du fichier/répertoire. Le deuxième bloc correspond aux bits de permission qui sont applicables pour les opérations effectuées par un processus dont l'identifiant de groupe est identique à l'identifiant de groupe du fichier/répertoire mais n'appartient pas à l'utilisateur qui est propriétaire du fichier/répertoire. Le dernier bloc est applicable pour les opérations effectuées par des processus qui appartiennent à d'autres utilisateurs. - -Les valeurs de ces bits sont représentés pas les symboles ``rwx`` dans l'output de la commande `ls(1)`_. Les bits de permission peuvent être modifiés en utilisant la commande `chmod(1)`_ qui utilise l'appel système `chmod(2)`_. Pour qu'un exécutable puisse être exécuté via l'appel système `execve(2)`_, il est nécessaire que le fichier correspondant possède les bits de permission ``r`` et ``x``. - - -.. note:: Manipulation des bits de permission avec `chmod(2)`_ - - L'appel système `chmod(2)`_ permet de modifier les bits de permission qui sont associés à un fichier. Ceux-ci sont encodés sous la forme d'un entier sur 16 bits. - - - ``S_IRUSR (00400)`` : permission de lecture par le propriétaire - - ``S_IWUSR (00200)`` : permission d'écriture par le propriétaire - - ``S_IXUSR (00100)`` : permission d'exécution par le propriétaire - - ``S_IRGRP (00040)`` : permission de lecture par le groupe hormis le propriétaire - - ``S_IWGRP (00020)`` : permission d'écriture par le groupe hormis le propriétaire - - ``S_IXGRP (00010)`` : permission d'exécution par le groupe hormis le propriétaire - - ``S_IROTH (00004)`` : permission de lecture par tout utilisateur hormis le propriétaire et son groupe - - ``S_IWOTH (00002)`` : permission d'écriture par tout utilisateur hormis le propriétaire et son groupe - - ``S_IXOTH (00001)`` : permission d'exécution par tout utilisateur hormis le propriétaire et son groupe - - .. code-block:: c - - #include <sys/stat.h> - int chmod(const char *path, mode_t mode); - - Ces bits de permissions sont généralement spécifiés soit sous la forme d'une disjonction logique ou sous forme numérique. A titre d'exemple, un fichier qui peut être lu et écrit uniquement par son propriétaire aura comme permissions ``00600`` ou ``S_IRUSR|S_IWUSR``. - - Le :term:`nibble` de poids fort des bits de permission sert à encoder des permissions particulières relatives aux fichiers et répertoires. Par exemple, lorsque la permission ``S_ISUID (04000)`` est associée à un exécutable, elle indique que celui-ci doit s'exécuter avec les permissions du propriétaire de l'exécutable et pas les permissions de l'utilisateur. Cette permission spéciale est utilisée par des programmes comme `passwd(1)`_ qui doivent disposer des permissions de l'administrateur système pour s'exécuter correctement (`passwd(1)`_ doit modifier le fichier `passwd(5)`_ qui appartient à l'administrateur système). - - -Les exemples ci-dessous présentent le contenu partiel d'un répertoire. - -.. code-block:: console - - $ ls -lai /etinfo/users/obo - total 1584396 - drwx------ 78 obo stafinfo 4096 Mar 17 00:34 . - drwxr-xr-x 93 root root 4096 Feb 22 11:37 .. - -rwxr-xr-x 1 obo stafinfo 11490 Feb 28 00:43 a.out - -rw------- 1 obo stafinfo 4055 Mar 22 15:13 .bash_history - -rw-r--r-- 1 obo stafinfo 55 Sep 18 1995 .bash_profile - -rw-r--r-- 1 obo stafinfo 101 Aug 28 2003 .bashrc - drwxr-xr-x 2 obo stafinfo 4096 Nov 22 2004 bin - -rw-r--r-- 1 obo stafinfo 346 Feb 13 15:37 hello.c - drwxr-xr-x 3 obo stafinfo 4096 Mar 2 09:30 sinf1252 - drwxr-xr-x 2 obo stafinfo 4096 May 17 2011 src - -Dans un système Unix, que ce soit au niveau du shell ou dans n'importe quel processus écrit par exemple en langage C, les fichiers peuvent être spécifiés de deux façons. La première est d'indiquer le chemin complet depuis la racine qui permet d'accéder au fichier. Le chemin ``/etinfo/users/obo`` passé comme argument à la commande `ls(1)`_ ci-dessus en est un exemple. Le premier caractère ``/`` correspond à la racine du système de fichiers et ensuite ce caractère est utilisé comme séparateur entre les répertoires successifs. Ainsi, le fichier ``/etinfo/users/obo/hello.c`` est un fichier qui a comme nom ``hello.c`` qui se trouve dans un répertoire nommé ``obo`` qui lui-même se trouve dans le répertoire ``users`` qui est dans le répertoire baptisé ``etinfo`` dans le répertoire racine. La seconde façon de spécifier un nom de fichier est de préciser son nom relatif. Pour éviter de forcer l'utilisateur à spécifier chaque fois le nom complet des fichiers et répertoires auxquels il veut accéder, le noyau maintient dans sa table des processus le :term:`répertoire courant` de chaque processus. Par défaut, lorsqu'un processus est lancé, son répertoire courant est le répertoire à partir duquel le programme a été lancé. Ainsi, lorsque l'utilisateur tape une commande comme ``gcc hello.c`` depuis son shell, le processus `gcc(1)`_ peut directement accéder au fichier ``hello.c`` qui se situe dans le répertoire courant. Un processus peut modifier son répertoire courant en utilisant l'appel système `chdir(2)`_. - - -.. code-block:: c - - #include <unistd.h> - - int chdir(const char *path); - -Cet appel système prend comme argument une chaîne de caractères contenant le nom du nouveau répertoire courant. Ce nom peut être soit un nom complet (commençant par ``/``), ou un nom relatif au répertoire courant actuel. Dans ce cas, il est parfois utile de pouvoir référer au répertoire parent du répertoire courant. Cela se fait en utilisant ``..``. Dans chaque répertoire, cet alias correspond au répertoire parent. Ainsi, si le répertoire courant est ``/etinfo/users``, alors le répertoire ``../../bin`` est le répertoire ``bin`` se trouvant dans le répertoire racine. Depuis le shell, il est possible de modifier le répertoire courant avec la commande `cd(1posix)`_. La commande `pwd(1)`_ affiche le répertoire courant actuel. - - -Il existe plusieurs appels systèmes et fonctions de la librairie standard qui permettent de parcourir le système de fichiers. Les principaux sont : - - - l'appel système `stat(2)`_ permet de récupérer les méta-données qui sont associées à un fichier ou un répertoire. La commande `stat(1)`_ fournit des fonctionnalités similaires depuis le shell. - - les appels systèmes `chmod(2)`_ et `chown(2)`_ permettent de modifier respectivement le mode (i.e. les permissions), le propriétaire et le groupe associés à un fichier. Les commandes `chmod(1)`_, `chown(1)`_ et `chgrp(1)`_ permettent de faire de même depuis le shell. - - l'appel système `utime(2)`_ permet de modifier les dates de création/modification associées à un fichier/répertoire. Cet appel système est utilisé par la commande `touch(1)`_ - - l'appel système `rename(2)`_ permet de changer le nom d'un fichier ou d'un répertoire. Il est utilisé notamment par la commande `rename(1)`_ - - l'appel système `mkdir(2)`_ permet de créer un répertoire alors que l'appel système `rmdir(2)`_ permet d'en supprimer un - - les fonctions de la librairie `opendir(3)`_, `closedir(3)`_, et `readdir(3)`_ permettent de consulter le contenu de répertoires. - -Les fonctions de manipulation des répertoires méritent que l'on s'y attarde un peu. Un répertoire est un fichier qui a une structure spéciale. Ces trois fonctions permettent d'en extraire de l'information en respectant le format d'un répertoire. Pour accéder à un répertoire, il faut d'abord l'ouvrir en utilisant `opendir(3)`_. La fonction `readdir(3)`_ permet d'accéder aux différentes entrées de ce répertoire et `closedir(3)`_ doit être utilisée lorsque l'accès n'est plus nécessaire. La fonction `readdir(3)`_ permet de manipuler la structure ``dirent`` qui est définie dans `bits/dirent.h`_. - -.. code-block:: c - - struct dirent { - ino_t d_ino; /* inode number */ - off_t d_off; /* offset to the next dirent */ - unsigned short d_reclen; /* length of this record */ - unsigned char d_type; /* type of file; not supported - by all file system types */ - char d_name[256]; /* filename */ - }; - - -.. spelling:: - - l'inode - métadonnée - -Cette structure comprend le numéro de l'inode, c'est-à -dire la métadonnée qui contient les informations relatives au fichier/répertoire, la position de l'entrée ``dirent`` qui suite, la longueur de l'entrée, son type et le nom de l'entrée dans le répertoire. Chaque appel à `readdir(3)`_ retourne un pointeur vers une structure de ce type. - - -L'extrait de code ci-dessous permet de lister tous les fichiers présents dans le répertoire ``name``. - -.. literalinclude:: /Fichiers/src/readdir.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -La lecture d'un répertoire avec `readdir(3)`_ commence au début de ce répertoire. A chaque appel à `readdir(3)`_, le programme appelant récupère un pointeur vers une zone mémoire contenant une structure ``dirent`` avec l'entrée suivante du répertoire ou ``NULL`` lorsque la fin du répertoire est atteinte. Si une fonction doit relire à nouveau un répertoire, cela peut se faire en utilisant `seekdir(3)`_ ou `rewinddir(3)`_. - - -.. note:: `readdir(3)`_ et les threads - - La fonction `readdir(3)`_ est un exemple de fonction non-réentrante qu'il faut éviter d'utiliser dans une application dont plusieurs threads doivent pouvoir parcourir le même répertoire. Ce problème est causé par l'utilisation d'une zone de mémoire ``static`` afin de stocker la structure dont le pointeur est retourné par `readdir(3)`_. Dans une application utilisant plusieurs threads, il faut utiliser la fonction `readdir_r(3)`_ : - - .. code-block:: c - - int readdir_r(DIR *restrict dirp, struct dirent *restrict entry, - struct dirent **restrict result); - - - Cette fonction prend comme arguments le pointeur ``entry`` vers un buffer propre à l'appelant qui permet de stocker le résultat de `readdir_r(3)`_. - - -Les appels systèmes `link(2)`_ et `unlink(2)`_ sont un peu particuliers et méritent une description plus détaillée. Sous Unix, un :term:`inode` est associé à chaque fichier mais l':term:`inode` ne contient pas le nom de fichier parmi les méta-données qu'il stocke. Par contre, chaque :term:`inode` contient un compteur (``nlinks``) du nombre de liens vers un fichier. Cela permet d'avoir une seule copie d'un fichier qui est accessible depuis plusieurs répertoires. Pour comprendre cette utilisation des liens sur un système de fichiers Unix, considérons le scénario suivant. - -.. code-block:: console - - $ mkdir a - $ mkdir b - $ cd a - $ echo "test" > test.txt - $ cd .. - $ ln a/test.txt a/test2.txt - $ ls -li a - total 16 - 9624126 -rw-r--r-- 2 obo stafinfo 5 24 mar 21:14 test.txt - 9624126 -rw-r--r-- 2 obo stafinfo 5 24 mar 21:14 test2.txt - $ ln a/test.txt b/test3.txt - $ stat --format "inode=%i nlinks=%h" b/test3.txt - inode=9624126 nlinks=3 - $ ls -li b - total 8 - 9624126 -rw-r--r-- 3 obo stafinfo 5 24 mar 21:14 test3.txt - $ echo "complement" >> b/test3.txt - $ ls -li a - total 16 - 9624126 -rw-r--r-- 3 obo stafinfo 16 24 mar 21:15 test.txt - 9624126 -rw-r--r-- 3 obo stafinfo 16 24 mar 21:15 test2.txt - $ ls -li b - total 8 - 9624126 -rw-r--r-- 3 obo stafinfo 16 24 mar 21:15 test3.txt - $ cat b/test3.txt - test - complement - $ cat a/test.txt - test - complement - $ rm a/test2.txt - $ ls -li a - total 8 - 9624126 -rw-r--r-- 2 obo stafinfo 16 24 mar 21:15 test.txt - $ rm a/test.txt - $ ls -li a - $ ls -li b - total 8 - 9624126 -rw-r--r-- 1 obo stafinfo 16 24 mar 21:15 test3.txt - -Dans ce scénario, deux répertoires sont créés avec la commande `mkdir(1)`_. Ensuite, la commande `echo(1)`_ est utilisée pour créer le fichier ``test.txt`` contenant la chaîne de caractères ``test`` dans le répertoire ``a``. Ce fichier est associé à l':term:`inode` ``9624126``. La commande `ln(1)`_ permet de rendre ce fichier accessible sous un autre nom depuis le même répertoire. La sortie produite par la commande `ls(1)`_ indique que ces deux fichiers qui sont présents dans le répertoire ``a`` ont tous les deux le même ``inode``. Ils correspondent donc aux mêmes données sur le disque. A ce moment, le compteur ``nlinks`` de l':term:`inode` ``9624126`` a la valeur ``2``. La commande `ln(1)`_ peut être utilisée pour créer un lien vers un fichier qui se trouve dans un autre répertoire [#flns]_ comme le montre la création du fichier ``test3.txt`` dans le répertoire ``b``. Ces trois fichiers correspondant au même :term:`inode`, toute modification à l'un des fichiers affecte et est visible dans n'importe lequel des liens vers ce fichier. C'est ce que l'on voit lorsque la commande ``echo "complement" >> b/test3.txt`` est exécutée. Cette commande affecte immédiatement les trois fichiers. La commande ``rm a/test2.txt`` efface la référence du fichier sous le nom ``a/test2.txt``, mais les deux autres liens restent accessibles. Le fichier ne sera réellement effacé qu'après que le dernier lien vers l':term:`inode` correspondant aie été supprimé. La commande `rm(1)`_ utilise en pratique l'appel système `unlink(2)`_ qui en toute généralité décrémente le compteur de liens de l'inode correspondant au fichier et l'efface lorsque ce compteur atteint la valeur ``0``. - -Une description détaillée du fonctionnement de ces appels systèmes et fonctions de la librairie standard peut se trouver dans les livres de référence sur la programmation en C sous Unix [Kerrisk2010]_, [Mitchell+2001]_, [StevensRago2008]_. - - -Utilisation des fichiers ------------------------- - -Si quelques processus manipulent le système de fichiers et parcourent les répertoires, les processus qui utilisent des données sauvegardées dans des fichiers sont encore plus nombreux. Un système Unix offre deux possibilités d'écrire et de lire dans un fichier. La première utilise directement les appels systèmes `open(2)`_, `read(2)`_/ `write(2)`_ et `close(2)`_. La seconde s'appuie sur les fonctions `fopen(3)`_, `fread(3)`_/ `fwrite(3)`_ et `fclose(3)`_ de la librairie `stdio(3)`_. Seuls les appels systèmes sont traités dans ce cours. Des détails complémentaires sur les fonctions de la libraire peuvent être obtenus dans [Kerrisk2010]_, [Mitchell+2001]_ ou [StevensRago2008]_. - -Du point de vue des appels systèmes de manipulation des fichiers, un fichier est une séquence d'octets. Avant qu'un processus ne puisse écrire ou lire dans un fichier, il doit d'abord demander au système d'exploitation l'autorisation d'accéder au fichier. Cela se fait en utilisant l'appel système `open(2)`_. - -.. code-block:: c - - #include <sys/types.h> - #include <sys/stat.h> - #include <fcntl.h> - - int open(const char *pathname, int flags); - int open(const char* pathname, int flags, mode_t mode); - -Il existe deux variantes de l'appel système `open(2)`_. La première permet d'ouvrir des fichiers existants. Elle prend deux arguments. La deuxième permet de créer un nouveau fichier et l'ouvre ensuite. Elle prend trois arguments. Le premier argument est le nom absolu ou relatif du fichier dont l'ouverture est demandée. Le deuxième argument est un entier qui contient un ensemble de drapeaux binaires qui précisent la façon dont le fichier doit être ouvert. Ces drapeaux sont divisés en deux groupes. Le premier groupe est relatif à l'accès en lecture et/ou en écriture du fichier. Lors de l'ouverture d'un fichier avec `open(2)`_, il est nécessaire de spécifier l'un des trois drapeaux d'accès suivants : - - - ``O_RDONLY`` : indique que le fichier est ouvert uniquement en lecture. Aucune opération d'écriture ne sera effectuée sur le fichier. - - ``O_WRONLY`` : indique que le fichier est ouvert uniquement en écriture. Aucune opération de lecture ne sera effectuée sur le fichier. - - ``O_RDWR`` : indique que le fichier est ouvert pour des opérations de lecture et d'écriture. - -En plus de l'un des trois drapeaux ci-dessus, il est également possible de spécifier un ou plusieurs drapeaux optionnels. Ces drapeaux sont décrits en détails dans la page de manuel `open(2)`_. Les plus utiles sont probablement : - - - ``O_CREAT`` : indique que si le fichier n'existe pas, il doit être créé lors de l'exécution de l'appel système `open(2)`_. L'appel système `creat(2)`_ peut également être utilisé pour créer un nouveau fichier. Lorsque le drapeau ``O_CREAT`` est spécifié, l'appel système `open(2)`_ prend comme troisième argument les permissions du fichier qui doit être créé. Celles-ci sont spécifiées de la même façon que pour l'appel système `chmod(2)`_. Si elles ne sont pas spécifiées, le fichier est ouvert avec comme permissions les permissions par défaut du processus définies par l'appel système `umask(2)`_ - - ``O_APPEND`` : indique que le fichier est ouvert de façon à ce que les données écrites dans le fichier par l'appel système `write(2)`_ s'ajoutent à la fin du fichier. - - ``O_TRUNC`` : indique que si le fichier existe déjà et qu'il est ouvert en écriture, alors le contenu du fichier doit être supprimé avant que le processus ne commence à y accéder. - - ``O_CLOEXEC`` : ce drapeau qui est spécifique à Linux indique que le fichier doit être automatiquement fermé lors de l'exécution de l'appel système `execve(2)`_. Normalement, les fichiers qui ont été ouverts par `open(2)`_ restent ouverts lors de l'exécution de `execve(2)`_. - - ``O_SYNC`` : ce drapeau indique que toutes les opérations d'écriture sur le fichier doivent être effectuées immédiatement sur le dispositif de stockage sans être mises en attente dans les buffers du noyau du système d'exploitation - -Ces différents drapeaux binaires doivent être combinés en utilisant une disjonction logique entre les différents drapeaux. Ainsi, ``O_CREAT|O_RDWR`` correspond à l'ouverture d'un fichier qui doit à la fois être créé si il n'existe pas et ouvert en lecture et écriture. - -Lors de l'exécution de `open(2)`_, le noyau du système d'exploitation vérifie si le processus qui exécute l'appel système dispose des permissions suffisantes pour accéder au fichier. Si oui, le système d'exploitation ouvre le fichier et retourne au processus appelant le :term:`descripteur de fichier` correspondant. Si non, le processus récupère une valeur de retour négative et ``errno`` indique le type d'erreur. - -Sous Unix, un :term:`descripteur de fichier` est représenté sous la forme d'un entier positif. L'appel système `open(2)`_ retourne toujours le plus petit :term:`descripteur de fichier` disponible. Par convention, - - - ``0`` est le :term:`descripteur de fichier` correspondant à l'entrée standard. - - ``1`` est le :term:`descripteur de fichier` correspondant à la sortie standard. - - ``2`` est le :term:`descripteur de fichier` correspondant à la sortie d'erreur standard. - -Si l'appel système `open(2)`_ échoue, il retourne ``-1`` comme :term:`descripteur de fichier` et ``errno`` donne plus de précisions sur le type d'erreur. Il peut s'agir d'une erreur liée aux droits d'accès au fichier (``EACESS``), une erreur de drapeau (``EINVAL``) ou d'une erreur d'entrée sortie lors de l'accès au dispositif de stockage (``EIO``). Le noyau du système d'exploitation maintient une table de l'ensemble des fichiers qui sont ouverts par tous les processus actifs. Si cette table est remplie, il n'est plus possible d'ouvrir de nouveau fichier et `open(2)`_ retourne une erreur. Il en va de même si le processus tente d'ouvrir plus de fichiers que le nombre maximum de fichiers ouverts qui est autorisé. - -.. note:: Seul `open(2)`_ vérifie les permissions d'accès aux fichiers - - Sous Unix, seul l'appel système `open(2)`_ vérifie qu'un processus dispose des permissions suffisantes pour accéder à un fichier qui est ouvert. Si les permissions ou le propriétaire d'un fichier change alors que ce fichier est ouvert par un processus, ce processus continue à pouvoir y accéder sans être affecté par la modification de droits. Il en va de même lorsqu'un fichier est effacé avec l'appel système `unlink(2)`_. Si un processus utilisait le fichier qui est effacé, il continue à pouvoir l'utiliser même si le fichier n'apparaît plus dans le répertoire. - -Toutes les opérations qui sont faites sur un fichier se font en utilisant le :term:`descripteur de fichier` comme référence au fichier. Un :term:`descripteur de fichier` est une ressource limitée dans un système d'exploitation tel que Unix et il est important qu'un processus n'ouvre pas inutilement un grand nombre de fichiers [#flimit]_ et ferme correctement les fichiers ouverts lorsqu'il ne doit plus y accéder. Cela se fait en utilisant l'appel système `close(2)`_. Celui-ci prend comme argument le :term:`descripteur de fichier` qui doit être fermé. - -.. code-block:: c - - #include <unistd.h> - - int close(int fd); - -Tout processus doit correctement fermer tous les fichiers qu'il a utilisé. Par défaut, le système d'exploitation ferme automatiquement les descripteurs de fichiers correspondant ``0``, ``1`` et ``2`` lorsqu'un processus se termine. Les autres descripteurs de fichiers doivent être explicitement fermés par le processus. Si nécessaire, cela peut se faire en enregistrant une fonction permettant de fermer correctement les fichiers ouverts via `atexit(3)`_. Il faut noter que par défaut un appel à `execve(2)`_ ne ferme pas les descripteurs de fichiers ouverts par le processus. C'est nécessaire pour permettre au programme exécuté d'avoir les entrées et sorties standard voulues. - -Lorsqu'un fichier a été ouvert, le noyau du système d'exploitation maintient, outre les références vers l':term:`inode` du fichier, un :term:`offset pointer`. Cet :term:`offset pointer` est la position actuelle de la tête de lecture/écriture du fichier. Lorsqu'un fichier est ouvert, son :term:`offset pointer` est positionné au premier octet du fichier, sauf si le drapeau ``O_APPEND`` a été spécifié lors de l'ouverture du fichier, dans ce cas l':term:`offset pointer` est positionné juste après le dernier octet du fichier de façon à ce qu'une écriture s'ajoute à la suite du fichier. - -Les deux appels systèmes permettant de lire et d'écrire dans un fichier sont respectivement `read(2)`_ et `write(2)`_. - -.. code-block:: c - - #include <unistd.h> - - ssize_t read(int fd, void *buf, size_t count); - ssize_t write(int fd, const void *buf, size_t count); - -Ces deux appels systèmes prennent trois arguments. Le premier est le `descripteur du fichier` sur lequel l'opération doit être effectuée. Le second est un pointeur ``void *`` vers la zone mémoire à lire ou écrire et le dernier est la quantité de données à lire/écrire. Si l'appel système réussit, il retourne le nombre d'octets qui ont été écrits/lus et sinon une valeur négative et la variable ``errno`` donne plus de précisions sur le type d'erreur. `read(2)`_ retourne ``0`` lorsque la fin du fichier a été atteinte. - -Il est important de noter que `read(2)`_ et `write(2)`_ permettent de lire et d'écrire des séquences contiguës d'octets. Lorsque l'on écrit ou lit des chaînes de caractères dans lesquels chaque caractère est représenté sous la forme d'un byte, il est possible d'utiliser `read(2)`_ et `write(2)`_ pour lire et écrire d'autres types de données que des octets comme le montre l'exemple ci-dessous. - -.. literalinclude:: /Fichiers/src/read.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Lors de son exécution, ce programme affiche la sortie ci-dessous. - -.. literalinclude:: /Fichiers/src/read.out - :encoding: utf-8 - :language: console - - - -Si il est bien possible de sauvegarder dans un fichier des entiers, des nombres en virgule flottante voire même des structures, il faut être bien conscient que l'appel système `write(2)`_ se contente de sauvegarder sur le disque le contenu de la zone mémoire pointée par le pointeur qu'il a reçu comme second argument. Si comme dans l'exemple précédent c'est le même processus qui lit les données qu'il a écrit, il pourra toujours récupérer les données correctement. - -Par contre, lorsqu'un fichier est écrit sur un ordinateur, envoyé via Internet et lu sur un autre ordinateur, il peut se produire plusieurs problèmes dont il faut être conscient. Le premier problème est que deux ordinateurs différents n'utilisent pas nécessairement le même nombre d'octets pour représenter chaque type de données. Ainsi, sur un ordinateur équipé d'un ancien processeur [IA32]_, les entiers sont représentés sur 32 bits (i.e. 4 bytes) alors que sur les processeurs plus récents ils sont souvent représentés sur 64 bits (i.e. 8 bytes). Cela implique qu'un tableau de 100 entiers en 32 bits sera interprété comme un tableau de 50 entiers en 64 bits. - -Le second problème est que les fabricants de processeurs ne se sont pas mis d'accord sur la façon dont il fallait représenter les entiers sur 16 et 32 bits en mémoire. Il y a deux techniques qui sont utilisées : :term:`big endian` et :term:`little endian`. - -Pour comprendre ces deux techniques, regardons comment l'entier 16 bits ``0b1111111100000000`` est stocké en mémoire. En :term:`big endian`, le byte ``11111111`` sera stocké à l'adresse `x` et le byte ``00000000`` à l'adresse `x+1`. En :term:`little endian`, c'est le byte ``00000000`` qui est stocké à l'adresse `x` et le byte ``11111111`` qui est stocké à l'adresse `x+1`. Il en va de même pour les entiers encodés sur 32 bits comme illustré dans les deux figures ci-dessous [#fendianfig]_. - -.. figure:: /Fichiers/fig/500px-Big-Endian.png - :align: center - :scale: 40 - - Ecriture d'un entier 32 bits en mémoire en `big endian` - -.. figure:: /Fichiers/fig/500px-Little-Endian.png - :align: center - :scale: 40 - - Ecriture d'un entier 32 bits en mémoire en `little endian` - - -Pour les nombres en virgule flottante, ce problème ne se pose heureusement pas car tous les processeurs actuels utilisent la même norme pour représenter les nombres en virgule flottant en mémoire. - -Les processeurs [IA32]_ utilisent la représentation :term:`little endian` tandis que les PowerPC utilisent :term:`big endian`. Certains processeurs sont capables d'utiliser les deux représentations. - -Il est également possible en utilisant l'appel système `lseek(2)`_ de déplacer l':term:`offset pointer` associé à un :term:`descripteur de fichier`. - -.. code-block:: c - - #include <sys/types.h> - #include <unistd.h> - - off_t lseek(int fd, off_t offset, int whence); - -Cet appel système prend trois arguments. Le premier est le :term:`descripteur de fichier` dont l':term:`offset pointer` doit être modifié. Le second est un entier qui est utilisé pour le calcul de la nouvelle position :term:`offset pointer` et le troisième indique comment l':term:`offset pointer` doit être calculé. Il y a trois modes de calcul possibles pour l':term:`offset pointer` : - - - ``whence==SEEK_SET`` : dans ce cas, le deuxième argument de l'appel système indique la valeur exacte du nouvel :term:`offset pointer` - - ``whence==SEEK_CUR`` : dans ce cas, le nouvel :term:`offset pointer` sera sa position actuelle à laquelle le deuxième argument aura été ajouté - - ``whence==SEEK_END`` : dans ce cas, le nouvel :term:`offset pointer` sera la fin du fichier à laquelle le deuxième argument aura été ajouté - -.. note:: Fichiers temporaires - - Il est parfois nécessaire dans un programme de créer des fichiers temporaires qui sont utilisés pour effectuer des opérations dans le processus sans pour autant être visible dans d'autres processus et sur le système de fichiers. Il est possible d'utiliser `open(2)`_ pour créer un tel fichier temporaire, mais il faut dans ce cas prévoir tous les cas d'erreur qui peuvent se produire lorsque par exemple plusieurs instances du même programme s'exécutent au même moment. Une meilleure solution est d'utiliser la fonction de la librairie `mkstemp(3)`_. Cette fonction prend comme argument un modèle de nom de fichier qui se termine par ``XXXXXX`` et génère un nom de fichier unique et retourne un descripteur de fichier associé à ce fichier. Elle s'utilise généralement comme suit : - - .. code-block:: c - - char template[]="/tmp/sinf1252PROCXXXXXX"; - - int fd=mkstemp(template); - if(fd==-1) - exit_on_error("mkstemp"); - // template contient le nom exact du fichier généré - unlink(template); - // le fichier est effacé, mais reste accessible - // via son descripteur jusqu'à close(fd) - - // Accès au fichier avec read et write - - if(close(fd)==-1) - exit_on_error("close"); - // le fichier n'est plus accessible - - L'utilisation de `unlink(2)`_ permet de supprimer le fichier du système de fichiers dès qu'il a été créé. Ce fichier reste cependant accessible au processus tant que celui-ci dispose d'un descripteur de fichier qui y est associé. - -.. note:: Duplication de descripteurs de fichiers - - Dans certains cas il est utile de pouvoir dupliquer un descripteur de fichier. C'est possible avec les appels systèmes `dup(2)`_ et `dup2(2)`_. L'appel système `dup(2)`_ prend comme argument un descripteur de fichier et retourne le plus petit descripteur de fichier libre. Lorsqu'un descripteur de fichier a été dupliqué avec `dup(2)`_ les deux descripteurs de fichiers partagent le même :term:`offset pointer` et les mêmes modes d'accès au fichier. - - - -.. rubric:: Footnotes - -.. [#fminixfs] Cette structure est partiellement inspirée du format des inodes du système de fichiers Minix, voir `linux/minix_fs.h`_. - -.. [#finode] Le champ ``zone[10]`` permet de stocker dans l':term:`inode` les références vers les premiers secteurs du fichier et des références vers d'autres blocs qui contiennent eux-aussi des références vers des blocs. Cela permet de stocker une liste de secteurs qui est de taille variable à partir d'un :term:`inode` qui a lui une taille fixe. Une description détaillée des inodes peut se trouver dans une référence sur les systèmes d'exploitation telle que [Tanenbaum+2009]_. - -.. [#fext2fs] Source : `linux/ext2_fs.h`_ - -.. [#flns] Dans un système de fichiers Unix, un lien ne peut être créé avec `ln(1)`_ ou `link(2)`_ que lorsque les deux répertoires concernés sont situés sur le même système de fichiers. Si ce n'est pas le cas, il faut utiliser un :term:`lien symbolique`. Ceux-ci peuvent être créés en utilisant l'appel système `symlink(2)`_ ou via la commande `ln(1)`_ avec l'argument ``-s``. - -.. [#flimit] Il y a une limite maximale au nombre de fichiers qui peuvent être ouverts par un processus. Cette limite peut être récupérée avec l'appel système `getdtablesize(2)`_. - -.. [#fendianfig] Source : http://en.wikipedia.org/wiki/Endianness - - - diff --git a/Theorie/Fichiers/fig/500px-Big-Endian.png b/Theorie/Fichiers/fig/500px-Big-Endian.png deleted file mode 100644 index 2c2bb0166d3e0cb903ab8bfd0858b0a0e5436444..0000000000000000000000000000000000000000 Binary files a/Theorie/Fichiers/fig/500px-Big-Endian.png and /dev/null differ diff --git a/Theorie/Fichiers/fig/500px-Little-Endian.png b/Theorie/Fichiers/fig/500px-Little-Endian.png deleted file mode 100644 index 38341bb472f73db3732bd9e05da01c6685dc6b77..0000000000000000000000000000000000000000 Binary files a/Theorie/Fichiers/fig/500px-Little-Endian.png and /dev/null differ diff --git a/Theorie/Fichiers/fig/Big-Endian.svg b/Theorie/Fichiers/fig/Big-Endian.svg deleted file mode 100644 index 9fb208d1f2f24f7f0b7d29735979528747cd6856..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/fig/Big-Endian.svg +++ /dev/null @@ -1,363 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> -<svg - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - version="1.0" - width="280" - height="250" - id="svg2328"> - <defs - id="defs2330"> - <marker - refX="0" - refY="0" - orient="auto" - style="overflow:visible" - id="Arrow1Lend"> - <path - d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z " - transform="matrix(-0.8,0,0,-0.8,-10,0)" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" - id="path3194" /> - </marker> - </defs> - <g - id="layer1"> - <g - transform="translate(-33,-16)" - id="g3480"> - <g - transform="translate(10.684927,10)" - id="g2641"> - <g - transform="translate(-4.9999999,5.0000001)" - id="g2707"> - <g - transform="translate(-182,-39)" - id="g3414"> - <g - transform="translate(74.324543,139.79415)" - style="stroke:none" - id="g2177"> - <path - d="M 194.97975,115.0099 L 194.97975,85.205848 L 224.99053,85.205848 L 224.99053,115.0099 L 194.97975,115.0099 z " - style="fill:#ffffff;stroke:none;stroke-width:0.42571709;overflow:visible" - id="path2179" /> - <text - x="210.48268" - y="106.59099" - style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black" - id="text2181" - xml:space="preserve"><tspan - x="210.48268" - y="106.59099" - style="font-size:18px;stroke:none" - id="tspan2183">0D</tspan></text> - </g> - <g - transform="translate(74.324543,49.794155)" - style="stroke:none" - id="g3180"> - <path - d="M 194.97975,115.0099 L 194.97975,85.205848 L 224.99053,85.205848 L 224.99053,115.0099 L 194.97975,115.0099 z " - style="fill:#ffffff;stroke:none;stroke-width:0.42571709;overflow:visible" - id="path3182" /> - <text - x="210.48268" - y="106.59099" - style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black" - id="text3184" - xml:space="preserve"><tspan - x="210.48268" - y="106.59099" - style="font-size:18px;stroke:none" - id="tspan3186">0A</tspan></text> - </g> - <g - transform="translate(74.324543,79.794155)" - style="stroke:none" - id="g3188"> - <path - d="M 194.97975,115.0099 L 194.97975,85.205848 L 224.99053,85.205848 L 224.99053,115.0099 L 194.97975,115.0099 z " - style="fill:#ffffff;stroke:none;stroke-width:0.42571709;overflow:visible" - id="path3190" /> - <text - x="210.48268" - y="106.59099" - style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black" - id="text3192" - xml:space="preserve"><tspan - x="210.48268" - y="106.59099" - style="font-size:18px;stroke:none" - id="tspan3194">0B</tspan></text> - </g> - <g - transform="translate(74.324543,109.79415)" - style="stroke:none" - id="g3196"> - <path - d="M 194.97975,115.0099 L 194.97975,85.205848 L 224.99053,85.205848 L 224.99053,115.0099 L 194.97975,115.0099 z " - style="fill:#ffffff;stroke:none;stroke-width:0.42571709;overflow:visible" - id="path3198" /> - <text - x="210.48268" - y="106.59099" - style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black" - id="text3200" - xml:space="preserve"><tspan - x="210.48268" - y="106.59099" - style="font-size:18px;stroke:none" - id="tspan3202">0C</tspan></text> - </g> - <path - d="M 269.57222,255.25715 L 299.05792,255.42779" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.51429158;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path2185" /> - <path - d="M 269.68311,120.31689 L 269.63196,269.68311" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.6337797;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path3158" /> - <path - d="M 299.68311,120.31689 L 299.63195,269.68311" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.63377368;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path3168" /> - <path - d="M 269.57222,225.25715 L 299.05792,225.42779" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.51429158;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path3170" /> - <path - d="M 269.57222,194.57221 L 299.05792,194.74285" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.51429158;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path3172" /> - <path - d="M 269.57222,165.25715 L 299.05792,165.42779" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.51429158;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path3174" /> - <path - d="M 269.57222,135.25715 L 299.05792,135.42779" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.51429158;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path3178" /> - <g - transform="translate(63.764862,76.892123)" - style="stroke:none" - id="g3204"> - <text - x="49.333466" - y="-219.84514" - transform="matrix(0,1,-1,0,0,0)" - style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black" - id="text3208" - xml:space="preserve"><tspan - x="49.333466" - y="-219.84514" - style="font-size:18px;stroke:none;font-family:Times New Roman" - id="tspan3210">...</tspan></text> - <text - x="187.58347" - y="-219.84514" - transform="matrix(0,1,-1,0,0,0)" - style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black" - id="text3212" - xml:space="preserve"><tspan - x="187.58347" - y="-219.84514" - style="font-size:18px;stroke:none;font-family:Times New Roman" - id="tspan3214">...</tspan></text> - <g - transform="translate(69.065073,85.25)" - style="stroke:none;stroke-opacity:1" - id="g3279"> - <rect - width="40" - height="25" - x="96.485138" - y="67.85788" - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3281" /> - <text - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" - id="text3283" - xml:space="preserve"><tspan - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;stroke:none;stroke-opacity:1;font-family:Times New Roman" - id="tspan3285"><tspan - style="font-size:18px;font-style:italic;text-align:end;text-anchor:end;stroke:none;stroke-opacity:1" - id="tspan3287">a</tspan>+3:</tspan></text> - </g> - <g - transform="translate(69.065073,55.25)" - style="stroke:none;stroke-opacity:1" - id="g3309"> - <rect - width="40" - height="25" - x="96.485138" - y="67.85788" - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3311" /> - <text - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" - id="text3313" - xml:space="preserve"><tspan - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;stroke:none;stroke-opacity:1;font-family:Times New Roman" - id="tspan3315"><tspan - style="font-size:18px;font-style:italic;text-align:end;text-anchor:end;stroke:none;stroke-opacity:1" - id="tspan3317">a</tspan>+2:</tspan></text> - </g> - <g - transform="translate(69.065073,25.25)" - style="stroke:none;stroke-opacity:1" - id="g3319"> - <rect - width="40" - height="25" - x="96.485138" - y="67.85788" - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3321" /> - <text - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" - id="text3323" - xml:space="preserve"><tspan - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;stroke:none;stroke-opacity:1;font-family:Times New Roman" - id="tspan3325"><tspan - style="font-size:18px;font-style:italic;text-align:end;text-anchor:end;stroke:none;stroke-opacity:1" - id="tspan3327">a</tspan>+1:</tspan></text> - </g> - <g - transform="translate(69.065073,-4.7500002)" - style="stroke:none;stroke-opacity:1" - id="g3329"> - <rect - width="40" - height="25" - x="96.485138" - y="67.85788" - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3331" /> - <text - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" - id="text3333" - xml:space="preserve"><tspan - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;stroke:none;stroke-opacity:1;font-family:Times New Roman" - id="tspan3335"><tspan - style="font-size:18px;font-style:italic;text-align:end;text-anchor:end;stroke:none;stroke-opacity:1" - id="tspan3337">a</tspan>:</tspan></text> - </g> - </g> - <text - x="282.54688" - y="105.59375" - style="font-size:16px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" - id="text3347" - xml:space="preserve"><tspan - x="282.54688" - y="105.59375" - id="tspan3349">Memory</tspan></text> - </g> - <text - x="218.93581" - y="33.109375" - style="font-size:16px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" - id="text3343" - xml:space="preserve"><tspan - x="218.93581" - y="33.109375" - id="tspan3345">Register</tspan></text> - <text - x="208.28125" - y="222.54688" - style="font-size:16px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" - id="text3351" - xml:space="preserve"><tspan - x="208.28125" - y="222.54688" - id="tspan3353">Big-endian</tspan></text> - <g - id="g2631"> - <g - transform="translate(124.339,5.779998)" - id="g2363"> - <path - d="M 34.109876,69.331124 L 34.109876,36.668878 L 155.89012,36.668878 L 155.89012,69.331124 L 34.109876,69.331124 z " - style="fill:#ffffff;stroke:#000000;stroke-width:0.89775217;overflow:visible" - id="path2340" /> - <text - x="95" - y="60" - style="font-size:16px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black" - id="text2359" - xml:space="preserve"><tspan - x="95" - y="60" - style="font-size:20px" - id="tspan2361">0A0B0C0D</tspan></text> - </g> - <g - id="g2250"> - <path - d="M 260.6875,75.09375 L 261.5,199.59375 L 124,200.5 L 124,201.5 L 262,200.625 L 262.53125,200.59375 L 262.53125,200.09375 L 261.71875,75.09375 L 260.6875,75.09375 z " - style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.02955723px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" - id="path2215" /> - <path - d="M 134.29535,200.9325 L 138.38649,196.78736 L 124,201 L 138.44049,205.02364 L 134.29535,200.9325 z " - style="fill-rule:evenodd;stroke:#000000;stroke-width:0.82364578pt;marker-start:none" - id="path2256" /> - </g> - <g - id="g2242"> - <path - d="M 232.6875,75 L 231.96875,170.875 L 123.5,171 L 123.5,172 L 232.46875,171.875 L 232.96875,171.875 L 232.96875,171.375 L 233.6875,75 L 232.6875,75 z " - style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" - id="path3388" /> - <path - d="M 133.49999,171.48944 L 137.49577,167.48521 L 123.5,171.5 L 137.50422,175.48521 L 133.49999,171.48944 z " - style="fill-rule:evenodd;stroke:#000000;stroke-width:0.8pt;marker-start:none" - id="path2248" /> - </g> - <g - id="g2234"> - <path - d="M 201.625,75.375 L 202.125,140.0625 L 124,141 L 124,142 L 202.65625,141.0625 L 203.125,141.0625 L 203.125,140.5625 L 202.625,75.375 L 201.625,75.375 z " - style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" - id="path3390" /> - <path - d="M 133.9993,141.3816 L 137.95166,137.33451 L 124,141.5 L 138.04638,145.33395 L 133.9993,141.3816 z " - style="fill-rule:evenodd;stroke:#000000;stroke-width:0.8pt;marker-start:none" - id="path2240" /> - </g> - <g - id="g2226"> - <path - d="M 174.1875,75 L 174.0625,110.46875 L 124,111 L 124,112 L 174.5625,111.46875 L 175.0625,111.4375 L 175.0625,110.96875 L 175.1875,75 L 174.1875,75 z " - style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" - id="path3392" /> - <path - d="M 133.99943,111.3928 L 137.95631,107.35014 L 124,111.5 L 138.04208,115.34968 L 133.99943,111.3928 z " - style="fill-rule:evenodd;stroke:#000000;stroke-width:0.8pt;marker-start:none" - id="path2232" /> - </g> - </g> - </g> - </g> - </g> - </g> -</svg> diff --git a/Theorie/Fichiers/fig/Little-Endian.svg b/Theorie/Fichiers/fig/Little-Endian.svg deleted file mode 100644 index c1545e495216a0ff661b4fc385360fa5f715e156..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/fig/Little-Endian.svg +++ /dev/null @@ -1,358 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> -<svg - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - version="1.0" - width="280" - height="250" - id="svg2328"> - <defs - id="defs2330"> - <marker - refX="0" - refY="0" - orient="auto" - style="overflow:visible" - id="Arrow1Lend"> - <path - d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z " - transform="matrix(-0.8,0,0,-0.8,-10,0)" - style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none" - id="path3194" /> - </marker> - </defs> - <g - id="layer1"> - <g - transform="translate(-33,-16)" - id="g3480"> - <g - transform="translate(-14.322004,-29)" - id="g3546"> - <g - id="g3414"> - <g - transform="translate(74.324543,139.79415)" - style="stroke:none" - id="g2177"> - <path - d="M 194.97975,115.0099 L 194.97975,85.205848 L 224.99053,85.205848 L 224.99053,115.0099 L 194.97975,115.0099 z " - style="fill:#ffffff;stroke:none;stroke-width:0.42571709;overflow:visible" - id="path2179" /> - <text - x="210.48268" - y="106.59099" - style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black" - id="text2181" - xml:space="preserve"><tspan - x="210.48268" - y="106.59099" - style="font-size:18px;stroke:none" - id="tspan2183">0A</tspan></text> - </g> - <g - transform="translate(74.324543,49.794155)" - style="stroke:none" - id="g3180"> - <path - d="M 194.97975,115.0099 L 194.97975,85.205848 L 224.99053,85.205848 L 224.99053,115.0099 L 194.97975,115.0099 z " - style="fill:#ffffff;stroke:none;stroke-width:0.42571709;overflow:visible" - id="path3182" /> - <text - x="210.48268" - y="106.59099" - style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black" - id="text3184" - xml:space="preserve"><tspan - x="210.48268" - y="106.59099" - style="font-size:18px;stroke:none" - id="tspan3186">0D</tspan></text> - </g> - <g - transform="translate(74.324543,79.794155)" - style="stroke:none" - id="g3188"> - <path - d="M 194.97975,115.0099 L 194.97975,85.205848 L 224.99053,85.205848 L 224.99053,115.0099 L 194.97975,115.0099 z " - style="fill:#ffffff;stroke:none;stroke-width:0.42571709;overflow:visible" - id="path3190" /> - <text - x="210.48268" - y="106.59099" - style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black" - id="text3192" - xml:space="preserve"><tspan - x="210.48268" - y="106.59099" - style="font-size:18px;stroke:none" - id="tspan3194">0C</tspan></text> - </g> - <g - transform="translate(74.324543,109.79415)" - style="stroke:none" - id="g3196"> - <path - d="M 194.97975,115.0099 L 194.97975,85.205848 L 224.99053,85.205848 L 224.99053,115.0099 L 194.97975,115.0099 z " - style="fill:#ffffff;stroke:none;stroke-width:0.42571709;overflow:visible" - id="path3198" /> - <text - x="210.48268" - y="106.59099" - style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black" - id="text3200" - xml:space="preserve"><tspan - x="210.48268" - y="106.59099" - style="font-size:18px;stroke:none" - id="tspan3202">0B</tspan></text> - </g> - <path - d="M 269.57222,255.25715 L 299.05792,255.42779" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.51429158;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path2185" /> - <path - d="M 269.68311,120.31689 L 269.63196,269.68311" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.6337797;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path3158" /> - <path - d="M 299.68311,120.31689 L 299.63195,269.68311" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.63377368;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path3168" /> - <path - d="M 269.57222,225.25715 L 299.05792,225.42779" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.51429158;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path3170" /> - <path - d="M 269.57222,194.57221 L 299.05792,194.74285" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.51429158;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path3172" /> - <path - d="M 269.57222,165.25715 L 299.05792,165.42779" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.51429158;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path3174" /> - <path - d="M 269.57222,135.25715 L 299.05792,135.42779" - style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.51429158;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - id="path3178" /> - <g - transform="translate(63.764862,76.892123)" - style="stroke:none" - id="g3204"> - <text - x="49.333466" - y="-219.84514" - transform="matrix(0,1,-1,0,0,0)" - style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black" - id="text3208" - xml:space="preserve"><tspan - x="49.333466" - y="-219.84514" - style="font-size:18px;stroke:none;font-family:Times New Roman" - id="tspan3210">...</tspan></text> - <text - x="187.58347" - y="-219.84514" - transform="matrix(0,1,-1,0,0,0)" - style="font-size:20px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black" - id="text3212" - xml:space="preserve"><tspan - x="187.58347" - y="-219.84514" - style="font-size:18px;stroke:none;font-family:Times New Roman" - id="tspan3214">...</tspan></text> - <g - transform="translate(69.065073,85.25)" - style="stroke:none;stroke-opacity:1" - id="g3279"> - <rect - width="40" - height="25" - x="96.485138" - y="67.85788" - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3281" /> - <text - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" - id="text3283" - xml:space="preserve"><tspan - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;stroke:none;stroke-opacity:1;font-family:Times New Roman" - id="tspan3285"><tspan - style="font-size:18px;font-style:italic;text-align:end;text-anchor:end;stroke:none;stroke-opacity:1" - id="tspan3287">a</tspan>+3:</tspan></text> - </g> - <g - transform="translate(69.065073,55.25)" - style="stroke:none;stroke-opacity:1" - id="g3309"> - <rect - width="40" - height="25" - x="96.485138" - y="67.85788" - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3311" /> - <text - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" - id="text3313" - xml:space="preserve"><tspan - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;stroke:none;stroke-opacity:1;font-family:Times New Roman" - id="tspan3315"><tspan - style="font-size:18px;font-style:italic;text-align:end;text-anchor:end;stroke:none;stroke-opacity:1" - id="tspan3317">a</tspan>+2:</tspan></text> - </g> - <g - transform="translate(69.065073,25.25)" - style="stroke:none;stroke-opacity:1" - id="g3319"> - <rect - width="40" - height="25" - x="96.485138" - y="67.85788" - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3321" /> - <text - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" - id="text3323" - xml:space="preserve"><tspan - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;stroke:none;stroke-opacity:1;font-family:Times New Roman" - id="tspan3325"><tspan - style="font-size:18px;font-style:italic;text-align:end;text-anchor:end;stroke:none;stroke-opacity:1" - id="tspan3327">a</tspan>+1:</tspan></text> - </g> - <g - transform="translate(69.065073,-4.7500002)" - style="stroke:none;stroke-opacity:1" - id="g3329"> - <rect - width="40" - height="25" - x="96.485138" - y="67.85788" - style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" - id="rect3331" /> - <text - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" - id="text3333" - xml:space="preserve"><tspan - x="133.96561" - y="82.861786" - style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;stroke:none;stroke-opacity:1;font-family:Times New Roman" - id="tspan3335"><tspan - style="font-size:18px;font-style:italic;text-align:end;text-anchor:end;stroke:none;stroke-opacity:1" - id="tspan3337">a</tspan>:</tspan></text> - </g> - </g> - <text - x="282.54688" - y="105.59375" - style="font-size:16px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" - id="text3347" - xml:space="preserve"><tspan - x="282.54688" - y="105.59375" - id="tspan3349">Memory</tspan></text> - </g> - <g - id="g3466"> - <g - transform="translate(33.661004,43.779998)" - id="g2363"> - <path - d="M 34.109876,69.331124 L 34.109876,36.668878 L 155.89012,36.668878 L 155.89012,69.331124 L 34.109876,69.331124 z " - style="fill:#ffffff;stroke:#000000;stroke-width:0.89775217;overflow:visible" - id="path2340" /> - <text - x="95" - y="60" - style="font-size:16px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial Black" - id="text2359" - xml:space="preserve"><tspan - x="95" - y="60" - style="font-size:20px" - id="tspan2361">0A0B0C0D</tspan></text> - </g> - <text - x="128.25781" - y="71.109375" - style="font-size:16px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" - id="text3343" - xml:space="preserve"><tspan - x="128.25781" - y="71.109375" - id="tspan3345">Register</tspan></text> - <text - x="143.77344" - y="266.10938" - style="font-size:16px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman" - id="text3351" - xml:space="preserve"><tspan - x="143.77344" - y="266.10938" - id="tspan3353">Little-endian</tspan></text> - <g - id="g2225"> - <path - d="M 170.03125,113.09375 L 170.0625,148.5 L 170.0625,149 L 170.5625,149 L 224.46875,149.875 L 224.5,148.84375 L 171.09375,147.96875 L 171.0625,113.09375 L 170.03125,113.09375 z " - style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.02955723px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" - id="path2215" /> - <path - d="M 214.19102,149.19681 L 210.00613,153.24728 L 224.48522,149.36483 L 210.14055,145.01192 L 214.19102,149.19681 z " - style="fill-rule:evenodd;stroke:#000000;stroke-width:0.82364578pt;marker-start:none" - id="path2231" /> - </g> - <g - id="g2233"> - <path - d="M 142,113 L 142.15625,177.9375 L 142.15625,178.4375 L 142.65625,178.4375 L 224.5,178.5 L 224.5,177.5 L 143.15625,177.4375 L 143,113 L 142,113 z " - style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" - id="path3388" /> - <path - d="M 214.5,177.99336 L 210.49735,181.9907 L 224.5,178 L 210.50266,173.9907 L 214.5,177.99336 z " - style="fill-rule:evenodd;stroke:#000000;stroke-width:0.8pt;marker-start:none" - id="path2239" /> - </g> - <g - id="g2241"> - <path - d="M 110.9375,113.375 L 110.375,209.6875 L 110.375,210.1875 L 110.875,210.1875 L 225,210.5 L 225,209.5 L 111.375,209.1875 L 111.9375,113.375 L 110.9375,113.375 z " - style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" - id="path3390" /> - <path - d="M 215.00004,209.97211 L 210.9889,213.96094 L 225,210 L 211.01121,205.96097 L 215.00004,209.97211 z " - style="fill-rule:evenodd;stroke:#000000;stroke-width:0.8pt;marker-start:none" - id="path2247" /> - </g> - <g - id="g2249"> - <path - d="M 83.5,113 L 83.4375,238.5 L 83.4375,239 L 83.9375,239 L 224,239 L 224,238 L 84.4375,238 L 84.5,113 L 83.5,113 z " - style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" - id="path3392" /> - <path - d="M 214,238.50057 L 210.00023,242.50079 L 224,238.5 L 209.99977,234.50079 L 214,238.50057 z " - style="fill-rule:evenodd;stroke:#000000;stroke-width:0.8pt;marker-start:none" - id="path2255" /> - </g> - </g> - </g> - </g> - </g> -</svg> diff --git a/Theorie/Fichiers/fig/figures-10-001-c.png b/Theorie/Fichiers/fig/figures-10-001-c.png deleted file mode 100644 index 9e5c34af533251ddaa62607703df2a6a205250ff..0000000000000000000000000000000000000000 Binary files a/Theorie/Fichiers/fig/figures-10-001-c.png and /dev/null differ diff --git a/Theorie/Fichiers/fig/figures-10-002-c.png b/Theorie/Fichiers/fig/figures-10-002-c.png deleted file mode 100644 index e4250eb104667bc17bc606c468e17b88273b7748..0000000000000000000000000000000000000000 Binary files a/Theorie/Fichiers/fig/figures-10-002-c.png and /dev/null differ diff --git a/Theorie/Fichiers/fig/figures-10-003-c.png b/Theorie/Fichiers/fig/figures-10-003-c.png deleted file mode 100644 index 30ca2f50203600c3b68a0af8a37c8f6bc041b39a..0000000000000000000000000000000000000000 Binary files a/Theorie/Fichiers/fig/figures-10-003-c.png and /dev/null differ diff --git a/Theorie/Fichiers/fig/figures-10-004-c.png b/Theorie/Fichiers/fig/figures-10-004-c.png deleted file mode 100644 index 3a0c96f5da66cc39d56f99530d164391ac81ca34..0000000000000000000000000000000000000000 Binary files a/Theorie/Fichiers/fig/figures-10-004-c.png and /dev/null differ diff --git a/Theorie/Fichiers/fig/figures-10.001.png b/Theorie/Fichiers/fig/figures-10.001.png deleted file mode 100644 index c9e922bfbddb81f604ddb5b87fb91aa7087fb2b2..0000000000000000000000000000000000000000 Binary files a/Theorie/Fichiers/fig/figures-10.001.png and /dev/null differ diff --git a/Theorie/Fichiers/fig/figures-10.002.png b/Theorie/Fichiers/fig/figures-10.002.png deleted file mode 100644 index 2a92c9bb3bbcfcdf6fb54c2f906d1ddf4f50afc5..0000000000000000000000000000000000000000 Binary files a/Theorie/Fichiers/fig/figures-10.002.png and /dev/null differ diff --git a/Theorie/Fichiers/fig/figures-10.003.png b/Theorie/Fichiers/fig/figures-10.003.png deleted file mode 100644 index f516ac03cb5e5c7e29dec1b04124962eb17f1b57..0000000000000000000000000000000000000000 Binary files a/Theorie/Fichiers/fig/figures-10.003.png and /dev/null differ diff --git a/Theorie/Fichiers/fig/figures-10.004.png b/Theorie/Fichiers/fig/figures-10.004.png deleted file mode 100644 index adce61b49d0e919c7d038b3561b113b62a6147f5..0000000000000000000000000000000000000000 Binary files a/Theorie/Fichiers/fig/figures-10.004.png and /dev/null differ diff --git a/Theorie/Fichiers/src/a.out b/Theorie/Fichiers/src/a.out deleted file mode 100755 index ea06754ee6b3584cb6be4787d742ac2308f089cc..0000000000000000000000000000000000000000 Binary files a/Theorie/Fichiers/src/a.out and /dev/null differ diff --git a/Theorie/Fichiers/src/alarm.c b/Theorie/Fichiers/src/alarm.c deleted file mode 100644 index 07abd5a1bd1c2d72051687ffb1a13ea702802a07..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/alarm.c +++ /dev/null @@ -1,45 +0,0 @@ -/************************************** - * alarm.c - * - * Programme d'exemple d'utilisation des - * signaux SIGUSR - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <unistd.h> -#include <stdbool.h> - -static void sig_handler(int); - -int main (int argc, char *argv[]) { - char c; - printf("Tapez return en moins de 5 secondes !\n"); - fflush(stdout); - if(signal(SIGALRM,sig_handler)==SIG_ERR) { - perror("signal"); - exit(EXIT_FAILURE); - } - // sigalrm interrompt les appels système - if(siginterrupt(SIGALRM,true)<0) { - perror("siginterrupt"); - exit(EXIT_FAILURE); - } - alarm(5); - int r=read(STDIN_FILENO,&c,1); - if((r==1)&&(c=='\n')) { - alarm(0); // reset timer - printf("Gagné\n"); - exit(EXIT_SUCCESS); - } - printf("Perdu !\n"); - exit(EXIT_FAILURE); -} - -static void sig_handler(int signum) { - // rien à faire, read sera interrompu -} - -///BBB diff --git a/Theorie/Fichiers/src/alarm.out b/Theorie/Fichiers/src/alarm.out deleted file mode 100644 index 33c2eb4e5e6a7ac8e3dfbd7acbd5ee37a08ec5a2..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/alarm.out +++ /dev/null @@ -1,2 +0,0 @@ -Tapez return en moins de 5 secondes ! -Perdu ! diff --git a/Theorie/Fichiers/src/alarm2.c b/Theorie/Fichiers/src/alarm2.c deleted file mode 100644 index 4007cc6006e2eb8c9f5c0de95990cb3f1bef6db3..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/alarm2.c +++ /dev/null @@ -1,58 +0,0 @@ -/************************************** - * alarm.c - * - * Programme d'exemple d'utilisation des - * signaux SIGUSR - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <unistd.h> -#include <stdbool.h> -#include <setjmp.h> - -sigjmp_buf env; - -static void sig_handler(int); - -int main (int argc, char *argv[]) { - char c; - printf("Tapez return en moins de 5 secondes !\n"); - fflush(stdout); - if(signal(SIGALRM,sig_handler)==SIG_ERR) { - perror("signal"); - exit(EXIT_FAILURE); - } - // sigalrm interrompt les appels système - if(siginterrupt(SIGALRM,true)<0) { - perror("siginterrupt"); - exit(EXIT_FAILURE); - } - int r=0; - if(sigsetjmp(env,1)==0) { - // sig_handler n'a pas encore été appelé - alarm(5); - r=read(STDIN_FILENO,&c,1); - } - else { - // sig_handler a déjà été exécuté - // le délai a déjà expiré, inutile de faire read - } - alarm(0); // arrêt du timer - if((r==1)&&(c=='\n')) { - printf("Gagné\n"); - exit(EXIT_SUCCESS); - } - else { - printf("Perdu !\n"); - exit(EXIT_FAILURE); - } -} - -static void sig_handler(int signum) { - siglongjmp(env,1); -} - -///BBB diff --git a/Theorie/Fichiers/src/fork-pipe.c b/Theorie/Fichiers/src/fork-pipe.c deleted file mode 100644 index 7048b623e9925ce3da3fac9da29759ad78777d4a..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/fork-pipe.c +++ /dev/null @@ -1,80 +0,0 @@ -/************************************** - * fork-pipe.c - * - * Programme d'exemple d'utilisation de - * pipe en combinaison avec fork - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/wait.h> -#include <sys/types.h> -#include <stdbool.h> - -void exit_on_error(char *s) { - perror(s); - exit(EXIT_FAILURE); -} - - -int main (int argc, char *argv[]) { - int status; - pid_t pid; - int fd[2]; - int err; - - if ( pipe(fd)==-1) - exit_on_error("pipe"); - - pid=fork(); - - if (pid==-1) { - // erreur à l'exécution de fork - exit_on_error("fork"); - } - // pas d'erreur - if (pid==0) { - int count=0; - int finished=false; - int n; - // processus fils, lecture du pipe - if(close(fd[1])==-1) - exit_on_error("close"); - while ( !finished) { - err=read(fd[0],(void *) &n,sizeof(int)); - if(err==sizeof(int)) - // entier reçu - count++; - else - if(err==0) - // fin de fichier - finished=true; - else - exit_on_error("read"); - } - if(close(fd[0])==-1) - exit_on_error("close"); - printf("Reçu : %d entiers\n",count); - return(EXIT_SUCCESS); - } - else { - // processus père - if(close(fd[0])==-1) - exit_on_error("close"); - for(int i=0;i<100000;i++) { - if(write(fd[1],(void *) &i,sizeof(int))==-1) - exit_on_error("write"); - } - if( close(fd[1])==-1) - exit_on_error("close(fd[1])"); - - int fils=waitpid(pid,&status,0); - if(fils==-1) { - exit_on_error("wait"); - } - // fils terminé correctement - } -} -///BBB diff --git a/Theorie/Fichiers/src/longjmp.c b/Theorie/Fichiers/src/longjmp.c deleted file mode 100644 index 87cc0b1c0a8a0577ac5ca3a99d283ec3187fcd9b..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/longjmp.c +++ /dev/null @@ -1,36 +0,0 @@ -/************************************** - * longjmp.c - * - * Programme d'exemple de longjmp - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <setjmp.h> - -jmp_buf label; - -void f() { - - printf("Début fonction f\n"); - if(setjmp(label)==0) { - printf("Exécution normale\n"); - } - else { - printf("Exécution après longjmp\n"); - } -} - -void g() { - printf("Début fonction g\n"); - longjmp(label,1); - printf("Ne sera jamais affiché\n"); -} - -int main (int argc, char *argv[]) { - f(); - g(); - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/Fichiers/src/longjmp.out b/Theorie/Fichiers/src/longjmp.out deleted file mode 100644 index f551980e51fabcd08d9e155c96de7a13d1ba114b..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/longjmp.out +++ /dev/null @@ -1,4 +0,0 @@ -Début fonction f -Exécution normale -Début fonction g -Exécution après longjmp diff --git a/Theorie/Fichiers/src/nkill.sh b/Theorie/Fichiers/src/nkill.sh deleted file mode 100755 index 2eccd5e9605ff593abefa50f969666497fbf982c..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/nkill.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -if [ $# -ne 2 ] -then - echo "Usage: `basename $0` n pid" - exit 1 -fi -n=$1 -pid=$2 -for (( c=1; c<=$n; c++ )) -do - kill -s SIGUSR1 $pid -done diff --git a/Theorie/Fichiers/src/process-sem-after.c b/Theorie/Fichiers/src/process-sem-after.c deleted file mode 100644 index 06ebd160fba30ad04514b35f928fa1b0386b78ce..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/process-sem-after.c +++ /dev/null @@ -1,58 +0,0 @@ -/************************************** - * process-sem-before.c - * - * Programme d'exemple de sémaphores nommés - * La fonction after ne peut s'exécuter - * qu'après la fonction before - **************************************/ - -#include <pthread.h> -#include <semaphore.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <fcntl.h> /* For O_* constants */ -#include <sys/stat.h> /* For mode constants */ -#include <sys/types.h> -#include <unistd.h> - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - - -///AAA - -sem_t *semaphore; - -void after() { - sem_wait(semaphore); - // do something - for(int j=0;j<1000000;j++) { - } - printf("after done, pid=%d\n",(int) getpid()); -} - -int main (int argc, char *argv[]) { - int err; - - // semaphore a été créé par before - semaphore=sem_open("lsinf1252",0); - if(semaphore==SEM_FAILED) { - error(-1,"sem_open"); - } - after(); - - err=sem_close(semaphore); - if(err!=0) { - error(err,"sem_close"); - } - err=sem_unlink("lsinf1252"); - if(err!=0) { - error(err,"sem_unlink"); - } - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/Fichiers/src/process-sem-before.c b/Theorie/Fichiers/src/process-sem-before.c deleted file mode 100644 index 1356eb8678aaa5ef6b413163832cd8ba7fa42511..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/process-sem-before.c +++ /dev/null @@ -1,56 +0,0 @@ -/************************************** - * process-sem-before.c - * - * Programme d'exemple de sémaphores - * La fonction after ne peut s'exécuter - * qu'après la fonction before - **************************************/ - -#include <pthread.h> -#include <semaphore.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> /* For O_* constants */ -#include <sys/stat.h> /* For mode constants */ -#include <sys/types.h> - - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - - -///AAA - -sem_t *semaphore; - -void before() { - // do something - for(int j=0;j<1000000;j++) { - } - printf("before done, pid=%d\n",(int) getpid()); - sem_post(semaphore); -} - - -int main (int argc, char *argv[]) { - - int err; - - semaphore=sem_open("lsinf1252",O_CREAT,S_IRUSR | S_IWUSR,0); - if(semaphore==SEM_FAILED) { - error(-1,"sem_open"); - } - sleep(20); - before(); - err=sem_close(semaphore); - if(err!=0) { - error(err,"sem_close"); - } - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/Fichiers/src/read.c b/Theorie/Fichiers/src/read.c deleted file mode 100644 index b81b8e7d14e4247bc3fd803bf5e9358959c9f7e7..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/read.c +++ /dev/null @@ -1,90 +0,0 @@ -/************************************** - * read.c - * - * Programme d'exemple d'utilisation de - * fichiers - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> - -void exit_on_error(char *s) { - perror(s); - exit(EXIT_FAILURE); -} - -int main (int argc, char *argv[]) { - int n=1252; - int n2; - short ns=1252; - short ns2; - long nl=125212521252; - long nl2; - float f=12.52; - float f2; - char *s="sinf1252"; - char *s2=(char *) malloc(strlen(s)*sizeof(char )+1); - int err; - int fd; - - fd=open("test.dat",O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); - if(fd==-1) { - perror("open"); - exit(EXIT_FAILURE); - } - if( write(fd, (void *) s, strlen(s)) == -1 ) - exit_on_error("write s"); - if (write(fd, (void *) &n, sizeof(int )) == -1) - exit_on_error("write n"); - if (write(fd, (void *) &ns, sizeof(short int))==-1) - exit_on_error("write ns"); - if (write(fd, (void *) &nl, sizeof(long int))==-1) - exit_on_error("write nl"); - if (write(fd, (void *) &f, sizeof(float))==-1) - exit_on_error("write f"); - if (close(fd)==-1) - exit_on_error("close "); - - // lecture - fd=open("test.dat",O_RDONLY); - if(fd==-1) { - perror("open"); - exit(EXIT_FAILURE); - } - printf("Fichier ouvert\n"); - - if(read(fd, (void *) s2, strlen(s))==-1) - exit_on_error("read s"); - printf("Donnée écrite : %s, lue: %s\n",s,s2); - - if(read(fd, (void *) &n2, sizeof(int))==-1) - exit_on_error("read n"); - printf("Donnée écrite : %d, lue: %d\n",n,n2); - - if(read(fd, (void *) &ns2, sizeof(short))==-1) - exit_on_error("read ns"); - printf("Donnée écrite : %d, lue: %d\n",ns,ns2); - - if(read(fd, (void *) &nl2, sizeof(long))==-1) - exit_on_error("read nl"); - printf("Donnée écrite : %ld, lue: %ld\n",nl,nl2); - - if(read(fd, (void *) &f2, sizeof(float))==-1) - exit_on_error("read f"); - printf("Donnée écrite : %f, lue: %f\n",f,f2); - err=close(fd); - if(err==-1){ - perror("close"); - exit(EXIT_FAILURE); - } - - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/Fichiers/src/read.out b/Theorie/Fichiers/src/read.out deleted file mode 100644 index 752a113708158e8f68fa3cce793bf37bcf7d806a..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/read.out +++ /dev/null @@ -1,6 +0,0 @@ -Fichier ouvert -Donnée écrite : sinf1252, lue: sinf1252 -Donnée écrite : 1252, lue: 1252 -Donnée écrite : 1252, lue: 1252 -Donnée écrite : 125212521252, lue: 125212521252 -Donnée écrite : 12.520000, lue: 12.520000 diff --git a/Theorie/Fichiers/src/readdir.c b/Theorie/Fichiers/src/readdir.c deleted file mode 100644 index 0f6b7a01e1debd006d575627a50254017c2f2508..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/readdir.c +++ /dev/null @@ -1,38 +0,0 @@ -/************************************** - * readdir.c - * - * Programme d'exemple d'utilisation de - * répertoires - * - *************************************/ -///AAA -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <dirent.h> - -void exit_on_error(char *s) { - perror(s); - exit(EXIT_FAILURE); -} - -int main (int argc, char *argv[]) { - - DIR *dirp; - struct dirent *dp; - char name[]="."; - dirp = opendir(name); - if(dirp==NULL) { - exit_on_error("opendir"); - } - while ((dp = readdir(dirp)) != NULL) { - printf("%s\n",dp->d_name); - } - int err = closedir(dirp); - if(err<0) { - exit_on_error("closedir"); - } - - -} -///BBB diff --git a/Theorie/Fichiers/src/sigfpe.c b/Theorie/Fichiers/src/sigfpe.c deleted file mode 100644 index eb296704d8b424ede768c1743bc3327d50670bdd..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/sigfpe.c +++ /dev/null @@ -1,21 +0,0 @@ -/************************************** - * sigfpe.c - * - * Programme d'exemple de signal sigfpe - * fichiers - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> - -int main (int argc, char *argv[]) { - int n=1252; - int zero=0; - printf("Calcul de : %d/%d\n",n,zero); - fflush(stdout); - printf("Résultat : %d\n",n/zero); - - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/Fichiers/src/sigfpe2.c b/Theorie/Fichiers/src/sigfpe2.c deleted file mode 100644 index d8d3468045809760847566e804a62f9c0796aef5..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/sigfpe2.c +++ /dev/null @@ -1,50 +0,0 @@ -/************************************** - * sigfpe.c - * - * Programme d'exemple de signal sigfpe - * handler incorrect - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <string.h> -#include <unistd.h> - -static void sigfpe_handler(int); - -int main (int argc, char *argv[]) { - - int n=1252; - void (*handler)(int); - - handler=signal(SIGFPE,sigfpe_handler); - if(handler==SIG_ERR) { - perror("signal"); - exit(EXIT_FAILURE); - } - - for(int i=1;i<argc;i++) { - char *endptr; - printf("Traitement de argv[%d]=%s\n",i,argv[i]); - fflush(stdout); - long val=strtol(argv[i],&endptr,10); - if(*endptr=='\0') { - int resultat=n/(int) val; - printf("%d/%d=%d\n",n,(int) val,resultat); - } - else { - printf("Argument incorrect : %s\n",argv[i]); - } - } - return(EXIT_SUCCESS); -} - -static void sigfpe_handler(int signum) { - char *msg="Signal SIGFPE reçu\n"; - write(STDOUT_FILENO,msg,strlen(msg)); - -} - -///BBB diff --git a/Theorie/Fichiers/src/sigfpe3.c b/Theorie/Fichiers/src/sigfpe3.c deleted file mode 100644 index 671c55bb747b7243fc9e36d8a7ceb3ada5cd7d48..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/sigfpe3.c +++ /dev/null @@ -1,53 +0,0 @@ -/************************************** - * sigfpe.c - * - * Programme d'exemple de signal sigfpe - * fichiers - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <setjmp.h> - -sigjmp_buf buf; - -static void sigfpe_handler(int); - -int main (int argc, char *argv[]) { - - int n=1252; - if(signal(SIGFPE,sigfpe_handler)==SIG_ERR) { - perror("signal"); - exit(EXIT_FAILURE); - } - - for(int i=1;i<argc;i++) { - char *endptr; - int r; - printf("Traitement de argv[%d]=%s\n",i,argv[i]); - long val=strtol(argv[i],&endptr,10); - if(*endptr=='\0') { - r=sigsetjmp(buf,1); - if(r==0) { - int resultat=n/(int) val; - printf("%d/%d=%d\n",n,(int) val,resultat); - } - else { - printf("%d/%d=NaN\n",n,(int) val); - } - } - else { - printf("Argument incorrect : %s\n",argv[i]); - } - } - return(EXIT_SUCCESS); -} - -static void sigfpe_handler(int signum) { - // ignorer la donnée et passer à la suivante - siglongjmp(buf,1); -} - -///BBB diff --git a/Theorie/Fichiers/src/sigusr.c b/Theorie/Fichiers/src/sigusr.c deleted file mode 100644 index 466943279c4d2e672a36e2833b2ddd5035a20d67..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/sigusr.c +++ /dev/null @@ -1,59 +0,0 @@ -/************************************** - * sigusr.c - * - * Programme d'exemple d'utilisation des - * signaux SIGUSR - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <signal.h> -#include <unistd.h> -#include <stdint.h> -#include <stdio.h> - -volatile sig_atomic_t n_sigusr1=0; -volatile sig_atomic_t n_sigusr2=0; - -static void sig_handler(int); - -int main (int argc, char *argv[]) { - - if(signal(SIGUSR1,sig_handler)==SIG_ERR) { - perror("signal"); - exit(EXIT_FAILURE); - } - if(signal(SIGUSR2,sig_handler)==SIG_ERR) { - perror("signal"); - exit(EXIT_FAILURE); - } - - while( (n_sigusr1+n_sigusr2) <5) { - // vide - } - - printf("Fin du processus\n"); - printf("Reçu %d SIGUSR1 et %d SIGUSR2\n",n_sigusr1,n_sigusr2); - return(EXIT_SUCCESS); -} - -static void sig_handler(int signum) { - - if(signum==SIGUSR1) { - n_sigusr1++; - } - else { - if(signum==SIGUSR2) { - n_sigusr2++; - } - else { - char *msg="Reçu signal inattendu\n"; - write(STDERR_FILENO,msg,strlen(msg)); - _exit(EXIT_FAILURE); - } - } -} - -///BBB diff --git a/Theorie/Fichiers/src/sigusrcount.c b/Theorie/Fichiers/src/sigusrcount.c deleted file mode 100644 index ed0aacf0387488f30780f199a0cea620213ea2ff..0000000000000000000000000000000000000000 --- a/Theorie/Fichiers/src/sigusrcount.c +++ /dev/null @@ -1,41 +0,0 @@ -/************************************** - * sigusrcount.c - * - * Programme d'exemple d'utilisation des - * signaux SIGUSR - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <unistd.h> - -volatile sig_atomic_t n_sigusr1=0; - -static void sig_handler(int); - -int main (int argc, char *argv[]) { - - if(signal(SIGUSR1,sig_handler)==SIG_ERR) { - perror("signal"); - exit(EXIT_FAILURE); - } - int duree=60; - while(duree>0) { - printf("Exécution de sleep(%d)\n",duree); - duree=sleep(duree); - } - printf("Fin du processus\n"); - printf("Reçu %d SIGUSR1\n",n_sigusr1); - return(EXIT_SUCCESS); -} - -static void sig_handler(int signum) { - - if(signum==SIGUSR1) { - n_sigusr1++; - } -} - -///BBB diff --git a/Theorie/Makefile b/Theorie/Makefile deleted file mode 100644 index 9ba663ec0638a6ca8fb361a49d13c7c75fe3dfb1..0000000000000000000000000000000000000000 --- a/Theorie/Makefile +++ /dev/null @@ -1,161 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = a4 -BUILDDIR = ../web/notes/Theorie - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext qcm projets sinf1252 - -help: - @echo "Please use \`make <target>' where <target> is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/SINF1252.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/SINF1252.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/SINF1252" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/SINF1252" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -qcm: - @for dir in Exercices/QCM/S*; do make -C $${dir}; done - -projets: - @for dir in Projets/P*; do [ -e $${dir}/Makefile ] && make -C $${dir}; true; done - -sinf1252: qcm projets html latexpdf epub diff --git a/Theorie/MemoireVirtuelle/fig/addrvirtuelle.png b/Theorie/MemoireVirtuelle/fig/addrvirtuelle.png deleted file mode 100644 index 3e1bf004f0ad4d232e789f0118bf738a16851570..0000000000000000000000000000000000000000 Binary files a/Theorie/MemoireVirtuelle/fig/addrvirtuelle.png and /dev/null differ diff --git a/Theorie/MemoireVirtuelle/fig/entreeComplete.png b/Theorie/MemoireVirtuelle/fig/entreeComplete.png deleted file mode 100644 index a718146832069e2356efaba3df2cc1d37718a612..0000000000000000000000000000000000000000 Binary files a/Theorie/MemoireVirtuelle/fig/entreeComplete.png and /dev/null differ diff --git a/Theorie/MemoireVirtuelle/fig/entreeTable.png b/Theorie/MemoireVirtuelle/fig/entreeTable.png deleted file mode 100644 index 2898f018331909e08633f8839e77dcae0fe330d9..0000000000000000000000000000000000000000 Binary files a/Theorie/MemoireVirtuelle/fig/entreeTable.png and /dev/null differ diff --git a/Theorie/MemoireVirtuelle/fig/fichierMappe.png b/Theorie/MemoireVirtuelle/fig/fichierMappe.png deleted file mode 100644 index 447fc040acb1b526d93d160e702b6ba8adc8869c..0000000000000000000000000000000000000000 Binary files a/Theorie/MemoireVirtuelle/fig/fichierMappe.png and /dev/null differ diff --git a/Theorie/MemoireVirtuelle/fig/memoireVirtuelle.png b/Theorie/MemoireVirtuelle/fig/memoireVirtuelle.png deleted file mode 100644 index 3b919e6a48c938b70681e349233d0d9753dad975..0000000000000000000000000000000000000000 Binary files a/Theorie/MemoireVirtuelle/fig/memoireVirtuelle.png and /dev/null differ diff --git a/Theorie/MemoireVirtuelle/fig/mmu.png b/Theorie/MemoireVirtuelle/fig/mmu.png deleted file mode 100644 index aa90909ac847831fcdba17f8e0a15ef689a433eb..0000000000000000000000000000000000000000 Binary files a/Theorie/MemoireVirtuelle/fig/mmu.png and /dev/null differ diff --git a/Theorie/MemoireVirtuelle/fig/orgMemoire.png b/Theorie/MemoireVirtuelle/fig/orgMemoire.png deleted file mode 100644 index 119abecae2f05dfc6e4c1981bd1b5032dff13040..0000000000000000000000000000000000000000 Binary files a/Theorie/MemoireVirtuelle/fig/orgMemoire.png and /dev/null differ diff --git a/Theorie/MemoireVirtuelle/fig/proc-mem.png b/Theorie/MemoireVirtuelle/fig/proc-mem.png deleted file mode 100644 index 2188733d5b1395bff8ee28df5488b26dcfe768c9..0000000000000000000000000000000000000000 Binary files a/Theorie/MemoireVirtuelle/fig/proc-mem.png and /dev/null differ diff --git a/Theorie/MemoireVirtuelle/fig/tablePages.png b/Theorie/MemoireVirtuelle/fig/tablePages.png deleted file mode 100644 index a685a9344b54edc050b37399733a5f220be77715..0000000000000000000000000000000000000000 Binary files a/Theorie/MemoireVirtuelle/fig/tablePages.png and /dev/null differ diff --git a/Theorie/MemoireVirtuelle/fig/traduction.png b/Theorie/MemoireVirtuelle/fig/traduction.png deleted file mode 100644 index 3769ba5924aee8d299808e60c63fbd79b36f1666..0000000000000000000000000000000000000000 Binary files a/Theorie/MemoireVirtuelle/fig/traduction.png and /dev/null differ diff --git a/Theorie/MemoireVirtuelle/fig/vmem.png b/Theorie/MemoireVirtuelle/fig/vmem.png deleted file mode 100644 index ee08cbab68c1d917376ccf3d6c8a8438b14fd951..0000000000000000000000000000000000000000 Binary files a/Theorie/MemoireVirtuelle/fig/vmem.png and /dev/null differ diff --git a/Theorie/MemoireVirtuelle/src/Makefile b/Theorie/MemoireVirtuelle/src/Makefile deleted file mode 100644 index 050ec12c5746ecb9c6974b58bc5ec2f149dffe1c..0000000000000000000000000000000000000000 --- a/Theorie/MemoireVirtuelle/src/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# -# Makefile for source code -# -# Builds all .c files, assuming they are all independant and runs them -# to collect the output on stdout -# -# Automatically builds some of the examples to be included in the text -# - -GCC = gcc - -CFLAGS = -Wall -std=c99 -g -LDFLAGS = -pthread - -ASMFLAGS = -Wall -std=c99 -O0 -fverbose-asm -fno-stack-protector -m32 -S - -CFILES := $(patsubst %.c,%.exe,$(wildcard *.c)) -ASMFILES := $(patsubst %.c,%.s,$(wildcard *.c)) -OUTPUT := $(patsubst %.c,%.out,$(wildcard *.c)) - - -all: ${CFILES} ${OUTPUT} - -%.s: %.c - @echo compiling $< - $(GCC) $(ASMFLAGS) $< - -%.exe: %.c - @echo compiling $< - $(GCC) $(CFLAGS) -o $@ $< $(LDFLAGS) - -%.out: %.exe - rm -f $@ - @echo executing $< - ./$< >$@ - diff --git a/Theorie/MemoireVirtuelle/src/cp2.c b/Theorie/MemoireVirtuelle/src/cp2.c deleted file mode 100644 index 74668b902af529d9863b01e352f928243a0c13d8..0000000000000000000000000000000000000000 --- a/Theorie/MemoireVirtuelle/src/cp2.c +++ /dev/null @@ -1,91 +0,0 @@ -/************************************** - * cp2.c - * - * copie de fichier avec mmap - * - *************************************/ -///AAA -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> - -int main (int argc, char *argv[]) { - int file1, file2; - void *src, *dst; - struct stat file_stat; - char dummy=0; - - if (argc != 3) { - fprintf(stderr,"Usage : cp2 source dest\n"); - exit(EXIT_FAILURE); - } - // ouverture fichier source - if ((file1 = open (argv[1], O_RDONLY)) < 0) { - perror("open(source)"); - exit(EXIT_FAILURE); - } - - if (fstat (file1,&file_stat) < 0) { - perror("fstat"); - exit(EXIT_FAILURE); - } - // ouverture fichier destination - if ((file2 = open (argv[2], O_RDWR | O_CREAT | O_TRUNC, file_stat.st_mode)) < 0) { - perror("open(dest)"); - exit(EXIT_FAILURE); - } - - // le fichier destination doit avoir la même taille que le source - if (lseek (file2, file_stat.st_size - 1, SEEK_SET) == -1) { - perror("lseek"); - exit(EXIT_FAILURE); - } - - // écriture en fin de fichier - if (write (file2, &dummy, sizeof(char)) != 1) { - perror("write"); - exit(EXIT_FAILURE); - } - - // mmap fichier source - if ((src = mmap (NULL, file_stat.st_size, PROT_READ, MAP_SHARED, file1, 0)) == NULL) { - perror("mmap(src)"); - exit(EXIT_FAILURE); - } - - // mmap fichier destination - if ((dst = mmap (NULL, file_stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, file2, 0)) == NULL) { - perror("mmap(src)"); - exit(EXIT_FAILURE); - } - - // copie complète - memcpy (dst, src, file_stat.st_size); - - // libération mémoire - if(munmap(src,file_stat.st_size)<0) { - perror("munmap(src)"); - exit(EXIT_FAILURE); - } - - if(munmap(dst,file_stat.st_size)<0) { - perror("munmap(dst)"); - exit(EXIT_FAILURE); - } - // fermeture fichiers - if(close(file1)<0) { - perror("close(file1)"); - exit(EXIT_FAILURE); - } - - if(close(file2)<0) { - perror("close(file2)"); - exit(EXIT_FAILURE); - } - return(EXIT_SUCCESS); -} diff --git a/Theorie/MemoireVirtuelle/src/cp2.out b/Theorie/MemoireVirtuelle/src/cp2.out deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/Theorie/MemoireVirtuelle/src/mincore.c b/Theorie/MemoireVirtuelle/src/mincore.c deleted file mode 100644 index 875183a67959f1534de52f5d942b1dc0f1375d16..0000000000000000000000000000000000000000 --- a/Theorie/MemoireVirtuelle/src/mincore.c +++ /dev/null @@ -1,65 +0,0 @@ -/************************************** - * mincore.c - * - * Programme d'exemple d'utilisation de - * mincore - * - *************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <sys/mman.h> - -///AAA -#dfine _BSD_SOURCE - -#define SIZE 10*4096 - -int main(int argc, char *argv[]) { - - char *mincore_vec; - size_t page_size = getpagesize(); - size_t page_index; - char *mem; - - mem=(char *)malloc(SIZE*sizeof(char)); - if(mem==NULL) { - perror("malloc"); - exit(EXIT_FAILURE); - } - for(int i=0;i<SIZE/2;i++) { - *(mem+i)='A'; - } - - mincore_vec = calloc(sizeof(char), SIZE/page_size); - if(mincore_vec==NULL) { - perror("calloc"); - exit(EXIT_FAILURE); - } - if(mincore(mem, SIZE, mincore_vec)!=0) { - perror("mincore"); - exit(EXIT_FAILURE); - } - - for (page_index = 0; page_index < SIZE/page_size; page_index++) { - printf("%lu :", (unsigned long)page_index); - if (mincore_vec[page_index]&MINCORE_INCORE) { - printf(" incore"); - } - if (mincore_vec[page_index]&MINCORE_REFERENCED) { - printf(" referenced_by_us"); - } - if (mincore_vec[page_index]&MINCORE_MODIFIED) { - printf(" modified_by_us"); - } - printf("\n"); - } - free(mincore_vec); - free(mem); - return (EXIT_SUCCESS); -} - diff --git a/Theorie/MemoireVirtuelle/src/mincore.out b/Theorie/MemoireVirtuelle/src/mincore.out deleted file mode 100644 index 5d95bce9efd964fdbe80ce5c666b42da8e5b0d2f..0000000000000000000000000000000000000000 --- a/Theorie/MemoireVirtuelle/src/mincore.out +++ /dev/null @@ -1,10 +0,0 @@ -0 : incore referenced_by_us modified_by_us -1 : incore referenced_by_us modified_by_us -2 : incore referenced_by_us modified_by_us -3 : incore referenced_by_us modified_by_us -4 : incore referenced_by_us modified_by_us -5 : -6 : -7 : -8 : -9 : diff --git a/Theorie/MemoireVirtuelle/src/mmap.c b/Theorie/MemoireVirtuelle/src/mmap.c deleted file mode 100644 index 617ce051e7ebf5e94adcc57d1e8a6ca9ec84ce87..0000000000000000000000000000000000000000 --- a/Theorie/MemoireVirtuelle/src/mmap.c +++ /dev/null @@ -1,72 +0,0 @@ -/************************************** - * mmap.c - * - * Programme d'exemple d'utilisation de - * mincore - * - *************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <sys/mman.h> -#include <float.h> - -void create_file(int n, char *filename) { - int fd=open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); - if(fd==-1) { - perror("open"); - exit(EXIT_FAILURE); - } - for (int i=0;i<n;i++) { - float f=(float ) i; - if(write(fd,(void *)&f,sizeof(float)) <0) { - perror("write"); - exit(EXIT_FAILURE); - } - } - int err=close(fd); - if (err<0) { - perror("close"); - exit(EXIT_FAILURE); - } -} - -int main(int argc, char *argv[]) { - int fd; - struct stat file_stat; - void *file_mmap; - - create_file(100,"sinf1252.dat"); - - fd = open("sinf1252.dat",O_RDONLY); - if(fd<0) { - perror("open"); - exit(EXIT_FAILURE); - } - if (fstat(fd, &file_stat)<0) { - perror("fstat"); - exit(EXIT_FAILURE); - } - // fichier est un vecteur d'entiers - file_mmap = mmap((void *) 0, file_stat.st_size, PROT_READ, MAP_FILE, fd, 0); - if(file_mmap==NULL) { - perror("mmap"); - exit(EXIT_FAILURE); - } - printf("%p mmap\n",file_mmap); - float * vector=(float *) file_mmap; - float min=FLT_MAX; - for(int i=0;i<file_stat.st_size/sizeof(float);i++) { - if (*vector<min) { - min=*vector; - } - vector++; - } - munmap(file_mmap, file_stat.st_size); - close(fd); - return(EXIT_SUCCESS); -} diff --git a/Theorie/MemoireVirtuelle/src/mmap.out b/Theorie/MemoireVirtuelle/src/mmap.out deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/Theorie/MemoireVirtuelle/src/simple.c b/Theorie/MemoireVirtuelle/src/simple.c deleted file mode 100644 index 7288e77dd9521232050a7c504231e55f56ac5b25..0000000000000000000000000000000000000000 --- a/Theorie/MemoireVirtuelle/src/simple.c +++ /dev/null @@ -1,19 +0,0 @@ -/************************************** - * simple.c - * - * Programme d'exemple qui affiche simplement - * les adresses de argc, main et printf - * - *************************************/ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -///AAA -int main (int argc, char *argv[]) { - printf("[pid=%ld] Adresse de argc : %p\n",(long) getpid(),&argc); - printf("[pid=%ld] Adresse de main : %p\n",(long) getpid(),main); - printf("[pid-%ld] Adresse de printf : %p\n",(long) getpid(),printf); - sleep(20); - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/MemoireVirtuelle/src/svshm_xfr.h b/Theorie/MemoireVirtuelle/src/svshm_xfr.h deleted file mode 100644 index 36045951c0c767e39120e967c82894590f99ef02..0000000000000000000000000000000000000000 --- a/Theorie/MemoireVirtuelle/src/svshm_xfr.h +++ /dev/null @@ -1,43 +0,0 @@ -/**********************************************************************\ -* Copyright (C) Michael Kerrisk, 2010. * -* * -* This program is free software. You may use, modify, and redistribute * -* it under the terms of the GNU Affero General Public License as * -* published by the Free Software Foundation, either version 3 or (at * -* your option) any later version. This program is distributed without * -* any warranty. See the file COPYING for details. * -\**********************************************************************/ - -/* svshm_xfr.h - - Header file used by the svshm_xfr_reader.c and svshm_xfr_writer.c programs. -*/ -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/sem.h> -#include <sys/shm.h> -#include "binary_sems.h" /* Declares our binary semaphore functions */ -#include "tlpi_hdr.h" - -/* Hard-coded keys for IPC objects */ - -#define SHM_KEY 0x1234 /* Key for shared memory segment */ -#define SEM_KEY 0x5678 /* Key for semaphore set */ - -#define OBJ_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) - /* Permissions for our IPC objects */ - -/* Two semaphores are used to ensure exclusive, alternating access - to the shared memory segment */ - -#define WRITE_SEM 0 /* Writer has access to shared memory */ -#define READ_SEM 1 /* Reader has access to shared memory */ - -#ifndef BUF_SIZE /* Allow "cc -D" to override definition */ -#define BUF_SIZE 1024 /* Size of transfer buffer */ -#endif - -struct shmseg { /* Defines structure of shared memory segment */ - int cnt; /* Number of bytes used in 'buf' */ - char buf[BUF_SIZE]; /* Data being transferred */ -}; diff --git a/Theorie/MemoireVirtuelle/src/svshm_xfr_writer.c b/Theorie/MemoireVirtuelle/src/svshm_xfr_writer.c deleted file mode 100644 index 9aa92f6dafc64f1276ae4b10d112e153fdfd21b4..0000000000000000000000000000000000000000 --- a/Theorie/MemoireVirtuelle/src/svshm_xfr_writer.c +++ /dev/null @@ -1,98 +0,0 @@ -/**********************************************************************\ -* Copyright (C) Michael Kerrisk, 2010. * -* * -* This program is free software. You may use, modify, and redistribute * -* it under the terms of the GNU Affero General Public License as * -* published by the Free Software Foundation, either version 3 or (at * -* your option) any later version. This program is distributed without * -* any warranty. See the file COPYING for details. * -\**********************************************************************/ - -/* svshm_xfr_writer.c - - Read buffers of data data from standard input into a System V shared memory - segment from which it is copied by svshm_xfr_reader.c - - We use a pair of binary semaphores to ensure that the writer and reader have - exclusive, alternating access to the shared memory. (I.e., the writer writes - a block of text, then the reader reads, then the writer writes etc). This - ensures that each block of data is processed in turn by the writer and - reader. - - This program needs to be started before the reader process as it creates the - shared memory and semaphores used by both processes. - - Together, these two programs can be used to transfer a stream of data through - shared memory as follows: - - $ svshm_xfr_writer < infile & - $ svshm_xfr_reader > out_file -*/ -#include "semun.h" /* Definition of semun union */ -#include "svshm_xfr.h" - -int -main(int argc, char *argv[]) -{ - int semid, shmid, bytes, xfrs; - struct shmseg *shmp; - union semun dummy; - - /* Create set containing two semaphores; initialize so that - writer has first access to shared memory. */ - - semid = semget(SEM_KEY, 2, IPC_CREAT | OBJ_PERMS); - if (semid == -1) - errExit("semget"); - - if (initSemAvailable(semid, WRITE_SEM) == -1) - errExit("initSemAvailable"); - if (initSemInUse(semid, READ_SEM) == -1) - errExit("initSemInUse"); - - /* Create shared memory; attach at address chosen by system */ - - shmid = shmget(SHM_KEY, sizeof(struct shmseg), IPC_CREAT | OBJ_PERMS); - if (shmid == -1) - errExit("shmget"); - - shmp = shmat(shmid, NULL, 0); - if (shmp == (void *) -1) - errExit("shmat"); - - /* Transfer blocks of data from stdin to shared memory */ - - for (xfrs = 0, bytes = 0; ; xfrs++, bytes += shmp->cnt) { - if (reserveSem(semid, WRITE_SEM) == -1) /* Wait for our turn */ - errExit("reserveSem"); - - shmp->cnt = read(STDIN_FILENO, shmp->buf, BUF_SIZE); - if (shmp->cnt == -1) - errExit("read"); - - if (releaseSem(semid, READ_SEM) == -1) /* Give reader a turn */ - errExit("releaseSem"); - - /* Have we reached EOF? We test this after giving the reader - a turn so that it can see the 0 value in shmp->cnt. */ - - if (shmp->cnt == 0) - break; - } - - /* Wait until reader has let us have one more turn. We then know - reader has finished, and so we can delete the IPC objects. */ - - if (reserveSem(semid, WRITE_SEM) == -1) - errExit("reserveSem"); - - if (semctl(semid, 0, IPC_RMID, dummy) == -1) - errExit("semctl"); - if (shmdt(shmp) == -1) - errExit("shmdt"); - if (shmctl(shmid, IPC_RMID, 0) == -1) - errExit("shmctl"); - - fprintf(stderr, "Sent %d bytes (%d xfrs)\n", bytes, xfrs); - exit(EXIT_SUCCESS); -} diff --git a/Theorie/MemoireVirtuelle/vmem.rst b/Theorie/MemoireVirtuelle/vmem.rst deleted file mode 100644 index a30d860c1a95139c9899e88346a6747bf6d30ea6..0000000000000000000000000000000000000000 --- a/Theorie/MemoireVirtuelle/vmem.rst +++ /dev/null @@ -1,666 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. _vmem: - -La mémoire virtuelle -==================== - -Le modèle d'interaction entre le processeur et la mémoire que nous avons utilisé jusqu'à présent est le modèle traditionnel. Dans ce modèle, illustré sur la figure ci-dessous, la mémoire est divisée en octets. Chaque octet est identifié par une adresse encodée sur :math:`n` bits. Une telle mémoire peut donc contenir au maximum :math:`2^n` octets de données. Aujourd'hui, les processeurs utilisent généralement des adresses sur 32 ou 64 bits. Avec des adresses sur 32 bits, la mémoire peut stocker :math:`4.294.967.296` octets de données. Avec des adresses sur 64 bits, la capacité de stockage de la mémoire monte à :math:`18.446.744.073.709.551.616` octets. Si on trouve facilement aujourd'hui des mémoires avec une capacité de :math:`4.294.967.296` octets, il n'en existe pas encore qui sont capables de stocker :math:`18.446.744.073.709.551.616` et il faudra probablement quelques années avant que de telles capacités ne soient utilisables en pratique. - -.. figure:: /MemoireVirtuelle/fig/proc-mem.png - :align: center - :scale: 60 - - Modèle simple d'interaction entre le processeur et la mémoire - -Ce modèle correspond au fonctionnement de processeurs simples tels que ceux que l'on trouve sur des systèmes embarqués comme une machine à lessiver. Malheureusement, il ne permet pas d'expliquer et de comprendre le fonctionnement des ordinateurs actuels. Pour s'en convaincre, il suffit de réfléchir à quelques problèmes liés à l'utilisation de la mémoire sur un ordinateur fonctionnant sous Unix. - -Le premier problème est lié à l'organisation d'un processus en mémoire. Sous Unix, le bas de la mémoire est réservé au code, le milieu au heap et le haut au stack. Le modèle simple d'organisation de la mémoire ne permet pas facilement de comprendre comment un tel processus peut pouvoir utiliser la mémoire sur un processeur 64 bits qui est placé dans un ordinateur qui ne dispose que de 4 GBytes de mémoire. Avec une telle quantité de mémoire, le sommet de la pile devrait se trouver à une adresse proche de :math:`2^{32}` et non :math:`2^{64}`. - -Un deuxième problème est lié à l'utilisation de plusieurs processus simultanément en mémoire. Lorsque deux processus s'exécutent, ils utilisent nécessairement la même mémoire physique. Si un processus utilise l'adresse `x` et y place des instructions ou des données, cette adresse ne peut pas être utilisée par un autre processus. Physiquement, ces deux processus doivent utiliser des zones mémoires distinctes. Pourtant, le programme ci-dessous affiche les adresses de ``argc``, de la fonction ``main`` et de la fonction ``printf`` de la librairie standard puis effectue ``sleep(20);``. Lors de l'exécution de deux instances de ce programmes simultanément, on observe ceci sur la sortie standard. - -.. code-block:: console - - $ ./simple & - [pid=32955] Adresse de argc : 0x7fff5fbfe18c - [pid=32955] Adresse de main : 0x100000e28 - [pid-32955] Adresse de printf : 0x7fff8a524f3a - $ ./simple 2 3 4 - [pid=32956] Adresse de argc : 0x7fff5fbfe18c - [pid=32956] Adresse de main : 0x100000e28 - [pid-32956] Adresse de printf : 0x7fff8a524f3a - - -.. Manifestement, les deux programmes utilisent exactement les mêmes adresses en mémoire. Pourtant, ces deux programmes doivent nécessairement utiliser des zones mémoires distinctes pour pouvoir s'exécuter correctement. Sinon, les accès mémoire des deux processus seront en conflit. Ceci est possible grâce à l'utilisation de la :term:`mémoire virtuelle`. - - -.. Le :term:`Memory Management Unit` -.. --------------------------------- - - -Manifestement, les deux programmes utilisent exactement les mêmes adresses en mémoire. Pourtant, ces deux programmes doivent nécessairement utiliser des zones mémoires différentes pour pouvoir s'exécuter correctement. Ceci est possible grâce à l'utilisation de la :term:`mémoire virtuelle`. Avec la :term:`mémoire virtuelle`, deux types d'adresses sont utilisées sur le système : les *adresses virtuelles* et les *adresses réelles* ou *physiques*. Une :term:`adresse virtuelle` est une adresse qui est utilisée à l'intérieur d'un programme. Les adresses des variables ou des fonctions de notre programme d'exemple ci-dessus sont des adresses virtuelles. Une :term:`adresse physique` est l'adresse qui est utilisée par des puces de RAM pour les opérations d'écriture et de lecture. Ce sont les adresses physiques qui sont échangées sur le bus auquel la mémoire est connectée. Pour que les programmes puissent accéder aux instructions et données qui se trouvent en mémoire, il est nécessaire de pouvoir traduire les adresses virtuelles en adresses physiques. C'est le rôle du :term:`MMU` ou :term:`Memory Management Unit`. Historiquement, le :term:`MMU` était implémenté sous la forme d'un chip séparé qui était placé entre le processeur (qui utilisait alors des adresses virtuelles) et la mémoire (qui utilise elle toujours des adresses physiques). Aujourd'hui, le :term:`MMU` est directement intégré au processeur pour des raisons de performance, mais conceptuellement son rôle reste essentiel comme nous allons le voir. - -La mémoire virtuelle --------------------- - -.. Avec la :term:`mémoire virtuelle`, deux types d'adresses sont utilisées sur le système : les adresses virtuelles et les adresses réelles ou physiques. - -.. Une :term:`adresse virtuelle` est une adresse qui est utilisée à l'intérieur d'un programme. Les adresses des variables ou des fonctions de notre programme d'exemple ci-dessous sont des adresses virtuelles. Une :term:`adresse physique` est l'adresse qui utilisée au niveau des puces de mémoire RAM pour les opérations d'écriture et de lecture. Ce sont les adresses physiques qui sont échangées sur le bus auquel la mémoire est connectée. Pour que les programmes puissent accéder aux instructions et données qui se trouvent en mémoire, il est nécessaire de pouvoir traduire les adresses virtuelles en adresses physiques. C'est le rôle du :term:`MMU` ou :term:`Memory Management Unit`. Historiquement, le :term:`MMU` était implémenté sous la forme d'un chip séparé qui était placé entre le processeur (qui utilisait alors des adresses virtuelles) et la mémoire (qui utilise elle toujours des adresses physiques). Aujourd'hui, le :term:`MMU` est généralement intégré au processeur pour des raisons de performances, mais conceptuellement son rôle reste essentiel comme nous allons le voir. - - -Le rôle principal du :term:`MMU` est de traduire toute adresse virtuelle en une adresse physique. Avant d'expliquer comment le :term:`MMU` peut être implémenté en pratique, il est utile de passer en revue plusieurs avantages de l'utilisation des adresses virtuelles. - - -.. figure:: /MemoireVirtuelle/fig/mmu.png - :align: center - :scale: 60 - - `MMU` et `mémoire virtuelle` - - - -Un premier avantage de l'utilisation de la mémoire virtuelle est qu'elle permet de découpler les adresses virtuelles des adresses physiques. Celles-ci ne doivent pas nécessairement être encodées en utilisant le même nombre de bits. La longueur des adresses dépend généralement de l'architecture du processeur et de la taille des registres qu'il utilise. Une organisation possible de la mémoire virtuelle est d'utiliser des adresses virtuelles qui sont encodées sur autant de bits que les adresses physiques, mais ce n'est pas la seule. Il est tout à fait possible d'avoir un ordinateur sur lequel les adresses virtuelles sont plus longues que les adresses physiques. C'est le cas par exemple sur les ordinateurs bon marché qui utilisent une quantité réduite de mémoire RAM. Inversement, la mémoire virtuelle permet à un serveur d'utiliser des adresses physiques qui sont plus longues que les adresses virtuelles. Cela lui permet d'utiliser une capacité de mémoire plus importante que celle autorisée par l'architecture de son processeur. Dans ce cas, un processus ne peut pas utiliser plus de mémoire que l'espace d'adressage virtuel disponible. Mais ensemble, tous les processus fonctionnant sur l'ordinateur peuvent utiliser tout l'espace d'adressage physique disponible. - -Un deuxième avantage de la mémoire virtuelle est qu'elle permet, à condition de pouvoir réaliser une traduction spécifique à chaque processus, de partager efficacement la mémoire entre plusieurs processus tout en leur permettant d'utiliser les mêmes adresses virtuelles. C'est cette particularité de la mémoire virtuelle qui nous a permis dans l'exemple précédent d'avoir deux processus qui en apparence utilisent les mêmes adresses. En effectuant une traduction spécifique à chaque processus, le :term:`MMU` permet d'autres avantages qui sont encore plus intéressants. - -Le :term:`MMU` est capable d'effectuer des traductions d'adresses virtuelles qui sont spécifiques à chaque processus. Cela implique qu'en général la traduction de l'adresse `x` dans le processus `P1` ne donnera pas la même adresse physique que la traduction de l'adresse `x` dans le processus `P2`. Par contre, il est tout à fait possible que la traduction de l'adresse `w` (resp. `y`) dans le processus `P1` (resp. `P2`) donne l'adresse physique `z` dans les deux processus. Comme nous le verrons ultérieurement, cela permet à deux processus distincts de partager de la mémoire. Cette propriété est aussi à la base du fonctionnement des librairies partagées dans un système Unix. Dans notre exemple, la fonction ``printf`` qui est utilisée par les deux processus fait partie de la librairie standard. Celle-ci doit être chargée en mémoire lors de l'exécution de chacun des processus. Grâce à l'utilisation du :term:`MMU` et de la mémoire virtuelle, une seule copie physique de la librairie standard est chargée en mémoire et tous les processus qui y font appel utilisent les instructions se trouvant dans cette copie physique. Cela permet de réduire fortement la consommation de mémoire lorsque de nombreux processus s'exécutent simultanément, ce qui est souvent le cas sur un système Unix. - -Le dernier avantage de l'utilisation de la mémoire virtuelle est qu'il est possible de combiner ensemble la mémoire RAM et un ou des dispositifs de stockage tels que des disques durs ou des disques SSD pour constituer une mémoire virtuelle de plus grande capacité que la mémoire RAM disponible. Pour cela, il suffit, conceptuellement, que le :term:`MMU` soit capable de supporter deux types d'adresses physiques : les adresses physiques en RAM et les adresses physiques qui correspondent à des données stockées sur un dispositif de stockage [#fmmu]_. - -.. figure:: /MemoireVirtuelle/fig/vmem.png - :align: center - :scale: 60 - - Organisation de la `mémoire virtuelle` - -Cette possibilité de combiner la mémoire RAM et les dispositifs de stockage offre encore plus de possibilités. Comme nous le verrons, grâce à la mémoire virtuelle, un processus pourra accéder à des fichiers via des pointeurs et des écriture/lectures en mémoire. Le chargement d'un programme pourra s'effectuer en passant par la mémoire virtuelle de façon à charger uniquement les parties du programme qui sont nécessaires en mémoire. Nous verrons également qu'il existe plusieurs appels systèmes qui permettent à des processus de contrôler leur utilisation de la mémoire virtuelle. - -.. _fctvmem: - -Fonctionnement de la mémoire virtuelle --------------------------------------- - -Avant d'analyser comment la mémoire virtuelle peut être utilisée par les processus, il est important de bien comprendre son organisation et les principes de base de fonctionnement du :term:`MMU`. La mémoire virtuelle combine la mémoire RAM et les dispositifs de stockage. Comme la mémoire RAM et les dispositifs de stockage ont des caractéristiques fort différentes, il n'est pas trivial de les combiner pour donner l'illusion d'une mémoire virtuelle unique. - -Au niveau de l'adressage, la mémoire RAM permet d'adresser des octets et supporte des lectures et des écritures à n'importe quelle adresse. La mémoire RAM permet au processeur d'écrire et de lire des octets ou des mots à une position déterminée en mémoire. - -Un dispositif de stockage (disque dur, CD/DVD, ...) quant à lui contient un ensemble de secteurs. Chaque secteur peut être identifié par une adresse, comprenant par exemple le numéro du plateau, le numéro de la piste et le numéro du secteur sur la piste. Sur un tel dispositif, le secteur est l'unité de transfert de l'information. Cela implique que la moindre lecture/écriture sur un dispositif de stockage nécessite la lecture/écriture d'au moins 512 octets, même pour modifier un seul bit. Enfin, la dernière différence importante entre ces deux technologies est leur temps d'accès. Au niveau des mémoires RAM, les temps d'accès sont de l'ordre de quelques dizaines de nanosecondes. Pour un dispositif de stockage, les temps d'accès peuvent être de quelques dizaines de microsecondes pour un dispositif de type :term:`Solid State Drive` ou :term:`SSD` et jusqu'à quelques dizaines de millisecondes pour un disque dur. Les tableaux ci-dessous présentent les caractéristiques techniques de deux dispositifs de stockage [#fintel]_ [#fseagate]_ à titre d'exemple. - -La mémoire virtuelle utilise elle une unité intermédiaire qui est la :term:`page`. Une :term:`page` est une zone de mémoire contigüe. La taille des pages dépend de l'architecture du processeur et/ou du système d'exploitation utilisé. Une taille courante est de 4096 octets. - - -.. code-block:: c - - #include <unistd.h> - int sz = getpagesize(); - -Lorsqu'un programme est chargé en mémoire, par exemple lors de l'exécution de l'appel système `execve(2)`_, il est automatiquement découpé en pages. Grâce à la mémoire virtuelle, ces pages peuvent être stockée dans n'importe quelle zone de la mémoire RAM. La seule contrainte est que tous les octets qui font partie de la même page soient stockés à des adresses qui sont contigües. Cette contrainte permet de structurer les adresses virtuelles en deux parties comme représenté dans la figure ci-dessous. Une :term:`adresse virtuelle` est donc un ensemble de bits. Les bits de poids fort servent à identifier la :term:`page` dans laquelle une donnée est stockée. Les bits de poids faible (12 lorsque l'on utilise des pages de 4 KBytes) identifient la position de la donnée par rapport au début de la page. - - -.. figure:: /MemoireVirtuelle/fig/addrvirtuelle.png - :align: center - :scale: 60 - - Adresse virtuelle - -Grâce à cette organisation des adresses virtuelles, il est possible de construire un mécanisme efficace qui permet de traduire une adresse virtuelle en une adresse réelle. La première solution qui a été proposée pour réaliser cette traduction est d'utiliser une :term:`table des pages`. La :term:`table des pages` est stockée en mémoire RAM et contient une ligne pour chaque page appartenant à la mémoire virtuelle. A titre d'exemple, un système utilisant des adresses virtuelles de 32 bits et des pages de 4 KBytes contient :math:`2^{32-12}=2^{20}` pages. La table des pages de ce système contient donc :math:`2^{20}` lignes. Une ligne de la table des pages contient différentes informations que nous détaillerons par après. Les deux plus importantes sont : - - - le :term:`bit de validité` qui indique si la page est actuellement présente en mémoire RAM ou non - - l'adresse en mémoire RAM à laquelle la page est actuellement stockée (si elle est présente en mémoire RAM, sinon une information permettant de trouver la page sur un dispositif de stockage) - -La table des page est stockée en mémoire RAM comme un tableau en C. L'information correspondant à la page `0` est stockée à l'adresse de début de la table des pages. Cette adresse de début de la table des pages (``P``) est généralement stockée dans un registre du processeur pour être facilement accessible. Si une entrée [#fentree]_ de la table des pages est encodée en `n` bytes, l'information correspondant à la page `1` sera stockée à l'adresse ``P+n``, celle relative à la page `2` à l'adresse ``P+2*n``, ... Cette organisation permet d'accéder facilement à l'entrée de la table des pages relative à la page `z`. Il suffit en effet d'y accéder depuis l'adresse ``P+z*n``. - -Grâce à cette table des pages, il est possible de traduire directement les adresses virtuelles en adresses physiques. Cette traduction est représentée dans la figure ci-dessous. Pour réaliser une traduction, il faut tout d'abord extraire de l'adresse virtuelle le numéro de la page. Celui-ci se trouve dans les bits de poids fort de l'adresse virtuelle. Le numéro de la page sert d'index pour récupérer l'entrée correspondant à cette page dans la table des pages. Cette entrée contient l'adresse en mémoire RAM à laquelle la page débute. Pour finaliser la traduction de l'adresse virtuelle, il suffit de concaténer les bits de poids faible de l'adresse virtuelle avec l'adresse de la page en mémoire RAM. Cette concaténation donne l'adresse réelle à laquelle la donnée est stockée en mémoire RAM. Cette adresse physique permet au processeur d'accéder directement à la donnée en mémoire. - - -.. figure:: /MemoireVirtuelle/fig/traduction.png - :align: center - :scale: 60 - - Traduction d'adresses avec une table des pages - -La table des pages permet de traduire les adresses virtuelles en adresses physiques. Ce faisant, elle introduit un mécanisme d'indirection entre les adresses (virtuelles) qui sont utilisées par les programmes et les adresses (réelles) qui sont utilisées par le hardware. Ce mécanisme d'indirection a de nombreuses applications comme nous le verrons par la suite. - - -Un point important à mentionner concernant l'utilisation d'un mécanisme de traduction des adresses est qu'il permet de découpler le choix de la taille des adresses (virtuelles) utilisées par les programmes des contraintes matérielles qui sont liées directement aux mémoires RAM utilisées. En pratique, il est très possible d'avoir des systèmes informatiques dans lesquels les adresses virtuelles sont plus longues, plus courtes ou ont la même longueur que les adresses physiques. Sur un ordinateur 32 bits actuel équipé de 4 GBytes de mémoire, il est naturel d'utiliser des adresses virtuelles de 32 bits et des adresses physiques de 32 bits également pour pouvoir accéder à l'ensemble de la mémoire. Dans ce cas, la mémoire virtuelle permet d'accéder à toute la mémoire physique. Aujourd'hui, il existe des serveurs 64 bits. Ceux-ci utilisent des adresses virtuelles de 64 bits, mais aucun ordinateur ne contient :term:`2^64` bytes de mémoire. Par exemple, un serveur disposant de 128 GBytes de mémoire physique pourrait se contenter d'utiliser des adresses physiques de 37 bits. Dans ce cas, la mémoire virtuelle donne l'illusion qu'il est possible d'accéder à plus de mémoire que celle qui est réellement disponible. D'un autre côté, il est aussi possible de construire des serveurs qui utilisent des adresses virtuelles de 32 bits, mais disposent de plus de 4 GBytes de mémoire RAM. Dans ce cas, les adresses physiques pourront être plus longues que les adresses réelles. Quelles que soient les longueurs respectives des adresses virtuelles et physiques, la table des pages, sous le contrôle du système d'exploitation, permettra de réaliser efficacement les traductions entre les adresses virtuelles et les adresses physiques. - -Pour bien comprendre la traduction des adresses virtuelles en utilisant la table des pages, considérons un système imaginaire qui utilise des adresses virtuelles encodées sur 7 bits et des adresses physiques qui sont elles encodées sur 6 bits. La table des pages correspondante est reprise dans le tableau ci-dessous. Comme dans la figure précédente, la ligne du bas du tableau est relative à la page `0`. - -======== ======= -Validité Adresse -======== ======= -true 00 -false - -true 11 -false - -false - -false - -true 01 -true 10 -======== ======= - -Cette mémoire virtuelle contient quatre pages. La première couvre les adresses physiques allant de ``000000`` à ``001111``, la seconde de ``010000`` à ``011111``, la troisième de ``100000`` à ``101111`` et la dernière de ``110000`` à ``111111``. Les adresses virtuelles elles vont de ``0000000`` à ``1111111``. La traduction s'effectue sur base de la table des pages. Ainsi, l'adresse ``1010001`` correspond à l'octet ``0001`` dans la page virtuelle ``101``. Sur base de la table des pages, cette page se trouve en mémoire RAM (son bit de validité est vrai) et elle démarre à l'adresse ``110000``. L'adresse virtuelle ``1010001`` est donc traduite en l'adresse réelle ``110001``. L'adresse virtuelle ``0110111`` correspond elle à une page qui n'est pas actuellement en mémoire RAM puisque le bit de validité correspondant à la page ``011`` est faux. - -Si on analyse la table des pages ci-dessus, on peut remarquer que la page contenant les adresses virtuelles les plus hautes se trouve dans la zone mémoire avec les adresses physiques les plus basses. Inversement, la page qui est en mémoire RAM à l'adresse la plus élevée correspond à des adresses virtuelles qui se trouvent au milieu de l'espace d'adressage. Ce découplage entre l'adresse virtuelle et la localisation physique de la page en mémoire est un des avantages importants de la mémoire virtuelle. - -La mémoire virtuelle a aussi un rôle important à jouer lorsque plusieurs processus s'exécutent simultanément. -Comme indiqué ci-dessus, l'adresse de la table des pages est stockée dans un des registre du processeur. L'utilisation de ce registre permet d'avoir une table des pages pour chaque processus. Pour cela, il suffit qu'une zone de mémoire RAM soit réservée pour chaque processus et que le système d'exploitation y stocke la table des pages du processus. Lors d'un changement de contexte, le système d'exploitation modifie le registre de table des pages de façon à ce qu'il pointe vers la table des pages du processus qui s'exécute. Ce mécanisme est particulièrement utile et efficace. - -A titre d'exemple, considérons un système imaginaire utilisant des adresses virtuelles sur 6 bits et des adresses physiques sur 8 bits. Deux processus s'exécutent sur ce système et ils utilisent chacun trois pages, deux pages dans le bas de l'espace d'adressage virtuel qui correspondent à leur segment de code et une page dans le haut de l'espace d'adressage virtuel qui correspond à leur pile. Le premier tableau ci-dessous présente la table des pages du processus ``P1``. - -======== ======= -Validité Adresse -======== ======= -true 0011 -false - -true 1001 -true 1000 -======== ======= - -Le processus ``P2`` a lui aussi sa table des pages. Celle-ci pointe vers des adresses physiques qui sont différentes de celle utilisées par le processus ``P1``. L'utilisation d'une table des pages par processus permet à deux processus distincts d'utiliser les mêmes adresses virtuelles. - -======== ======= -Validité Adresse -======== ======= -true 0000 -false - -true 1111 -true 1110 -======== ======= - -Lorsque le processus ``P1`` s'exécute, c'est sa table des pages qui est utilisée par le processeur pour la traduction des adresses virtuelles en adresses physiques. Ainsi, l'adresse ``011101`` est traduite en l'adresse ``10011101``. Par contre, lorsque le processus ``P2`` s'exécuté, cette adresse ``011101`` est traduite grâce à la table des pages de ce processus en l'adresse ``11111101``. - -.. note:: Performance de la mémoire virtuelle - - Grâce à son mécanisme d'indirection entre les adresses virtuelles et les adresses physiques, la mémoire virtuelle permet de nombreuses applications comme nous le verrons dans les sections qui suivent. Cependant, la mémoire virtuelle peut avoir un impact important au niveau des performances des accès à une donnée en mémoire. Pour cela, il est intéressant d'analyser en détails ce qu'il se passe lors de chaque accès à la mémoire. Pour accéder à une donnée en mémoire, le :term:`MMU` doit d'abord consulter la table des pages pour traduire l'adresse virtuelle en une adresse physique correspondante. Ce n'est qu'après avoir obtenu cette adresse physique que le processeur peut effectuer l'accès à la mémoire RAM. En pratique, l'utilisation d'une table des pages a comme conséquence de doubler le temps d'accès à une donnée en mémoire. Lorsque la mémoire virtuelle a été inventée, ce doublement du temps d'accès à la mémoire n'était pas une limitation car les mémoires RAM étaient nettement plus rapides que les processeurs. Aujourd'hui, la situation est complètement inversée puisque les processeurs sont déjà fortement ralentis par les temps d'accès à la mémoire RAM. Doubler ce temps d'accès aurait un impact négatif sur les performances des processeurs. Pour faire face à ce problème, les processeurs actuels disposent tous d'un :term:`Translation Lookaside Buffer` (:term:`TLB`). Ce :term:`TLB` est en fait une sorte de :term:`mémoire cache` qui permet de stocker dans une mémoire rapide se trouvant sur le processeur certaines lignes de la :term:`table des pages`. Les détails de gestion du :term:`TLB` sortent du cadre de ce cours [HennessyPatterson]_. Grâce à l'utilisation du :term:`TLB`, la plupart des traductions des adresses virtuelles en adresses physique peuvent être obtenus sans devoir directement consulter la table des pages. - - -La table des pages d'un processus contrôle les adresses physiques auxquelles le processus a accès. Pour garantir la sécurité d'un système informatique, il faut bien entendu éviter qu'un processus ne puisse modifier lui-même et sans contrôle sa table des pages. Toutes les manipulations de la table des pages ou du registre de table des pages se font sous le contrôle du système d'exploitation. La modification du registre de table des pages est une opération privilégiée qui ne peut être exécutée que par le système d'exploitation. - -En termes de sécurité, une entrée de la table des pages contient également des bits de permission qui sont contrôlés par le système d'exploitation et spécifient quelles opérations peuvent être effectuées sur chaque page. Une entrée de la table des pages contient trois bits de permissions : - - - `R` bit. Ce bit indique si le processus peut accéder en lecture à la page se trouvant en mémoire physique. - - `W` bit. Ce bit indique si le processus peut modifier le contenu de la page se trouvant en mémoire physique - - `X` bit. Ce bit indique si la page contient des instructions qui peuvent être exécutées par le processeur ou des données. - -Ces bits de protection sont généralement fixés par le système d'exploitation. Par exemple, le segment code qui ne contient que des instructions à exécuter pourra être stocké dans des pages avec les bits `R` et `X` mais pas le bit `W` pour éviter que le processus ne modifie les instructions qu'il exécute. Le stack par contre sera placé dans des pages avec les bits `R` et `W` mais pas le bit `X`. Cette technique est utilisée dans les systèmes d'exploitation récents pour éviter qu'un problème de buffer overflow sur le stack ne conduise à l'exécution d'instructions qui ne font pas partie du processus. Le heap peut utiliser les mêmes bits de protection. Enfin, les pages qui n'ont pas été allouées au processus, notamment celles se trouvant entre le heap et le stack auront toutes leurs bits de protection mis à faux. Cela permet au processeur de détecter les accès à de la mémoire qui n'a pas été allouée au processus. Un tel accès provoquera la génération d'une `segmentation fault` et l'envoi du signal correspondant. - -Même si ces bits de protection sont contrôlés par le système d'exploitation, il est parfois utile à un processus de modifier les bits de permissions qui sont associés à certaines de ses pages. Cela peut se faire via l'appel système `mprotect(2)`_. - -.. code-block:: c - - #include <sys/mman.h> - - int mprotect(const void *addr, size_t len, int prot); - -Cet appel système prend trois arguments. Le premier est un pointeur vers le début de la zone mémoire dont il faut modifier les bits de protection. Le second est la longueur de la zone mémoire concernée et le dernier la protection souhaitée. Celle-ci est spécifiée en utilisant les constantes ``PROT_NONE``, ``PROT_READ``, ``PROT_WRITE`` et ``PROT_EXEC`` qui peuvent être combinées en utilisant une disjonction logique. La protection demandée ne peut pas être plus libérale que la protection qui est déjà fixée par le système d'exploitation. Dans ce cas, le système d'exploitation génère un signal ``SIGSEGV``. - - -.. todo:: l'ordre de présentaiton n'est pas le plus appropriée. il faudrait d'abord commencer par expliquer l'utilisation du disque avec des partitions de swap et les stratégies de remplacement de pages et ensuite arriver avec mmap, ce sera plus naturel - -.. _stockage: - -Utilisation des dispositifs de stockage ---------------------------------------- - -La mémoire virtuelle permet non seulement à des pages d'un processus d'être placées à différents endroits de la mémoire, mais aussi elle permet de combiner la mémoire RAM et les dispositifs de stockage de façon transparente pour les processus. - -.. La section précédente a montré qu'il était possible de mettre en correspondance des fichiers ou des portions de fichiers avec des zones de mémoires dans un processus. En pratique, les interactions entre les dispositifs de stockage et la mémoire sont encore plus fortes que cela puisque - -Une partie des pages qui composent la mémoire virtuelle peut être stockée sur un dispositif de stockage (disque dur, SSD, ...). En pratique, la mémoire RAM peut jouer le rôle d'une sorte de mémoire cache pour la mémoire virtuelle. Les pages qui sont le plus fréquemment utilisées sont placées en mémoire RAM par le système d'exploitation. Les pages les moins utilisées sont quant à elles placées sur un dispositif de stockage et ramenées en mémoire RAM lorsqu'elles sont utilisées par le processeur. - -Pour bien comprendre cette utilisation de la mémoire virtuelle, il nous faut revenir à la table des pages. Celle-ci comprend autant d'entrées qu'il y a de pages dans l'espace d'adressage d'un processus. Nous avons vu qu'une entrée de cette table pouvait être structurée comme dans la figure ci-dessous. - -.. figure:: /MemoireVirtuelle/fig/entreeTable.png - :align: center - :scale: 60 - - Entrée de la table des pages - -Le bit de validité indique si la page est présente en mémoire RAM ou non. Lorsque la page est présente en mémoire RAM, les bits de poids faible de l'entrée de la table des pages contiennent l'adresse physique de la page en mémoire RAM. Lorsque le bit de validité a comme valeur `faux`, cela signifie que la page n'existe pas (elle n'a jamais été créée) ou qu'elle est actuellement stockée sur un dispositif de stockage. Si la page n'existe pas, aucun de ses bits de permission n'aura comme valeur `vrai` et tout accès à cette page provoquera une `segmentation fault`. Si par contre la page existe mais se trouve sur un dispositif de stockage, alors l'information de localisation pointera vers une structure de données qui est maintenue par le système d'exploitation et contient la localisation physique de la donnée sur un dispositif de stockage. - -Schématiquement, ces informations de localisation des pages peuvent être de deux types. Lorsqu'un dispositif de stockage, ou une partition d'un tel dispositif, est dédié au stockage de pages de la mémoire virtuelle, alors la localisation d'une page est composée de l'identifiant du dispositif et du numéro du secteur sur le dispositif. Ce sera le cas lorsque par exemple une :term:`partition de swap` est utilisée. Sous Linux, le fichier ``/proc/swaps`` contient la liste des partitions de swap qui sont utilisées pour stocker les pages de la mémoire virtuelle avec leur type, leur taille et leur utilisation. Une telle partition de swap peut être créée avec l'utilitaire `mkswap(8)`_. Elle est activée en exécutant la commande `swapon(8)`_. Celle-ci est généralement lancée automatiquement lors du démarrage du système. - - -.. code-block:: console - - $ cat /proc/swaps - Filename Type Size Used Priority - /dev/sda3 partition 8193140 444948 -1 - -Outre les partitions de swap, il est également possible de stocker des pages de la mémoire virtuelle dans des fichiers. Dans ce cas, la localisation d'une page comprend le dispositif, l':term:`inode` du fichier et l'offset à partir duquel la page est accessible dans le fichier. En pratique, les partitions de swap sont un peu plus rapides que les fichiers de swap car les secteurs qui composent une telle partition sont contigus, ce qui n'est pas toujours le cas avec un fichier de swap. D'un autre côté, il est plus facile d'ajouter ou de retirer des fichiers de swap que des partitions de swap sur un dispositif de stockage. En pratique, les deux techniques peuvent être utilisées. - -.. todo:: change -.. Comme nous l'avons vu dans la section précédente, il est également possible avec l'appel système `mmap(2)`_ de faire correspondre une page en mémoire avec des données se trouvant dans un fichier sur un dispositif de stockage. Dans ce cas, la localisation de la page est spécifiée avec l'identifiant du dispositif, l'inode du fichier et la position du premier octet de la page à l'intérieur de ce fichier. `mmap(2)`_ utilise donc la même technique que celle utilisée par les fichiers de swap. - -A ce stade, il est utile d'analyser à nouveau le fonctionnement de la mémoire virtuelle. En toute généralité, celle-ci est découpée en pages et comprend une mémoire RAM et un ou plusieurs dispositifs de stockage. Pour simplifier la présentation, nous supposons qu'un seul disque dur est utilisé. - -.. figure:: /MemoireVirtuelle/fig/memoireVirtuelle.png - :align: center - :scale: 60 - - La mémoire virtuelle - - -Les processus utilisent des adresses virtuelles pour représenter les positions des données et des instructions en mémoire virtuelles. Ces adresses virtuelles sont donc utilisées par le CPU chaque fois qu'il doit charger ou sauvegarder une donnée ou une instruction en mémoire. Comme nous l'avons vu, le :term:`MMU` permet de traduire les adresses virtuelles en adresses réelles. Pour des raisons de performance, le :term:`MMU` est intégré directement sur le processeur et il comprend un :term:`TLB` qui sert de cache pour les entrées de la table des pages du processus qui est en train de s'exécuter. - -Considérons une opération de lecture faite par le CPU. Pour réaliser cette opération, le CPU fournit l'adresse virtuelle au :term:`MMU`. Celui-ci va consulter le :term:`TLB` pour traduire l'adresse virtuelle demandée. Cette traduction peut nécessiter différentes opérations. Supposons que l'entrée de la table des pages demandées se trouve dans le :term:`TLB`. - - - Si le :term:`bit de validité` de la page est `vrai`, la page demandée se situe en mémoire RAM. Dans ce cas, le :term:`MMU` vérifie via les bits de permissions si l'accès demandé (dans ce cas une lecture, mais un raisonnement similaire est valable pour une écriture ou le chargement d'une instruction) est valide. - - - Si l'accès est autorisé, le :term:`MMU` retourne l'adresse réelle et le processeur accède aux données. - - Si l'accès n'est pas autorisé, le processeur génère une interruption. Le processus ayant tenté d'accéder à une zone de mémoire ne faisant pas partie de son espace d'adressage virtuel, c'est au système d'exploitation de réagir. Celui-ci enverra un signal segmentation fault, ``SIGSEGV``, au processus qui a tenté cet accès. - - - Si le :term:`bit de validité` de la page est `faux`, la page demandée ne se trouve pas en mémoire RAM. Deux cas de figure sont possibles : - - - les bits de permission ne permettent aucun accès à la page. Dans ce cas, la page n'existe pas et le :term:`MMU` va générer une interruption qui va provoquer l'exécution d'une routine de traitement d'interruption du système d'exploitation. Lors du traitement de cette opération, le noyau va envoyer un signal segmentation fault au processus qui a tenté cet accès. - - - les bits de permission permettent l'accès à la page. On parle dans ce cas de :term:`page fault`, c'est-à -dire qu'une page nécessaire à l'exécution du processus n'est pas disponible en mémoire RAM. Vu les temps d'accès et la complexité d'accéder à une page sur un disque dur (via une partition, un fichier de swap ou un fichier normal), le :term:`MMU` ne peut pas accéder directement à la donnée sur le disque dur. Le :term:`MMU` va donc générer une interruption qui va forcer l'exécution d'une routine de traitement d'interruption par le noyau. Cette routine va identifier la page manquante et préparer son transfert du disque dur vers la mémoire. Ce transfert peut durer plusieurs dizaines de millisecondes, ce qui est un temps très long par rapport à l'exécution d'instructions par le processeur. Tant que cette page n'est pas disponible en mémoire RAM, le processus ne peut pas continuer son exécution. Il passe dans l'état bloqué et le noyau effectue un changement de contexte pour exécuter un autre processus. Lorsque la page manquante aura été rapatriée depuis le disque dur en mémoire RAM, le noyau pourra relancer le processus qu'il avait bloqué afin de retenter l'accès mémoire qui vient d'échouer. - -Durant son exécution, un système doit pouvoir gérer des pages qui se trouvent en mémoire RAM et des pages qui sont stockées sur le disque dur. Lorsque la mémoire RAM est entièrement remplies de pages, il peut être nécessaire d'y libérer de l'espace mémoire en déplaçant des pages vers un des dispositifs de stockage. C'est le rôle des algorithmes de remplacement de pages. - -.. _remplacement: - -Stratégies de remplacements de pages ------------------------------------- - -C'est le système d'exploitation qui prend en charge les transferts de pages entre les dispositifs de stockage et la mémoire. Tant que la mémoire RAM n'est pas remplie, ces transferts sont simples, il suffit de ramener une ou plusieurs pages du dispositif de stockage vers la mémoire RAM. En général, le système d'exploitation cherchera à exploiter le principe de localité lors de ces transferts. Lorsqu'une page manque en mémoire RAM, le noyau programmera le chargement de cette page, mais aussi d'autres pages du même processus ayant des adresses proches. - -Lorsque la mémoire RAM est remplie et qu'il faut ramener une page depuis un dispositif de stockage, le problème est plus délicat. Pour pouvoir charger cette nouvelle page en mémoire RAM, le système d'exploitation doit libérer de la mémoire. Pour cela, il doit implémenter une :term:`stratégie de remplacement de pages` en mémoire. Cette stratégie définit quelle page doit être préférentiellement retirée de la mémoire RAM et placée sur le dispositif de stockage. Différentes stratégies sont possibles. Elles résultent en général d'un compromis entre la quantité d'information de contrôle qui est stockée dans la table des pages et les performances de la stratégie de remplacement des pages. - -Une première stratégie de remplacement de pages pourrait être de sauvegarder les identifiants des pages dans une :term:`file FIFO`. Chaque fois qu'une page est créée par le noyau, son identifiant est placé à la fin de la :term:`file FIFO`. Lorsque la mémoire est pleine et qu'une page doit être retirée de la mémoire RAM, le noyau pourrait choisir la page dont l'identifiant se trouve en tête de la :term:`file FIFO`. Cette stratégie a l'avantage d'être simple à implémenter, mais remettre sur disque la page la plus anciennement créée n'est pas toujours la solution la plus efficace du point de vue des performances. En effet, cette page peut très bien être une des pages les plus utilisées par le processeur. Si elle est remise sur le disque, elle risque de devoir être récupérée peu de temps après. - -Au niveau des performances, la meilleure stratégie de remplacement de pages serait de sauvegarder sur le disque dur les pages qui seront utilisées par le processeur d'ici le plus de temps possible. Malheureusement, cette stratégie nécessite de prévoir le futur, une fonctionnalité qui n'existe pas dans les systèmes d'exploitation actuels... Une solution alternative serait de comptabiliser les accès aux différentes pages et de sauvegarder sur disque les pages qui ont été les moins utilisées. Cette solution est séduisante du point de vue théorique car en disposant de statistiques sur l'utilisation des pages, le système d'exploitation devrait pouvoir être capable de mieux prédire les pages qui seront nécessaires dans le futur et les conserver en mémoire RAM. Du point de vue de l'implémentation par contre, cette solution est loin d'être réaliste. En effet, pour maintenir un compteur du nombre d'accès à une page, il faut consommer de la mémoire supplémentaire dans chaque entrée de la table des pages. Mais il faut aussi que le :term:`TLB` puisse incrémenter ce compteur lors de chaque accès à une de ces entrées. Cela augmente inutilement la complexité du :term:`TLB`. - -Stocker dans le :term:`TLB` l'instant du dernier accès à une page de façon à pouvoir déterminer quelles sont les pages auxquelles le système a accédé depuis le plus longtemps est une autre solution séduisante d'un point de vue théorique. Du point de vue de l'implémentation, c'est loin d'être facilement réalisable. Tout d'abord, pour que cet instant soit utile, il faut probablement disposer d'une résolution d'une milliseconde voire mieux. Une telle résolution consommera au moins quelques dizaines de bits dans chaque entrée de la table des pages. En outre, le :term:`TLB` devra pouvoir mettre à jour cette information lors de chaque accès. - -Face à ces difficultés d'implémentation, la plupart des stratégies de remplacement de pages s'appuient sur deux bits qui se trouvent dans chaque entrée de la table des pages [HennessyPatterson]_. Il est relativement facile de supporter ces deux bits dans une implémentation du :term:`TLB` et leur présence n'augmente pas de façon significative la mémoire occupée par une entrée de la table des pages. - - -.. figure:: /MemoireVirtuelle/fig/entreeComplete.png - :align: center - :scale: 60 - - Une entrée complète de la table des pages - - -Outre les bits de validité et de permission, une entrée de la table des pages contient les bits de contrôle suivants : - - - le :term:`bit de référence` est mis à vrai par le :term:`MMU` dans le :term:`TLB` à chaque accès à une donnée se trouvant dans la page correspondante, que cet accès soit en lecture ou en écriture - - le :term:`bit de modification` ou :term:`dirty bit` est mis à vrai par le :term:`MMU` chaque fois qu'une opération d'écriture est réalisée dans cette page. - -Ces deux bits sont mis à jour par le :term:`MMU` à l'intérieur du :term:`TLB`. Lorsqu'une entrée de la table des pages est retirée du :term:`TLB` pour être remise en mémoire, que ce soit à l'occasion d'un changement de contexte ou parce que le :term:`TLB` est plein, les valeurs de ces deux bits sont recopiées dans l'entrée correspondante de la table des pages. En somme, le :term:`TLB` fonctionne comme une cache en :term:`write-back` pour ces deux bits de contrôle. - -Les bits de référence et de modification sur utilisés par la plupart des algorithmes de remplacement de pages. Le bit de référence est généralement utilisé par le système d'exploitation pour déterminer quelles sont les pages auxquelles un processus accède actuellement. Pour cela, le noyau va régulièrement remettre à `faux` les bits de validité des entrées des tables de pages. Lorsque une entrée de la table des pages est chargée dans le :term:`TLB` suite à un :term:`page fault`, son :term:`bit de référence` est mis à `vrai`. Il en va de même chaque fois que le processeur accède à une donnée dans cette page. - -La stratégie de remplacement utilisant une :term:`file FIFO` que nous avons mentionné précédemment peut être améliorée en utilisant le :term:`bit de référence`. Plutôt que de remettre sur disque la page dont l'identifiant est en tête de la file il suffit de regarder son :term:`bit de référence`. Si celui-ci a la valeur `faux`, la page n'a pas été utilisée récemment et peut donc être retirée de la mémoire RAM. Sinon, le :term:`bit de référence` est remis à `faux` et l'identifiant de la page est replacé en fin de file. L'algorithme de remplacement de page passe ensuite à la page suivante dans la file et continue jusqu'à trouver suffisamment de pages ayant leur bit de référence mis à `faux`. - -Une autre stratégie est de combiner le :term:`bit de référence` et le :term:`dirty bit`. Dans ce cas, le noyau du système d'exploitation va régulièrement remettre à la valeur `faux` tous les bits de référence (par exemple toutes les secondes). Lorsque la mémoire RAM est pleine et qu'il faut libérer de l'espace mémoire pour charger de nouvelles pages, l'algorithme de remplacement de pages va grouper les pages en mémoire en quatre classes. - - 1. La première classe comprend les pages dont le :term:`bit de référence` et le :term:`bit de modification` ont comme valeur `faux`. Ces pages n'ont pas été utilisées récemment et sont identiques à la version qui est déjà stockée sur disque. Elles peuvent donc être retirée de la mémoire RAM sans nécessiter de transfert vers le disque. - - 2. La deuxième classe comprend les pages dont le :term:`bit de référence` a comme valeur `faux` mais le :term:`bit de modification` a comme valeur `vrai`. Ces pages n'ont pas été utilisées récemment, mais doivent être transférées vers le disque avant d'être retirées de la mémoire RAM. - - 3. La troisième classe comprend les pages dont le :term:`bit de référence` a comme valeur `vrai` mais le :term:`bit de modification` a comme valeur `faux`. Ces pages ont été utilisées récemment mais peuvent être retirées de la mémoire RAM sans nécessiter de transfert vers le disque. - - 4. La dernière classe comprend les pages dont les bits de référence et de modification ont comme valeur `vrai`. Ces pages ont étés utilisées récemment et il faut les transférer vers le disque avant de les retirer de la mémoire RAM. - -Si l'algorithme de remplacement de pages doit retirer des pages de la mémoire RAM, il commencera par retirer des pages de la première classe, et ensuite de la deuxième, ... - -Des algorithmes plus performants ont été proposés et sont utilisés en pratique. Une description détaillée de ces algorithmes sort du cadre de ce cours d'introduction mais peut être trouvée dans un livre consacré aux systèmes d'exploitation comme [Tanenbaum+2009]_. - -.. note:: Swapping et pagination - - Grâce à l'utilisation de la mémoire virtuelle qui est découpée en pages, il est possible de stocker certaines parties de processus sur un dispositif de stockage plutôt qu'en mémoire RAM. Cette technique de :term:`pagination` permet au système d'exploitation de gérer efficacement la mémoire et de réserver la mémoire RAM aux parties de processus qui sont nécessaires à leur exécution. Grâce à la découpe en pages, il est possible de transférer de petites parties d'un processus temporairement sur un dispositif de stockage. Aujourd'hui, la :term:`pagination` est très largement utilisée, mais ce n'est pas la seule technique qui permette de placer temporairement l'espace mémoire utilisé par un processus sur disque. Le :term:`swapping` est une technique plus ancienne mais qui est encore utilisée en pratique. Le :term:`swapping` est plus radical que la :term:`pagination` puisque cette technique permet au noyau de sauvegarder sur disque la quasi totalité de la mémoire utilisée par un processus. Le noyau fera appel au swapping lorsque la mémoire RAM est surchargée et pour des processus qui sont depuis longtemps bloqués par exemple en attente d'un opération d'entrée/sortie. Lorsque le noyau manque de mémoire, il est plus efficace de sauvegarder un processus complet plutôt que de transférer des pages de différents processus. Un tel processus swappé sera réactivé et ramené en mémoire par le noyau lorsqu'il repassera dans l'état `Running`, par exemple suite à la réussite d'une opération d'entrée/sortie. - - - -Utilisations de la mémoire virtuelle ------------------------------------- - -Comme nous l'avons vu précédemment, la mémoire virtuelle est découpée en pages et elle permet de découpler les adresses utilisées par les processus des adresses physiques. Grâce à la table des pages, il est possible de placer les pages d'un processus à n'importe quel endroit de la mémoire RAM. Mais la mémoire virtuelle permet également d'interagir avec les dispositifs de stockage comme si ils faisaient partie de la mémoire accessible au processus. - - -.. _mmap: - -Fichiers mappés en mémoire --------------------------- - -Lorsqu'un processus Unix veut lire ou écrire des données dans un fichier, il utilise en général les appels systèmes `open(2)`_, `read(2)`_, `write(2)`_ et `close(2)`_ directement ou à travers une librairie de plus haut niveau comme la libraire d'entrées/sorties standard. Ce n'est pas la seule façon pour accéder à des données sur un dispositif de stockage. Grâce à la mémoire virtuelle, il est possible de placer le contenu d'un fichier ou d'une partie de fichier dans une zone de la mémoire du processus. Cette opération peut être effectuée en utilisant l'appel système `mmap(2)`_. Cet appel système permet de rendre des pages d'un fichier accessibles à travers la table des pages du processus comme illustré dans la figure ci-dessous. - - -.. figure:: /MemoireVirtuelle/fig/fichierMappe.png - :align: center - :scale: 60 - - Fichiers mappés en mémoire - - - -.. code-block:: c - - #include <sys/mman.h> - - void *mmap(void *addr, size_t length, int prot, int flags, - int fd, off_t offset); - - -L'appel système `mmap(2)`_ prend six arguments, c'est un des appels systèmes qui utilise le plus d'arguments. Il permet de rendre accessible une portion d'un fichier via la mémoire d'un processus. Le cinquième argument est le descripteur du fichier qui doit être mappé. Celui-ci doit avoir été préalablement ouvert avec l'appel système `open(2)`_. Le sixième argument spécifie l'offset à partir duquel le fichier doit être mappé, ``0`` correspondant au début du fichier. Le premier argument est l'adresse à laquelle la première page du fichier doit être mappée. Généralement, cet argument est mis à ``NULL`` de façon à laisser le noyau choisir l'adresse la plus appropriée. Si cette adresse est spécifiée, elle doit être un multiple de la taille des pages. Le deuxième argument est la longueur de la zone du fichier qui doit être mappée en mémoire. Le troisième argument contient des drapeaux qui spécifient les permissions d'accès aux données mappées. Cet argument peut soit être ``PROT_NONE``, ce qui indique que la page est inaccessible soit une permission classique : - - - ``PROT_EXEC``, les pages mappées contiennent des instructions qui peuvent être exécutées - - ``PROT_READ``, les pages mappées contiennent des données qui peuvent être lues - - ``PROT_WRITE``, les pages mappées contiennent des données qui peuvent être modifiées - -Ces drapeaux peuvent être combinés avec une disjonction logique. Le quatrième argument est un drapeau qui indique comment les pages doivent être mappées en mémoire. Ce drapeau spécifie comment un fichier qui est mappé par deux ou plusieurs processus doit être traité. Deux drapeaux sont possibles : - - - ``MAP_PRIVATE``. Dans ce cas, les pages du fichier sont mappées dans chaque processus, mais si un processus modifie une page, cette modification n'est pas répercutée aux autres processus qui ont mappé la même page de ce fichier. - - ``MAP_SHARED``. Dans ce cas, plusieurs processus peuvent accéder et modifier la page qui est mappée en mémoire. Lorsqu'un processus modifie le contenu d'une page, la modification est visible aux autres processus. Par contre, le fichier qui est mappé en mémoire n'est modifié que lorsque le noyau du système d'exploitation décide d'écrire les données modifiées sur le dispositif de stockage. Ces écritures dépendent de nombreux facteurs, dont la charge du système. Si un processus veut être sûr des écritures sur disque des modifications qu'il a fait à un fichier mappé un mémoire, il doit exécuter l'appel système `msync(2)`_ ou supprimer le mapping via `munmap(2)`_. - -Ces deux drapeaux peuvent dans certains cas particuliers être combinés avec d'autres drapeaux définis dans la page de manuel de `mmap(2)`_. - -Lorsque `mmap(2)`_ réussit, il retourne l'adresse du début de la zone mappée en mémoire. En cas d'erreur, la constante ``MAP_FAILED`` est retournée et ``errno`` est mis à jour en conséquence. - -L'appel système `msync(2)`_ permet de forcer l'écriture sur disque d'une zone mappée en mémoire. Le premier argument est l'adresse du début de la zone qui doit être écrite sur disque. Le deuxième argument est la longueur de la zone qui doit être écrite sur le disque. Enfin, le dernier contient un drapeau qui spécifie comment les pages correspondantes doivent être écrites sur le disque. La drapeau ``MS_SYNC`` indique que l'appel `msync(2)`_ doit bloquer tant que les données n'ont pas été écrites. Le drapeau ``MS_ASYNC`` indique au noyau que l'écriture doit être démarrée, mais l'appel système peut se terminer avant que toutes les pages modifiées aient été écrites sur disque. - -.. code-block:: c - - #include <sys/mman.h> - int msync(void *addr, size_t length, int flags); - - -Lorsqu'un processus a fini d'utiliser un fichier mappé en mémoire, il doit d'abord supprimer le mapping en utilisant l'appel système `munmap(2)`_. Cet appel système prend deux arguments. Le premier doit être un multiple de la taille d'une page [#ftaillepage]_. Le second est la taille de la zone pour laquelle le mapping doit être retiré. - -.. code-block:: c - - #include <sys/mman.h> - - int munmap(void *addr, size_t length); - - -A titre d'exemple d'utilisation de `mmap(2)`_ et `munmap(2)`_, le programme ci-dessous implémente l'équivalent de la commande `cp(1)`_. Il prend comme arguments deux noms de fichiers et copie le contenu du premier dans le second. La copie se fait en mappant le premier fichier entièrement en mémoire et en utilisant la fonction `memcpy(3)`_ pour réaliser la copie. Cette solution fonctionne avec de petits fichiers. Avec de gros fichiers, elle n'est pas très efficace car tout le fichier doit être mappé en mémoire. - -.. literalinclude:: /MemoireVirtuelle/src/cp2.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - - - -.. _shmem: - -Mémoire partagée ----------------- - -Dans les exemples précédents, nous avons supposé qu'il existait une correspondance biunivoque entre chaque page de la mémoire virtuelle et une page en mémoire RAM. C'est souvent le cas, mais ce n'est pas nécessaire. Il est tout à fait possible d'avoir plusieurs pages de la mémoire virtuelle qui appartiennent à des processus différents mais pointent vers la même page en mémoire physique. Ce partage d'une même page physique entre plusieurs pages de la mémoire virtuelle a plusieurs utilisations en pratique. - -Revenons aux threads POSIX. Lorsqu'un processus crée un nouveau thread d'exécution, celui-ci a un accès complet au segment code, aux variables globales et au heap du processus. Par contre, le thread et le processus ont chacun un stack qui leur est propre. Comme nous l'avons indiqué lors de la présentation des threads, ceux-ci peuvent être implémentés en utilisant une librairie ou avec l'aide du système d'exploitation. Du point de vue de la mémoire, lorsqu'une librairie telle que :term:`gnuth` est utilisée pour créer un thread, la librairie réserve une zone de mémoire sur le heap pour ce thread. Cette zone mémoire contient le stack qui est spécifique au thread. Celui-ci a été alloué en utilisant `malloc(3)`_ et a généralement une taille fixe. Avec la mémoire virtuelle, il est possible d'implémenter les threads plus efficacement avec l'aide du système d'exploitation. Lors de la création d'un thread, celui-ci va tout d'abord créer une nouvelle table des pages pour le thread. Celle-ci sera initialisée en copiant toutes les entrées de la table des pages du processus, sauf celles qui correspondent au stack. De cette façon, le processus `père` et le thread auront accès aux mêmes segments de code, aux même variables globales et au même heap. Toute modification faite par le processus père à une variable globale ou à une information stockée sur le heap sera immédiatement accessible au thread et inversement. L'entrée de la table des pages du thread correspondant à son stack pointera vers une page qui sera spécifique au thread. Cette page aura été initialisée par le système d'exploitation avec l'argument passé par le processus à la fonction `pthread_create(3)`_. La figure ci-dessous illustre ce partage de table des pages après la création d'un thread. - -.. figure:: /MemoireVirtuelle/fig/tablePages.png - :align: center - :scale: 60 - - Tables des pages après création d'un thread - -.. todo:: mieux montrer comment cela fonctionne en la représentant en mémoire - -En exploitant intelligemment la table des pages, il est également possible de permettre à deux processus distincts d'avoir accès à la même zone de mémoire physique. Si deux processus peuvent accéder simultanément à la même zone de mémoire, ils peuvent l'utiliser pour communiquer plus efficacement qu'en utilisant des pipes par exemple. Cette technique porte le nom de :term:`mémoire partagée`. Elle nécessite une modification de la table des pages des processus qui veulent partager une même zone mémoire. Pour comprendre le fonctionnement de cette :term:`mémoire partagée`, considérons le cas de deux processus : `P1` et `P2` qui veulent pouvoir utiliser une page commune en mémoire. Pour cela, plusieurs interactions entre les processus et le système d'exploitation sont nécessaires comme nous allons le voir. - -Avant de permettre à deux processus d'accéder à la même page en mémoire physique, il faut d'abord se poser la question de l'origine de cette page physique. Deux solutions sont possibles. La première est de prendre cette page parmi les pages qui appartiennent à l'un des processus, par exemple `P1`. Lorsque la page est partagée, le système d'exploitation peut modifier la table des pages du processus `P2` de façon à lui permettre d'y accéder. La seconde est que le noyau du système d'exploitation fournisse une nouvelle page qui pourra être partagée. Cette page "appartient" au noyau mais celui-ci la rend accessible aux processus `P1` et `P2` en modifiant leurs tables des pages. Linux utilise la seconde technique. Elle a l'avantage de permettre un meilleur contrôle par le système d'exploitation du partage de pages entre différents processus. De plus, lorsqu'une zone de mémoire partagée a été créée via le système d'exploitation, elle survit à la terminaison de ce processus. Une mémoire partagée créée par un processus peut donc être utilisée par d'autres processus. - -Sous Linux, la mémoire partagée peut s'utiliser via les appels systèmes `shmget(2)`_, `shmat(2)`_ et `shmdt(2)`_. L'appel système `shmget(2)`_ permet de créer un segment de mémoire partagée. Le premier argument de `shmget(2)`_ est une clé qui identifie le segment de mémoire partagée. Cette clé est en pratique encodée sous la forme d'un entier qui identifie le segment de mémoire partagée. Elle sert d'identifiant du segment de mémoire partagée dans le noyau. Un processus doit connaître la clé qui identifie un segment de mémoire partagée pour pouvoir y accéder. Le deuxième argument de `shmget(2)`_ est la taille du segment. En pratique, celle-ci sera arrondie au multiple entier supérieur de la taille d'une page. Enfin, le troisième argument sont des drapeaux qui contrôlent la création du segment et les permissions qui y sont associées. - -.. code-block:: c - - #include <sys/ipc.h> - #include <sys/shm.h> - int shmget(key_t key, size_t size, int shmflg); - -L'appel système `shmget(2)`_ retourne un entier qui identifie le segment de mémoire partagée à l'intérieur du processus si il réussit et ``-1`` sinon. Il peut être utilisé de deux façons. Un processus peut appeler `shmget(2)`_ pour créer un nouveau segment de mémoire partagée. Pour cela, il choisit une clé unique qui identifie ce segment et utilise le drapeau ``IPC_CREAT``. Celui-ci peut être combiné avec les drapeaux qui sont supportés par l'appel système `open(2)`_. Ainsi, le fragment de code ci-dessous permet de créer une page de mémoire partagée qui a ``1252`` comme identifiant et est accessible en lecture et en écriture par tous les processus qui appartiennent au même utilisateur ou au même groupe que le processus courant. Si cet appel à `shmget(2)`_ réussit, le segment de mémoire est initialisé à la valeur 0. - -.. code-block:: c - - key_t key=1252; - int shm_id = shmget(key, 4096, IPC_CREAT | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP ); - if (shm_id == -1) { - perror("shmget"); - exit(EXIT_FAILURE); - } - -La fonction `shmget(2)`_ peut aussi être utilisée par un processus pour obtenir l'autorisation d'accéder à un segment de mémoire partagée qui a été créé par un autre processus. Dans ce cas, le drapeau ``IPC_CREAT`` n'est pas passé en argument. - -.. todo:: question IPC_EXCL -.. todo:: question peut-ton avoir un processus qui l'ouvre en read/write et l'autre en read ? - -Il est important de noter que si l'appel à `shmget(2)`_ réussit, cela indique que le processus dispose des permissions pour accéder au segment de mémoire partagée, mais à ce stade il n'est pas accessible depuis la table des pages du processus. Cette modification à la table des pages du processus se fait en utilisant `shmat(2)`_. Cet appel système permet d'attacher un segment de mémoire partagée à un processus. Il prend comme premier argument l'identifiant du segment de mémoire retourné par `shmget(2)`_. Le deuxième argument est un pointeur vers la zone mémoire via laquelle le segment doit être accessible dans l'espace d'adressage virtuel du processus. Généralement, c'est la valeur ``NULL`` qui est spécifiée comme second argument et le noyau choisit l'adresse à laquelle le segment de mémoire est attaché dans le processus. Il est aussi possible de spécifier une adresse dans l'espace d'adressage du processus. Le troisième argument permet, en utilisant le drapeau ``SHM_RDONLY``, d'attacher le segment en lecture seule. `shmat(2)`_ retourne l'adresse à laquelle le segment a été attaché en cas de succès et ``(void *) -1`` en cas d'erreur. - -.. code-block:: c - - #include <sys/types.h> - #include <sys/shm.h> - - void *shmat(int shmid, const void *shmaddr, int shmflg); - - int shmdt(const void *shmaddr); - -L'appel système `shmdt(2)`_ permet de détacher un segment de mémoire qui avait été attaché en utilisant `shmat(2)`_. L'argument passé à `shmdt(2)`_ doit être l'adresse d'un segment de mémoire attaché préalablement par `shmat(2)`_. Lorsqu'un processus se termine, tous les segments auxquels il était attaché sont détachés lors de l'appel à `exit(2)`_. Cela n'empêche pas un programme de détacher correctement tous les segments de mémoire qu'il utilise avant de se terminer. - -Le fragment de code ci-dessous présente comment un segment de mémoire peut être attaché et détaché après avoir été créé avec `shmget(2)`_. - -.. code-block:: c - - void * addr = shmat(shm_id, NULL, 0); - if (addr == (void *) -1) { - perror("shmat"); - exit(EXIT_FAILURE); - } - // ... - if(shmdt(addr)==-1) { - perror("shmdt"); - exit(EXIT_FAILURE); - } - -.. note:: Attention aux pointeurs en mémoire partagée - - Lorsque deux processus partagent le même segment de mémoire partagée, ils ont tous les deux accès directement à la mémoire. Il est ainsi possible de stocker dans cette mémoire un tableau de nombres ou de caractères. Chacun des processus pourra facilement accéder aux données stockées dans le tableau. Il faut cependant être vigilant lorsque l'on veut stocker une structure de données utilisant des pointeurs dans un segment de mémoire partagée. Considérons une liste simplement chaînée. Cette liste peut être implémentée en utilisant une structure contenant la donnée stockée dans l'élément de la liste (par exemple un entier) et un pointeur vers l'élément suivant dans la liste (et ``NULL`` en fin de liste). Imaginons que les deux processus ont attaché le segment de mémoire destiné à contenir la liste avec l'appel `shmat(2)`_ présenté ci-dessus et que l'adresse retournée par `shmat(2)`_ est celle qui correspond au premier élément de la liste. Comme le système d'exploitation choisit l'adresse à laquelle le segment de mémoire partagée est stocké dans chaque processus, l'appel à `shmat(2)`_ retourne potentiellement une adresse différente dans les deux processus. Si ils peuvent tous les deux accéder au premier élément de la liste, il n'en sera pas de même pour le second élément. En effet, si cet élément a été créé par le premier processus, le pointeur contiendra l'adresse du second élément dans l'espace d'adressage virtuel du premier processus. Cette adresse ne correspondra en général pas à celle du second élément dans l'espace d'adressage du second processus. Pour cette raison, il est préférable de ne pas utiliser de pointeurs dans un segment de mémoire partagé. - -.. todo:: exercice, comment implémenter cette liste chaînée - -Comme les segments de mémoire partagée sont gérés par le noyau du système d'exploitation, ils persistent après la terminaison du processus qui les a créé. C'est intéressant lorsque l'on veut utiliser des segments de mémoire partagée pour la communication entre plusieurs processus dont certains peuvent se crasher. Malheureusement, le nombre de segments de mémoire partagée qui peuvent être utilisés sur un système Unix est borné. Lorsque la limite fixée par la configuration du noyau est atteinte, il n'est plus possible de créer de nouveau segment de mémoire partagée. Sous Linux ces limites sont visibles dans les fichiers ``/proc/sys/kernel/shmmni`` (nombre maximum d'identifiants de segments de mémoire partagée) et ``/proc/sys/kernel/shmall`` (taille totale maximale de la mémoire partagée) ou via `shmctl(2)`_. Cet appel système permet de réaliser de nombreuses fonctions de contrôle de la mémoire partagée et notamment la destruction de segments de mémoire partagée qui ont été créés par `shmget(2)`_. `shmctl(2)`_ s'appuie sur les structures de données qui sont maintenues par le noyau pour les segments de mémoire partagée. Lorsqu'un segment de mémoire partagée est crée, le noyau lui associe une structure de type ``shmid_ds``. - -.. code-block:: c - - struct shmid_ds { - struct ipc_perm shm_perm; /* Propriétaire et permissions */ - size_t shm_segsz; /* Taille du segment (bytes) */ - time_t shm_atime; /* Instant de dernier attach */ - time_t shm_dtime; /* Instant de dernier detach */ - time_t shm_ctime; /* Instant de dernière modification */ - pid_t shm_cpid; /* PID du créateur */ - pid_t shm_lpid; /* PID du dernier `shmat(2)`_ / `shmdt(2)`_ */ - shmatt_t shm_nattch; /* Nombre de processus attachés */ - }; - -Ce descripteur de segment de mémoire partagée, décrit dans `shmctl(2)`_ contient plusieurs informations utiles. Son premier élément est une structure qui reprend les informations sur le propriétaire et les permissions qui ont été définies ainsi que la taille du segment. Le descripteur de segment comprend ensuite les instants auxquels les dernières opérations `shmat(2)`_, `shmdt(2)`_ et la dernière modification au segment ont été faites. Le dernier élément contient le nombre de processus qui sont actuellement attachés au segment. L'appel système `shmctl(2)`_ prend trois arguments. Le premier est un identifiant de segment de mémoire partagée retourné par `shmget(2)`_. Le deuxième est une constante qui spécifie une commande. Nous utiliserons uniquement la commande ``IPC_RMID`` qui permet de retirer le segment de mémoire partagée dont l'identifiant est passé comme premier argument. Si il n'y a plus de processus attaché au segment de mémoire partagée, celui-ci est directement supprimé. Sinon, il est marqué de façon à ce que le noyau retire le segment dès que le dernier processus s'en détache. `shmctl(2)`_ retourne ``0`` en cas de succès et ``-1`` en cas d'échec. - -.. code-block:: c - - #include <sys/ipc.h> - #include <sys/shm.h> - - int shmctl(int shmid, int cmd, struct shmid_ds *buf); - -Le segment de mémoire partagée qui a été créé dans les exemples précédents peut être supprimé avec le fragment de code ci-dessous. - -.. code-block:: c - - if (shmctl(shm_id, IPC_RMID, 0) != 0) { - perror("shmctl"); - exit(EXIT_FAILURE); - } - -En pratique, comme le noyau ne détruit un segment de mémoire partagée que lorsqu'il n'y a plus de processus qui y est attaché, il peut être utile de détruire le segment de mémoire partagée juste après avoir effectué l'appel `shmat(2)`_. C'est ce que l'on fera par exemple si un processus père utilise un segment de mémoire partagée pour communiquer avec son processus fils. - - -La mémoire partagée est utilisée non seulement pour permettre la communication entre processus, mais également avec les librairies partagées. Celles-ci sont chargées automatiquement lors de l'exécution d'un processus qui les utilise. Les instructions qui font partie de ces librairies partagées sont chargées dans la même zone mémoire que celle qui est utilisée pour la mémoire partagée. Sous Linux, cette zone mémoire est située entre le heap et le stack comme illustré dans la figure ci-dessous. - -.. figure:: /MemoireVirtuelle/fig/orgMemoire.png - :align: center - :scale: 60 - - Organisation en mémoire d'un processus - - -Lorsqu'il exécute un processus, le noyau maintient dans les structures de données qui sont relatives à ce processus la liste des segments de mémoire partagée et des librairies partagées qu'il utilise. Sous Linux, cette information est visible via le pseudo-système de fichiers ``/proc``. Le fichier ``/proc/PID/maps`` représente de façon textuelle la table des segments de mémoire qui sont partagés dans le processus ``PID``. - - -Un exemple d'un tel fichier `maps` est présenté ci-dessous. Il contient une carte de l'ensemble des pages qui appartiennent à un processus. Le fichier comprend six colonnes. La première est la zone de mémoire virtuelle. La seconde sont les bits de permission avec `r` pour la permission de lecture, `w` pour l'écriture et `x` pour l'exécution. Le dernier bit de permission est à la valeur `p` lorsque la page est en :term:`copy-on-write` et `s` lorsqu'il s'agit d'un segment de mémoire partagé. Les trois dernières colonnes sont relatives au stockage des pages sur le disque. - -.. code-block:: console - - 00400000-00402000 r-xp 00000000 00:1a 49485798 /tmp/a.out - 00602000-00603000 rw-p 00002000 00:1a 49485798 /tmp/a.out - 3d3f200000-3d3f220000 r-xp 00000000 08:01 268543 /lib64/ld-2.12.so - 3d3f41f000-3d3f420000 r--p 0001f000 08:01 268543 /lib64/ld-2.12.so - 3d3f420000-3d3f421000 rw-p 00020000 08:01 268543 /lib64/ld-2.12.so - 3d3f421000-3d3f422000 rw-p 00000000 00:00 0 - 3d3f600000-3d3f786000 r-xp 00000000 08:01 269510 /lib64/libc-2.12.so - 3d3f786000-3d3f986000 ---p 00186000 08:01 269510 /lib64/libc-2.12.so - 3d3f986000-3d3f98a000 r--p 00186000 08:01 269510 /lib64/libc-2.12.so - 3d3f98a000-3d3f98b000 rw-p 0018a000 08:01 269510 /lib64/libc-2.12.so - 3d3f98b000-3d3f990000 rw-p 00000000 00:00 0 - 3d3fa00000-3d3fa83000 r-xp 00000000 08:01 269516 /lib64/libm-2.12.so - 3d3fa83000-3d3fc82000 ---p 00083000 08:01 269516 /lib64/libm-2.12.so - 3d3fc82000-3d3fc83000 r--p 00082000 08:01 269516 /lib64/libm-2.12.so - 3d3fc83000-3d3fc84000 rw-p 00083000 08:01 269516 /lib64/libm-2.12.so - 7f7c57e42000-7f7c57e45000 rw-p 00000000 00:00 0 - 7f7c57e60000-7f7c57e61000 rw-s 00000000 00:04 66355276 /SYSV00000000 - 7f7c57e61000-7f7c57e63000 rw-p 00000000 00:00 0 - 7fffc479c000-7fffc47b1000 rw-p 00000000 00:00 0 [stack] - - -L'exemple ci-dessus présente la carte de mémoire d'un processus qui utilise trois librairies partagées. Le segment de mémoire partagée se trouve aux adresses virtuelles ``7f7c57e60000-7f7c57e61000``. Il est accessible en lecture et en écriture. - -.. _forkmem: - -Implémentation de `fork(2)`_ ----------------------------- - -La mémoire partagée joue un rôle clé dans l'exécution efficace des appels systèmes `fork(2)`_ et `execve(2)`_. Considérons d'abord `fork(2)`_. Cet appel est fondamental sur un système Unix. Au fil des années, les développeurs de Unix et de Linux ont cherché à optimiser ses performances. Une implémentation naïve de l'appel système `fork(2)`_ est de copier physiquement toutes les pages utilisées en mémoire RAM par le processus père. Ensuite, le noyau peut créer une table des pages pour le processus fils qui pointe vers les copies des pages du processus père. De cette façon, le processus père et le processus fils utilisent exactement les mêmes instructions. Ils peuvent donc poursuivre leur exécution à partir des mêmes données en mémoire. Mais chaque processus pourra faire les modifications qu'il souhaite aux données stockées en mémoire. Cette implémentation était utilisée par les premières versions de Unix, mais elle est peu efficace, notamment pour les processus qui consomment beaucoup de mémoire et le shell qui généralement exécute `fork(2)`_ et suivi par `execve(2)`_. Dans ce scénario, copier l'entièreté de la mémoire du processus père est un gaspillage de ressources. - -La mémoire virtuelle permet d'optimiser l'appel système `fork(2)`_ et de le rendre nettement plus rapide. Lors de la création d'un processus fils, le noyau du système d'exploitation commence par créer une table des pages pour le processus fils. En initialisant cette table avec les mêmes entrées que celles du processus père, le noyau permet aux deux processus d'accéder aux mêmes instructions et aux mêmes données. Pour les instructions se trouvant dans le segment code et dont les entrées de la table des pages sont généralement en `read-only`, cette solution fonctionne correctement. Le processus père et le processus fils peuvent exécuter exactement les mêmes instructions tout en n'utilisant qu'une seule copie de ces instructions en mémoire. - -Malheureusement, cette solution ne fonctionne plus pour les pages contenant les données globales, le stack et le heap. En effet, ces pages doivent pouvoir être modifiées de façon indépendante par le processus père et le processus fils. C'est notamment le cas pour la zone mémoire qui contient la valeur de retour de l'appel système `fork(2)`_. Par définition, cette zone mémoire doit contenir une valeur différente dans le processus père et le processus fils. Pour éviter ce problème, le noyau pourrait copier physiquement les pages contenant les variables globales, le heap et le stack. Cela permettrait, notamment dans le cas de l'exécution de `fork(2)`_ par le shell d'améliorer les performances de `fork(2)`_ sans pour autant compromettre la sémantique de cet appel système. Il existe cependant une alternative à cette copie physique. Il s'agit de la technique du :term:`copy-on-write`. - -Sur un système qui utilise :term:`copy-on-write`, l'appel système `fork(2)`_ est implémenté comme suit. Lors de l'exécution de `fork(2)`_, le noyau copie toutes les entrées de la table des pages du processus père vers la table des pages du processus fils. Ce faisant, le noyau modifie également les permissions de toutes les pages utilisées par le processus père. Les pages correspondant au segment de code sont toutes marquées en lecture seule. Les pages correspondant aux données globales, heap et stack sont marquées avec un statut spécial (:term:`copy-on-write`). Celui-ci autorise les accès en lecture à la page sans restriction. Si un processus tente un accès en écriture sur une de ces pages, le :term:`MMU` interrompt l'exécution du processus et force l'exécution d'une routine d'interruption du noyau. Celle-ci analyse la tentative d'accès à la mémoire qui a échoué. Si la page était en lecture seule (par exemple une page du segment de code), un signal ``SIGSEGV`` est envoyé au processus concerné. Si par contre la page était marquée :term:`copy-on-write`, alors le noyau alloue une nouvelle page physique et y recopie la page où la tentative d'accès a eu lieu. La table des pages du processus qui a fait la tentative d'accès est modifiée pour pointer vers la nouvelle page avec une permission en lecture et en écriture. La permission de l'entrée de la table des pages de l'autre processus est également modifiée de façon à autoriser les écritures et les lectures. Les deux processus disposent donc maintenant d'une copie différente de cette page et ils peuvent la modifier à leur guise. Cette technique de :term:`copy-on-write` permet de ne copier que les pages qui sont modifiées par le processus père ou le processus fils. C'est un gain de temps appréciable par rapport à la copie complète de toutes les pages. - -Dans le pseudo fichier ``/proc/PID/maps`` présenté avant, le bit `p` indique que les pages correspondantes sont en `copy-on-write`. - -.. _vmstat: - -Interactions entre les processus et la mémoire ----------------------------------------------- - -La mémoire virtuelle est gérée par le système d'exploitation. La plupart des processus supportent très bien d'avoir certaines de leurs pages qui sont sauvegardées sur disque lorsque la mémoire est saturée. Cependant, dans certains cas très particuliers, il peut être intéressant pour un processus de contrôler quelles sont ses pages qui restent en mémoire et quelles sont celles qui sont stockées sur le disque dur. Linux fournit plusieurs appels systèmes qui permettent à un processus de monitorer et éventuellement d'influencer la stratégie de remplacement des pages. - -.. code-block:: c - - #include <unistd.h> - #include <sys/mman.h> - int mincore(void *addr, size_t length, unsigned char *vec); - -L'appel système `mincore(2)`_ permet à un processus d'obtenir de l'information sur certaines de ses pages. Il prend comme premier argument une adresse, qui doit être un multiple de la taille des pages. Le deuxième est la longueur de la zone mémoire pour laquelle le processus demande de l'information. Le dernier argument est un pointeur vers une chaîne de caractères qui doit contenir autant de caractères que de pages dans la zone de mémoire analysée. Cette chaîne de caractères contiendra des drapeaux pour chaque page de la zone mémoire concernée. Les principaux sont : - - - ``MINCORE_INCORE`` indique que la page est en mémoire RAM - - ``MINCORE_REFERENCED`` indique que la page a été référencée - - ``MINCORE_MODIFIED`` indique que la page a été modifiée - -Un exemple d'utilisation de `mincore(2)`_ est repris dans le programme :download:`/MemoireVirtuelle/src/mincore.c` ci-dessous. - -.. literalinclude:: /MemoireVirtuelle/src/mincore.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - - -Certains processus doivent pouvoir contrôler la façon dont leurs pages sont stockées en mémoire RAM ou sur disque. C'est le cas notamment des processus qui manipulent des clés cryptographiques. Pour des raisons de sécurité, il est préférable que ces clés ne soient pas sauvegardées sur le disque dur. Pour des raisons de performances, certains processus préfèrent également éviter que leurs pages ne soient stockées sur disque dur. Linux comprend plusieurs appels systèmes qui permettent à un processus d'influencer la stratégie de remplacement des pages du noyau. - -.. code-block:: c - - #include <sys/mman.h> - - int mlock(const void *addr, size_t len); - int munlock(const void *addr, size_t len); - - int mlockall(int flags); - int munlockall(void); - -L'appel système `mlock(2)`_ permet de forcer un ensemble de pages à rester en mémoire RAM tandis que `munlock(2)`_ fait l'inverse. L'appel système `mlockall(2)`_ quant à lui permet à un processus de demander que tout l'espace d'adressage qu'il utilise reste en permanence en mémoire RAM. `mlockall(2)`_ prend comme argument des drapeaux. Actuellement deux drapeaux sont supportés. ``MCL_CURRENT`` indique que toutes les pages actuellement utilisées par le processus doivent rester en mémoire. ``MCL_FUTURE`` indique que toutes les pages qui seront utilisées par le processus devront être en mémoire RAM au fur et à mesure de leur allocation. L'appel système `madvise(2)`_ permet également à un processus de donner des indications sur la façon dont il utilisera ses pages dans le futur. - -Ces appels systèmes doivent être utilisés avec précautions. En forçant certaines de ses pages à rester en mémoire, un processus perturbe le bon fonctionnement de la mémoire virtuelle, ce qui risque de perturber les performances globales du système. En pratique, en dehors d'applications cryptographiques et de processus avec des exigences temps réel qui sortent du cadre de ce cours, il n'y a pas d'intérêt à utiliser ces appels système. - -L'utilisation de la mémoire influence fortement les performances des processus. Plusieurs utilitaires sous Linux permettent de mesurer la charge d'un système. Certains offrent une interface graphique. D'autres, comme `top(1)`_ ou `vmstat(8)`_ s'utilisent directement depuis un terminal. La commande `vmstat(8)`_ permet de suivre l'évolution de la charge du système et de la mémoire virtuelle. - -.. code-block:: console - - $ vmstat 5 - procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu----- - r b swpd free buff cache si so bi bo in cs us sy id wa st - 3 0 662260 259360 49044 583808 0 0 1 1 1 2 5 0 95 0 0 - 3 0 662260 259352 49044 583808 0 0 0 0 6018 4182 61 0 39 0 0 - 7 1 662260 254856 49044 587328 0 0 0 0 6246 4309 61 0 38 2 0 - 4 0 662260 221668 49044 608652 0 0 0 0 9731 5520 62 1 9 28 0 - 3 0 662260 260368 49044 583836 0 0 0 2 8291 4868 70 1 12 17 0 - 4 0 662260 260548 49044 583836 0 0 0 0 6042 4174 61 0 39 0 0 - 3 0 662260 260720 49044 583836 0 0 0 0 6003 4242 61 0 39 0 0 - -Lorsqu'elle est utilisée, la commande `vmstat(8)`_ retourne de l'information sur l'état du système. Dans l'exemple ci-dessus, elle affiche cet état toutes les 5 secondes. La sortie de `vmstat(8)`_ comprend plusieurs informations utiles. - - - la colonne ``procs`` reprend le nombre de processus qui sont dans l'état `Running` ou `Blocked`. - - la colonne ``memory`` reprend l'information relative à l'utilisation de la mémoire. La colonne `swpd` est la quantité de mémoire virtuelle utilisée. La colonne `free` est la quantité de mémoire RAM qui est actuellement libre. Les colonnes ``buff`` et ``cache`` sont relatives aux buffers et à la cache qui sont utilisés par le noyau. - - la colonne ``swap`` reprend la quantité de mémoire qui a été transférée sur le disque (`so`) ou lue du disque (`si`) - - la colonne ``io`` reprend le nombre de blocs lus du disque (`bi`) et écrits (`bo`) - - la colonne ``system`` reprend le nombre d'interruptions (`in`) et de changements de contexte (`cs`) - - la dernière colonne (``cpu``) fournit des statistiques sur l'utilisation du cpu - -Enfin, notons que l'appel système `getrusage(2)`_ peut être utilisé par un processus pour obtenir de l'information sur son utilisation des ressources du système et notamment les opérations de transfert de pages entre le mémoire RAM et les dispositifs de stockage. - -.. _execvmem: - -`execve(2)`_ et la mémoire virtuelle ------------------------------------- - -Pour terminer ce survol de la mémoire virtuelle, il est intéressant de revenir sur le fonctionnement de l'appel système `execve(2)`_. Celui-ci permet de remplacer l'image mémoire du processus en cours d'exécution par un exécutable chargé depuis le disque. L'appel système `execve(2)`_ utilise fortement la mémoire virtuelle. Plutôt que de copier l'entièreté de l'exécutable en mémoire, il se contente de créer les entrées correspondants au segment de code et aux variables globales dans la table des pages du processus. Ces entrées pointent vers le fichier exécutable qui est sauvegardé sur le disque. En pratique, celui-ci est découpé en deux parties. La première contient les instructions. Celles-ci sont mappées sous forme de pages sur lesquelles le processus a les permissions d'exécution et de lecture. La seconde partie du fichier correspond à la zone des chaînes de caractères et des variables globales. Celle-ci est mappée dans des pages qui sont accessibles en lecture et en écriture. En pratique, la technique du :term:`copy-on-write` est utilisée pour ne créer une copie spécifique au processus que si celui-ci modifie certaines données en mémoire. Ensuite, les pages relatives au :term:`heap` et au :term:`stack` peuvent être créées. - -La sortie ci-dessous présente le contenu de ``/proc/PID/maps`` lors de l'exécution du programme :download:`/MemoireVirtuelle/src/cp2.c` présenté plus haut. Celui-ci utilise deux fichiers mappés en mémoire avec `mmap(2)`_. Ceux-ci apparaissent dans la table des pages du processus, tout comme l'exécutable. Au niveau des permissions, on remarquera que le fichier source est mappé avec des pages en lecture seule tandis que le fichier destination est mappé en lecture/écriture. - -.. code-block:: console - - $ cat /proc/29039/maps - 00400000-004ab000 r-xp 00000000 00:19 49479785 /etinfo/users2/obo/sinf1252/SINF1252/2012/S12/src/cp2.exe - 006ab000-006ac000 rw-p 000ab000 00:19 49479785 /etinfo/users2/obo/sinf1252/SINF1252/2012/S12/src/cp2.exe - 006ac000-006af000 rw-p 00000000 00:00 0 - 00bc7000-00bea000 rw-p 00000000 00:00 0 [heap] - 7fc43d5e4000-7fc43d6a4000 rw-s 00000000 00:19 51380745 /etinfo/users2/obo/sinf1252/SINF1252/2012/S12/src/t - 7fc43d6a4000-7fc43d764000 r--s 00000000 00:19 49479785 /etinfo/users2/obo/sinf1252/SINF1252/2012/S12/src/cp2.exe - 7fff5b912000-7fff5b927000 rw-p 00000000 00:00 0 [stack] - 7fff5b9ff000-7fff5ba00000 r-xp 00000000 00:00 0 [vdso] - ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] - - - -.. rubric:: Footnotes - -.. todo: faire exemple avec un processus père qui fait fork puis le fils accède à 100, 1000 pages (qui seront copiées), montrer l'évolution du temps d'accès à ces pages - - -.. [#fmmu] En pratique, les adresses sur le disque dur ne sont pas stockées dans le :term:`MMU` mais dans une table maintenue par le système d'exploitation. C'est le noyau qui est responsable des transferts entre le dispositif de stockage et la mémoire RAM. - -.. [#fintel] Source : http://www.intel.com/content/www/us/en/solid-state-drives/ssd-320-specification.html - -.. [#fseagate] Source : http://www.seagate.com/staticfiles/support/disc/manuals/desktop/Barracuda%207200.11/100507013e.pdf - -.. [#fentree] Une entrée de la table de pages occupe généralement 32 ou 64 bits suivant les architectures de processeurs. - -.. [#ftaillepage] Il est possible d'obtenir la taille des pages utilisée sur un système via les appels `sysconf(3)`_ ou `getpagesize(2)`_ diff --git a/Theorie/Threads/S5-src/errno.c b/Theorie/Threads/S5-src/errno.c deleted file mode 100644 index 4c0a4ec790bb622f03dfdb9a0714063f065c1950..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/errno.c +++ /dev/null @@ -1,24 +0,0 @@ -/************************************** - * errno.c - * - * Programme d'exemple pour errno - * - **************************************/ -///AAA -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -int main(int argc, char *argv[]) { - - if(setenv(NULL,NULL,1)!=0) { - fprintf(stderr,"Erreur : errno=%d %s\n",errno,strerror(errno)); - } - if(setenv("PATH=","/usr/bin",1)!=0) { - fprintf(stderr,"Erreur : errno=%d %s\n",errno,strerror(errno)); - } - - -} - diff --git a/Theorie/Threads/S5-src/fctptr.c b/Theorie/Threads/S5-src/fctptr.c deleted file mode 100644 index c9b68d53b0d4231dd3e6f9348b13263c5ed3c031..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/fctptr.c +++ /dev/null @@ -1,45 +0,0 @@ -/************************************** - * fctptr.c - * - * Programme d'exemple pour les pointeurs - * vers des fonctions - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> -///AAA -int g=1; -int debug_level; - -void empty (char *str) { - return; -} - -void oneline(char *str) { - fprintf(stderr,"debug: %s\n",str); -} - -void detailed(char *str) { - fprintf(stderr, "debug: %s\n",str); - fprintf(stderr,"g=%d\n",g); -} - -void (* debug_print[])(char *) = { empty, - oneline, - detailed }; - -int main(int argc, char *argv[]) { - - if(argc!=2) - return(EXIT_FAILURE); - - debug_level=atoi(argv[1]); - if((debug_level<0) || (debug_level>2) ) - return(EXIT_FAILURE); - printf("fct debug_print : %p\n",debug_print[debug_level]); - (debug_print[debug_level])("Hello"); - - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/Threads/S5-src/main.c b/Theorie/Threads/S5-src/main.c deleted file mode 100644 index 01130f8a563511b4851a98873a0e95f937025024..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/main.c +++ /dev/null @@ -1,18 +0,0 @@ -/************************************** - * main.c - * - * Programme d'exemple pour le linker - * - **************************************/ - -#include "min.h" -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) { - float f1=3.45; - float f2=-4.12; - printf("Minimum(%f,%f)=%f\n",f1,f2,min(f1,f2)); - return(EXIT_SUCCESS); -} - diff --git a/Theorie/Threads/S5-src/math.c b/Theorie/Threads/S5-src/math.c deleted file mode 100644 index 78da61797c921410ef305fbe67fd8ab747284f77..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/math.c +++ /dev/null @@ -1,16 +0,0 @@ -/************************************** - * min.c - * - * Programme d'exemple pour le linker - * - **************************************/ - -#include <math.h> -#include <stdio.h> -#include <stdlib.h> - -int main (int argc, char *argv[]) { - printf("Le cosinus de PI vaut : %f\n",cos(M_PI)); - return(EXIT_SUCCESS); - -} diff --git a/Theorie/Threads/S5-src/min-ex.c b/Theorie/Threads/S5-src/min-ex.c deleted file mode 100644 index 44712f5ae995c912657d9cf3b4b9cfb253f95a85..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/min-ex.c +++ /dev/null @@ -1,24 +0,0 @@ -/************************************** - * min-ex.c - * - * Programme d'exemple pour le linker - * - **************************************/ - -#include "min.h" -#include <stdlib.h> - -float min(float a, float b) { - if(a<b) - return a; - else - return b; -} - -static int main(int argc, char*argv[]) { - - if(min(3.0,2.0)!=2.0) - return(EXIT_FAILURE); - -} - diff --git a/Theorie/Threads/S5-src/min.c b/Theorie/Threads/S5-src/min.c deleted file mode 100644 index 1a0c53f81b43a18e0c0be95f386570b256c0cfef..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/min.c +++ /dev/null @@ -1,17 +0,0 @@ -/************************************** - * min.c - * - * Programme d'exemple pour le linker - * - **************************************/ - -#include "min.h" - -float min(float a, float b) { - if(a<b) - return a; - else - return b; -} - - diff --git a/Theorie/Threads/S5-src/module.c b/Theorie/Threads/S5-src/module.c deleted file mode 100644 index a8f6204ae63f555734b0d31f3fd6285b5915bad7..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/module.c +++ /dev/null @@ -1,31 +0,0 @@ -/************************************** - * module.c - * - **************************************/ - -#include "module.h" - -static float min(float, float); - -int num1=0; // accessible hors de module.c -extern int num2; // définie dans un autre module -static int num3=1252; // accessible uniquement dans ce module - -float vmin(int n, float *ptr) { - float *p=ptr; - float m=*ptr; - for(int i=1;i<n;i++) { - m=min(m,*p); - p++; - } - return m; -} - -static float min(float a, float b) { - if(a<b) - return a; - else - return b; -} - - diff --git a/Theorie/Threads/S5-src/mystrtol.c b/Theorie/Threads/S5-src/mystrtol.c deleted file mode 100644 index 3cfbfdc267ac23810a787a128d3110798f254138..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/mystrtol.c +++ /dev/null @@ -1,46 +0,0 @@ -/************************************** - * stresep.c - * - * Implementation partielle de strtol - * - **************************************/ -///AAA -#include <stdlib.h> -#include <stdio.h> -#include <ctype.h> -#include <stdbool.h> - -int mystrtol(const char *restrict str, - char **restrict endptr, - int base) { - - int val; - int i=0; - int err=false; - while(!err && *(str+i)!='\0') - { - if(!isdigit(*(str+i))) { - err=true; - *endptr=(char *)(str+i); - } - i++; - } - // ... - return val; -} -///BBB - -int main(int argc, char *argv[]) -{ - char *p, *s; - long li; - s = "1252m"; - li = mystrtol(s,&p,10); - if(p!=NULL) { - printf("Caractère erronné : %c\n",*p); - // p pointe vers le caractère en erreur - } - printf("Valeur convertie : %s -> %ld\n",s,li); - return(EXIT_SUCCESS); - -} diff --git a/Theorie/Threads/S5-src/prog.c b/Theorie/Threads/S5-src/prog.c deleted file mode 100644 index 538d4f8a4b0aa521664f00e9169d11dd8fa3556d..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/prog.c +++ /dev/null @@ -1,39 +0,0 @@ -/************************************** - * prog - * - * Programme d'exemple pour le linker - * - **************************************/ - -#include <stdlib.h> -#include <stdio.h> -///AAA -#include "min.h" -#include "module.h" - -#define SIZE 4 - -extern int num1; // définie dans un autre module -int num2=1252; // accessible depuis un autre module -static int num3=-1; // accessible uniquement dans ce module - -void f() { - static int n=0; - int loc=2; - if(n==0) - printf("n est à l'adresse %p et loc à l'adresse %p\n",&n,&loc); - printf("f, n=%d\n",n); - n++; -} - -int main(int argc, char* argv[]) { - - float v[SIZE]={1.0, 3.4, -2.4, 9.9}; - printf("Minimum: %f\n",vmin(SIZE,v)); - f(); - f(); - printf("Minimum(0.0,1.1)=%f\n",min(0.0,1.1)); - return(EXIT_SUCCESS); -} - - diff --git a/Theorie/Threads/S5-src/pthread-args.c b/Theorie/Threads/S5-src/pthread-args.c deleted file mode 100644 index 6e4365501388aba19b8adbb30d4743524b46f371..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/pthread-args.c +++ /dev/null @@ -1,88 +0,0 @@ -/************************************** - * pthread-args.c - * - * Programme d'exemple de pthread utilisant les - * arguments et retournant une valeur - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -#define MAXNUM 1000 -#define NTHREADS 4 - -struct result { - long x; - long y; - long z; -}; - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - - -long power(long i, long j) { - long r=i; - while(j>0) { - r=r*i; - j--; - } - return r; -} - - -void *fermat (void * param) { - - struct result *r=(struct result *)malloc(sizeof(struct result)); - if(r==NULL) - error(-1,"malloc"); - - long n=(long) param; - for(long x=1;x<MAXNUM;x++) { - for(long y=1;y<MAXNUM;y++) { - for(int z=1;z<MAXNUM;z++) { - if( (power(x,n)+power(y,n))==power(z,n) ) { - r->x=x; - r->y=y; - r->z=z; - return((void *) r); - } - } - } - } - return(NULL); -} - -int main (int argc, char *argv[]) { - pthread_t threads[NTHREADS]; - int err; - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(threads[i]),NULL,&fermat,(void *)(long) i+2); - if(err!=0) - error(err,"pthread_create"); - } - - - - for(int i=0;i<NTHREADS;i++) { - void *p; - err=pthread_join(threads[i],(void **)&(p)); - - if(err!=0) - error(err,"pthread_create"); - //if(p!=NULL) { - //struct result r; - // r=(struct result) p; - //printf("Trouvé pour %d : x=%ld, y=%ld, z=%ld\n",i+2,r[i].x,r[i].y, r[i].z); - } - - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S5-src/pthread-array.c b/Theorie/Threads/S5-src/pthread-array.c deleted file mode 100644 index 242a3209a44a8f4d319bd166af38d42542d38909..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/pthread-array.c +++ /dev/null @@ -1,51 +0,0 @@ -/************************************** - * pthread-neg.c - * - * Programme d'exemple de pthread utilisant les - * arguments et retournant une valeur - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -///AAA -#define NTHREADS 4 -#define SIZE 100 - -pthread_t mythread; - -void *f(void *param) { - int *v=(int *) param; - long r=0; - for(long i=0;i<SIZE;i++) { - r+=v[i]; - } - return((void *) r); -} - -void launch(void ){ - int v[SIZE]; - for(int i=0;i<SIZE;i++) { - v[i]=1; - } - int err=pthread_create(&(mythread),NULL,&f,(void *) v); - if(err!=0) - error(err,"pthread_create"); -} - - -int main (int argc, char *argv[]) { - - launch(); - // ... - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S5-src/pthread-neg.c b/Theorie/Threads/S5-src/pthread-neg.c deleted file mode 100644 index efc0b74ff6bddae9c8d8169aaed7cccfece1edd0..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/pthread-neg.c +++ /dev/null @@ -1,51 +0,0 @@ -/************************************** - * pthread-neg.c - * - * Programme d'exemple de pthread utilisant les - * arguments et retournant une valeur - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -///AAA -#define NTHREADS 4 -void *neg (void * param) { - int *l; - l=(int *) param; - int *r=(int *)malloc(sizeof(int)); - *r=-*l; - return ((void *) r); -} - -int main (int argc, char *argv[]) { - pthread_t threads[NTHREADS]; - int arg[NTHREADS]; - int err; - - for(long i=0;i<NTHREADS;i++) { - arg[i]=i; - err=pthread_create(&(threads[i]),NULL,&neg,(void *) &(arg[i])); - if(err!=0) - error(err,"pthread_create"); - } - - for(int i=0;i<NTHREADS;i++) { - int *r; - err=pthread_join(threads[i],(void **)&r); - printf("Resultat[%d]=%d\n",i,*r); - free(r); - if(err!=0) - error(err,"pthread_join"); - } - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S5-src/pthread-neg2.c b/Theorie/Threads/S5-src/pthread-neg2.c deleted file mode 100644 index 15573be985fee78fd349496be1f4d64bab2dbe80..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/pthread-neg2.c +++ /dev/null @@ -1,54 +0,0 @@ -/************************************** - * pthread-neg.c - * - * Programme d'exemple de pthread utilisant les - * arguments et retournant une valeur - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -///AAA -#define NTHREADS 4 -void *neg (void * param) { - int *l; - l=(int *) param; - int *r=(int *)malloc(sizeof(int)); - *r=-*l; - return ((void *) r); -} - -int main (int argc, char *argv[]) { - pthread_t threads[NTHREADS]; - int arg[NTHREADS]; - int err; - - for(int i=0;i<NTHREADS;i++) { - arg[i]=i; - } - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(threads[i]),NULL,&neg,(void *) &(arg[i])); - if(err!=0) - error(err,"pthread_create"); - } - - for(int i=0;i<NTHREADS;i++) { - int *r; - err=pthread_join(threads[i],(void **)&r); - - printf("Resultat[%d]=%d\n",i,*r); - free(r); - if(err!=0) - error(err,"pthread_join"); - } - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S5-src/pthread-test-if.c b/Theorie/Threads/S5-src/pthread-test-if.c deleted file mode 100644 index d901ebe3b4cad95a5bbc61b2ba923305a4f0b148..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/pthread-test-if.c +++ /dev/null @@ -1,77 +0,0 @@ -/************************************** - * pthread-test.c - * - * Programme d'exemple de pthread avec condition de course - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - - -///AAA - -long global=0; -int even=0; -int odd=0; - -void test_even(int i) { - if((i%2)==0) - even++; -} - -int increment(int i) { - return i+1; -} - -void *inc(void * param) { - for(int j=0;j<1000000;j++) { - global=increment(global); - } - pthread_exit(NULL); -} - -void *even(void * param) { - for(int j=0;j<1000000;j++) { - test_even(global); - } - pthread_exit(NULL); -} - -int main (int argc, char *argv[]) { - pthread_t thread_inc; - pthread_t thread_even; - int err; - - err=pthread_create(&(thread_inc),NULL,&inc,NULL); - if(err!=0) { - error(err,"pthread_create"); - } - - err=pthread_create(&(thread_even),NULL,&inc,NULL); - if(err!=0) { - error(err,"pthread_create"); - } - - err=pthread_join(thread_inc,NULL); - if(err!=0) - error(err,"pthread_join"); - } - - err=pthread_join(thread_even,NULL); - if(err!=0) - error(err,"pthread_join"); - } - - printf("global: %ld, even:%ld\n",global); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S5-src/pthread-test.c b/Theorie/Threads/S5-src/pthread-test.c deleted file mode 100644 index 0cfb277d9aa349afd6f0f8bf5dc9ec74bdab10d8..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/pthread-test.c +++ /dev/null @@ -1,56 +0,0 @@ -/************************************** - * pthread-test.c - * - * Programme d'exemple de pthread avec condition de course - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -///AAA - -#define NTHREADS 4 - -long global=0; - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -int increment(int i) { - return i+1; -} - -void *func(void * param) { - for(int j=0;j<1000000;j++) { - global=increment(global); - } - pthread_exit(NULL); -} - -int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&func,NULL); - if(err!=0) - error(err,"pthread_create"); - } - for(int i=0; i<1000000000;i++) { /*...*/ } - - for(int i=NTHREADS-1;i>=0;i--) { - err=pthread_join(thread[i],NULL); - if(err!=0) - error(err,"pthread_join"); - } - - printf("global: %ld\n",global); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S5-src/pthread.c b/Theorie/Threads/S5-src/pthread.c deleted file mode 100644 index 4e2741c68832e16f565b1305d5ce5e05f617564b..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/pthread.c +++ /dev/null @@ -1,57 +0,0 @@ -/************************************** - * pthread.c - * - * Programme d'exemple de pthread - * - **************************************/ -///AAA -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -int global=0; - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -void *thread_first(void * param) { - global++; - return(NULL); -} - -void *thread_second(void * param) { - global++; - pthread_exit(NULL); -} - -int main (int argc, char *argv[]) { - pthread_t first; - pthread_t second; - int err; - - err=pthread_create(&first,NULL,&thread_first,NULL); - if(err!=0) - error(err,"pthread_create"); - - err=pthread_create(&second,NULL,&thread_second,NULL); - if(err!=0) - error(err,"pthread_create"); - - for(int i=0; i<1000000000;i++) { /*...*/ } - - err=pthread_join(second,NULL); - if(err!=0) - error(err,"pthread_join"); - - err=pthread_join(first,NULL); - if(err!=0) - error(err,"pthread_join"); - - printf("global: %d\n",global); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S5-src/ptr-char.c b/Theorie/Threads/S5-src/ptr-char.c deleted file mode 100644 index 4af3385ff319c996f6ed3879c11b1f8f65e8288c..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/ptr-char.c +++ /dev/null @@ -1,21 +0,0 @@ -/************************************** - * ptr.c - * - * Programme d'exemple pour les pointeurs - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char **argv) { - - for(char **ptr=argv;*ptr!=NULL;ptr++) { - printf("Pointeur : %p, chaîne:%s\n",ptr,*ptr); - } - -} - - - - diff --git a/Theorie/Threads/S5-src/ptr.c b/Theorie/Threads/S5-src/ptr.c deleted file mode 100644 index c4ddc482ae1c7be7d615c7456f622e44dbf05559..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/ptr.c +++ /dev/null @@ -1,38 +0,0 @@ -/************************************** - * ptr.c - * - * Programme d'exemple pour les pointeurs - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) { - - int a=1252; - int b=1; - int *p=&a; - int **pp=&(p); - - printf("a=%d [%p], b=%d [%p], p=%p, *p=%d, pp=%p, *pp=%p, **pp=%d\n",a,&a,b,&b,p,*p,pp,*pp,**pp); - - a++; - - printf("a=%d [%p], b=%d [%p], p=%p, *p=%d, pp=%p, *pp=%p, **pp=%d\n",a,&a,b,&b,p,*p,pp,*pp,**pp); - - - *p=*p+1; - printf("a=%d [%p], b=%d [%p], p=%p, *p=%d, pp=%p, *pp=%p, **pp=%d\n",a,&a,b,&b,p,*p,pp,*pp,**pp); - - *pp=&b; - - printf("a=%d [%p], b=%d [%p], p=%p, *p=%d, pp=%p, *pp=%p, **pp=%d\n",a,&a,b,&b,p,*p,pp,*pp,**pp); - - - -} - - - - diff --git a/Theorie/Threads/S5-src/ptrptr.c b/Theorie/Threads/S5-src/ptrptr.c deleted file mode 100644 index 1044c2a914f7f8902b5257fd951ec34e529fbdd3..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/ptrptr.c +++ /dev/null @@ -1,24 +0,0 @@ -/************************************** - * ptrptr.c - * - * Programme d'exemple pour les pointeurs - * vers des pointeurs - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> -///AAA -int main(int argc, char **argv) { - - char **p; - p=argv; - printf("Arguments :"); - while(*p!=NULL) { - printf(" %s",*p); - p++; - } - printf("\n"); - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/Threads/S5-src/qsort.c b/Theorie/Threads/S5-src/qsort.c deleted file mode 100644 index 3e834bba35d90ebcebafc19a92e954a0e72d5723..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/qsort.c +++ /dev/null @@ -1,41 +0,0 @@ -/************************************** - * qosrt.c - * - * Programme d'exemple d'utilisation de qsort - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> -///AAA -#define SIZE 5 -double array[SIZE]= { 1.0, 7.32, -3.43, 8.7, 9.99 }; - -void print_array() { - for(int i=0;i<SIZE;i++) - printf("array[i]:%f\n",array[i]); -} - -int cmp(const void *ptr1, const void *ptr2) { - const double *a=ptr1; - const double *b=ptr2; - if(*a==*b) - return 0; - else - if(*a<*b) - return -1; - else - return +1; -} - -int main(int argc, char *argv[]) { - - printf("Avant qsort\n\n"); - print_array(); - qsort(array,SIZE,sizeof(double),cmp); - printf("Après qsort\n\n"); - print_array(); - - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/Threads/S5-src/strip.c b/Theorie/Threads/S5-src/strip.c deleted file mode 100644 index 238480980fb8277719d9ea2576bb3633d01aff8e..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/strip.c +++ /dev/null @@ -1,53 +0,0 @@ -/************************************** - * strip.c - * - * Programme d'exemple de fonction avec char ** - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -int strip(char **str) { - int count=0; - char *c; - c=*str; - int len=strlen(c); - for(int i=0; i<len;i++) { - if(*c==' ') { - count++; - } - c++; - } - int removed=0; - c=*str; - char *string=(char *) malloc(sizeof(char)*count+1); - char *r=string; - for(int i=0; i<strlen(*str);i++) { - if(*c!=' ') { - *r=*c; - r++; - removed++; - } - c++; - } - *r='\0'; - *str=string; - return removed; -} - -int main(int argc, char *argv[]) { - char *s1=" lkslskldklqkds"; - char *s2="alkjlksj skdjlskd sqdlkj"; - char **s1ptr=&(s1); - char **s2ptr=&(s2); - int n1=strip(s1ptr); - printf("n1=%d, %s\n",n1,s1); - int n2=strip(s2ptr); - printf("n2=%d, %s\n",n2,s2); - - -} - - diff --git a/Theorie/Threads/S5-src/strsep.c b/Theorie/Threads/S5-src/strsep.c deleted file mode 100644 index a523cd67169889939873f47a484dc0f4f8f64f76..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/strsep.c +++ /dev/null @@ -1,46 +0,0 @@ -/************************************** - * stresep.c - * - * Implementation partielle de strtol - * - **************************************/ - -#include <stdlib.h> -#include <stdio.h> -#include <ctype.h> - -int mystrtol(const char *restrict str, - char **restrict endptr, - int base) { - - int val; - int i=0; - int err=0; - while(!err && *(str+i)!='\0') - { - if(!isdigit(*(str+i))) { - err=1; - *endptr=(char *)(str+i); - } - i++; - } - // ... - - return val; -} - - -int main(int argc, char *argv[]) -{ - char *p, *s; - long li; - s = "1252m"; - li = mystrtol(s,&p,10); - if(p!=NULL) { - printf("Caractère erronné : %c\n",*p); - // p pointe vers le caractère en erreur - } - printf("Valeur convertie : %s -> %ld\n",s,li); - return(EXIT_SUCCESS); - -} diff --git a/Theorie/Threads/S5-src/strtol.c b/Theorie/Threads/S5-src/strtol.c deleted file mode 100644 index b1755d6fa8bdd9d8dea44720458583bbe5539441..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/strtol.c +++ /dev/null @@ -1,34 +0,0 @@ -/************************************** - * strtol.c - * - * Programme d'exemple d'utilisation de strtol - * - **************************************/ -///AAA -#include <stdlib.h> -#include <stdio.h> - -int main(int argc, char *argv[]) { - - char *p, *s; - long li; - s = "1252"; - li = strtol(s,&p,10); - if(*p != '\0') { - printf("Caractère erronné : %c\n",*p); - // p pointe vers le caractère en erreur - } - printf("Valeur convertie : %s -> %ld\n",s,li); - - s = "12m52"; - li = strtol(s,&p,10); - if(*p != '\0') { - printf("Caractère erronné : %c\n",*p); - } - printf("Valeur convertie : %s -> %ld\n",s,li); - - return(EXIT_SUCCESS); -} - - - diff --git a/Theorie/Threads/S5-src/sudoku.c b/Theorie/Threads/S5-src/sudoku.c deleted file mode 100644 index 215e3e4e4857e09d450ceedcf2efc6765b16e5d6..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S5-src/sudoku.c +++ /dev/null @@ -1,99 +0,0 @@ -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - -#define SUDOKU_MAX (9) -#define SUDOKU_DIM (SUDOKU_MAX) -#define SUDOKU_BOX (3) - -typedef struct { - int grid[SUDOKU_DIM][SUDOKU_DIM]; -} sudoku_t; - -static sudoku_t sudokus[] = { - { /* First sudoku */ - .grid = { - {8, 1, 5, 3, 4, 2, 9, 6, 7}, - {6, 0, 9, 7, 8, 1, 4, 2, 0}, - {7, 4, 2, 5, 6, 9, 0, 8, 1}, - {3, 8, 4, 9, 0, 6, 5, 1, 2}, - {9, 7, 1, 2, 5, 4, 6, 3, 8}, - {5, 2, 6, 0, 3, 8, 7, 4, 9}, - {4, 0, 3, 8, 2, 7, 0, 9, 6}, - {2, 9, 7, 6, 1, 3, 8, 5, 4}, - {1, 6, 8, 4, 0, 5, 2, 7, 3}, - } - }, - /* TODO fill with new sudokus */ -}; - - -static void print_sudoku(sudoku_t *s) -{ - int i, j; - - for (i = 0; i < SUDOKU_DIM; ++i) { - if (!(i % SUDOKU_BOX)) - printf("+-------+-------+-------+\n"); - for (j = 0; j < SUDOKU_DIM; ++j) { - if (!(j % SUDOKU_BOX)) - printf("| "); - printf("%d ", s->grid[i][j]); - } - printf("|\n"); - } - printf("+-------+-------+-------+\n"); - fflush(stdout); -} - -static int validate_sudoku(sudoku_t *s) -{ - int i, j, k, l; - - /* check sum of rows and columns + check that they only - * contain once one number from [1, 9] */ - for (i = 0; i < SUDOKU_DIM; ++i) { - int used_row[SUDOKU_MAX]; - int used_col[SUDOKU_MAX]; - memset(used_row, 0, sizeof(used_row)); - memset(used_col, 0, sizeof(used_col)); - int sum_row = 0, sum_col = 0; - for (j = 0; j < SUDOKU_DIM; ++j) { - if (used_row[s->grid[i][j]-1] > 0) - return 0; - if (used_col[s->grid[j][i]-1] > 0) - return 0; - sum_row += s->grid[i][j]; - sum_col += s->grid[j][i]; - used_row[s->grid[i][j]-1]++; - used_col[s->grid[j][i]-1]++; - } - if (sum_row != 45 || sum_col != 45) - return 0; - } - - /* check sum of boxes */ - for (k = 0; k < SUDOKU_DIM / SUDOKU_BOX; ++k) { - for (l = 0; l < SUDOKU_DIM / SUDOKU_BOX; ++l) { - int sum = 0; - for (i = 0; i < SUDOKU_BOX; ++i) - for (j = 0; j < SUDOKU_BOX; ++j) - sum += s->grid[SUDOKU_BOX * k + i][SUDOKU_BOX * l + j]; - if (sum != 45) - return 0; - } - } - - - return 1; -} - - -int main(int argc, char *argv[]) -{ - /* A COMPLETER */ - print_sudoku(&sudokus[0]); - - return 0; -} diff --git a/Theorie/Threads/S6-fig/figures-001-c.png b/Theorie/Threads/S6-fig/figures-001-c.png deleted file mode 100644 index 48c5aa499b47647fd9ccb59496550b0f40d8f800..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/S6-fig/figures-001-c.png and /dev/null differ diff --git a/Theorie/Threads/S6-fig/figures-002-c.png b/Theorie/Threads/S6-fig/figures-002-c.png deleted file mode 100644 index 5d1267967d4acc5fd956cb4cece893c0da64518a..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/S6-fig/figures-002-c.png and /dev/null differ diff --git a/Theorie/Threads/S6-fig/figures-003-c.png b/Theorie/Threads/S6-fig/figures-003-c.png deleted file mode 100644 index 7cdc9d1c9bd0d7d6fd0498754a655a427d51190b..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/S6-fig/figures-003-c.png and /dev/null differ diff --git a/Theorie/Threads/S6-fig/figures.001.png b/Theorie/Threads/S6-fig/figures.001.png deleted file mode 100644 index 0205872366cac8d88947e84333f4f8bd7efdce36..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/S6-fig/figures.001.png and /dev/null differ diff --git a/Theorie/Threads/S6-fig/figures.002.png b/Theorie/Threads/S6-fig/figures.002.png deleted file mode 100644 index 37d158236c459e9056cf020760120c6939bdcf6f..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/S6-fig/figures.002.png and /dev/null differ diff --git a/Theorie/Threads/S6-fig/figures.003.png b/Theorie/Threads/S6-fig/figures.003.png deleted file mode 100644 index 577900fb56fe8884027f5c98c054993f60a4c217..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/S6-fig/figures.003.png and /dev/null differ diff --git a/Theorie/Threads/S6-src/Makefile b/Theorie/Threads/S6-src/Makefile deleted file mode 100644 index 2aa4fb2bec558ba3a7ce233ec09acd46ad48165f..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S6-src/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# -# Makefile for source code -# -# Builds all .c files, assuming they are all independant and runs them -# to collect the output on stdout -# -# Automatically builds some of the examples to be included in the text -# - -GCC = gcc - -CFLAGS = -Wall -std=c99 -LDFLAGS = -lpthread - -ASMFLAGS = -Wall -std=c99 -O0 -fverbose-asm -fno-stack-protector -m32 -S - -CFILES := $(patsubst %.c,%.exe,$(wildcard *.c)) -ASMFILES := $(patsubst %.c,%.s,$(wildcard *.c)) -OUTPUT := $(patsubst %.c,%.out,$(wildcard *.c)) - - -all: ${CFILES} ${OUTPUT} - -%.s: %.c - @echo compiling $< - $(GCC) $(ASMFLAGS) $< - -%.exe: %.c - @echo compiling $< - $(GCC) $(CFLAGS) -o $@ $< $(LDFLAGS) - -%.out: %.exe - rm -f $@ - @echo executing $< - ./$< >$@ - diff --git a/Theorie/Threads/S6-src/arraylist.c b/Theorie/Threads/S6-src/arraylist.c deleted file mode 100644 index 406b7a1d8322bf033f0bb8d33d1ef48b6b65ac13..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S6-src/arraylist.c +++ /dev/null @@ -1,53 +0,0 @@ -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> - -#define N_THREADS 4 -#define LIST_SIZE 1000 -#define N_RAND 100000 - -static struct { - pthread_mutex_t mutex; - int val; -} list[LIST_SIZE]; - -static void *thread_random(void *arg) -{ - int i, r; - - for (i = 0; i < N_RAND; ++i) { - r = rand() % LIST_SIZE; - - pthread_mutex_lock(&list[r].mutex); - list[r].val++; - pthread_mutex_unlock(&list[r].mutex); - } - - return NULL; -} - - -int main (int argc, char const *argv[]) -{ - int i, sum; - pthread_t threads[N_THREADS]; - - // init elements mutexes - for (i = 0; i < LIST_SIZE; ++i) - pthread_mutex_init(&list[i].mutex, NULL); - - for (i = 0; i < N_THREADS; ++i) - pthread_create(&threads[i], NULL, thread_random, NULL); - - for (i = 0; i < N_THREADS; ++i) - pthread_join(threads[i], NULL); - - sum = 0; - for (i = 0; i < LIST_SIZE; ++i) { - sum += list[i].val; - pthread_mutex_destroy(&list[i].mutex); - } - printf("Sum of all elements: %d =?= %d\n", sum, N_THREADS * N_RAND); - - return 0; -} diff --git a/Theorie/Threads/S6-src/arraylist2.c b/Theorie/Threads/S6-src/arraylist2.c deleted file mode 100644 index 07ad5d48bf820f56ba3a926e92153dd15d2b2b5d..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S6-src/arraylist2.c +++ /dev/null @@ -1,50 +0,0 @@ -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> - -#define N_THREADS 4 -#define LIST_SIZE 1000 -#define N_RAND 100000 - -pthread_mutex_t mutex; -static int list[LIST_SIZE]; - -static void *thread_random(void *arg) -{ - int i, r; - - for (i = 0; i < N_RAND; ++i) { - r = rand() % LIST_SIZE; - - pthread_mutex_lock(&mutex); - list[r]++; - pthread_mutex_unlock(&mutex); - } - - return NULL; -} - - -int main (int argc, char const *argv[]) -{ - int i, sum; - pthread_t threads[N_THREADS]; - - // init elements mutex - pthread_mutex_init(&mutex, NULL); - - for (i = 0; i < N_THREADS; ++i) - pthread_create(&threads[i], NULL, thread_random, NULL); - - for (i = 0; i < N_THREADS; ++i) - pthread_join(threads[i], NULL); - - sum = 0; - pthread_mutex_destroy(&mutex); - for (i = 0; i < LIST_SIZE; ++i) - sum += list[i]; - - printf("Sum of all elements: %d =?= %d\n", sum, N_THREADS * N_RAND); - - return 0; -} diff --git a/Theorie/Threads/S6-src/pthread-mutex-perf.c b/Theorie/Threads/S6-src/pthread-mutex-perf.c deleted file mode 100644 index 63eab9f09c8cc776794aa0309a4f483c1ca57720..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S6-src/pthread-mutex-perf.c +++ /dev/null @@ -1,116 +0,0 @@ -/************************************** - * pthread-mutex.c - * - * Programme d'exemple de pthread avec - * utilisation de mutex pour éviter une - * violation de section critique - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <sys/time.h> - -/* Return t2-t1 in microseconds */ -long timeval_diff(struct timeval *t2, struct timeval *t1) -{ - long diff = (t2->tv_usec + 1000000 * t2->tv_sec) - (t1->tv_usec + 1000000 * t1->tv_sec); - return (diff); -} - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -///AAA -#include <pthread.h> -#define LOOP 40000 -#define LOOP_CRITIQUE 40000 -#define N 4 - -int percent; // pourcentage de temps en section critique -int nthreads; // nombre de threads -pthread_mutex_t mutex; - -void critique() { - long j=0; - for(int i=0;i<(LOOP_CRITIQUE*percent)/100;i++) { - j+=i; - // ... - } -} - -void noncritique() { - int j=0; - for(int i=0;i<(LOOP_CRITIQUE*(100-percent))/100;i++) { - j-=i; - // ... - } -} - - -void *func(void * param) { - for(int j=0;j<LOOP/nthreads;j++) { - pthread_mutex_lock(&mutex); - critique(); - pthread_mutex_unlock(&mutex); - noncritique(); - } - return(NULL); -} - -int main (int argc, char *argv[]) { - int err; - struct timeval tvStart, tvEnd; - long mesures[N]; - - if(argc!=3) - return(EXIT_FAILURE); - - char *endptr; - percent=strtol(argv[1],&endptr,10); - nthreads=strtol(argv[2],&endptr,10); - - pthread_t thread[nthreads]; - - err=pthread_mutex_init( &mutex, NULL); - if(err!=0) - error(err,"pthread_mutex_init"); - - for (int j=0;j<N;j++) { - - err=gettimeofday(&tvStart, NULL); - if(err!=0) - exit(EXIT_FAILURE); - - for(int i=0;i<nthreads;i++) { - err=pthread_create(&(thread[i]),NULL,&func,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - for(int i=nthreads-1;i>=0;i--) { - err=pthread_join(thread[i],NULL); - if(err!=0) - error(err,"pthread_join"); - } - err=gettimeofday(&tvEnd, NULL); - if(err!=0) - exit(EXIT_FAILURE); - - mesures[i]=timeval_diff(&tvEnd, &tvStart); - sum+=mesures[i]; - - } - printf("%d, %d, %ld\n",nthreads,percent,sum/N); - - err=pthread_mutex_destroy(&mutex); - if(err!=0) - error(err,"pthread_destroy"); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S6-src/pthread-mutex.c b/Theorie/Threads/S6-src/pthread-mutex.c deleted file mode 100644 index 891d1cf91baf1c29fe8e001b2419febe1a3bc673..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S6-src/pthread-mutex.c +++ /dev/null @@ -1,75 +0,0 @@ -/************************************** - * pthread-mutex.c - * - * Programme d'exemple de pthread avec - * utilisation de mutex pour éviter une - * violation de section critique - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -///AAA -#include <pthread.h> -#define NTHREADS 4 - -long global=0; -pthread_mutex_t mutex_global; - -int increment(int i) { - return i+1; -} - -void *func(void * param) { - int err; - for(int j=0;j<1000000;j++) { - err=pthread_mutex_lock(&mutex_global); - if(err!=0) - error(err,"pthread_mutex_lock"); - global=increment(global); - err=pthread_mutex_unlock(&mutex_global); - if(err!=0) - error(err,"pthread_mutex_unlock"); - } - return(NULL); -} - -int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - - err=pthread_mutex_init( &mutex_global, NULL); - if(err!=0) - error(err,"pthread_mutex_init"); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&func,NULL); - if(err!=0) - error(err,"pthread_create"); - } - for(int i=0; i<1000000000;i++) { /*...*/ } - - for(int i=NTHREADS-1;i>=0;i--) { - err=pthread_join(thread[i],NULL); - if(err!=0) - error(err,"pthread_join"); - } - - err=pthread_mutex_destroy(&mutex_global); - if(err!=0) - error(err,"pthread_mutex_destroy"); - - printf("global: %ld\n",global); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S6-src/pthread-mutex.out b/Theorie/Threads/S6-src/pthread-mutex.out deleted file mode 100644 index f9d92b29b14dfabfaf0ba54735e13a1abc82cd82..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S6-src/pthread-mutex.out +++ /dev/null @@ -1 +0,0 @@ -global: 4000000 diff --git a/Theorie/Threads/S6-src/pthread-neg2.c b/Theorie/Threads/S6-src/pthread-neg2.c deleted file mode 100644 index efc0b74ff6bddae9c8d8169aaed7cccfece1edd0..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S6-src/pthread-neg2.c +++ /dev/null @@ -1,51 +0,0 @@ -/************************************** - * pthread-neg.c - * - * Programme d'exemple de pthread utilisant les - * arguments et retournant une valeur - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -///AAA -#define NTHREADS 4 -void *neg (void * param) { - int *l; - l=(int *) param; - int *r=(int *)malloc(sizeof(int)); - *r=-*l; - return ((void *) r); -} - -int main (int argc, char *argv[]) { - pthread_t threads[NTHREADS]; - int arg[NTHREADS]; - int err; - - for(long i=0;i<NTHREADS;i++) { - arg[i]=i; - err=pthread_create(&(threads[i]),NULL,&neg,(void *) &(arg[i])); - if(err!=0) - error(err,"pthread_create"); - } - - for(int i=0;i<NTHREADS;i++) { - int *r; - err=pthread_join(threads[i],(void **)&r); - printf("Resultat[%d]=%d\n",i,*r); - free(r); - if(err!=0) - error(err,"pthread_join"); - } - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S6-src/pthread-neg2.out b/Theorie/Threads/S6-src/pthread-neg2.out deleted file mode 100644 index d5823dd8ef29e10d55c1c0b0085387ce326e5d98..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S6-src/pthread-neg2.out +++ /dev/null @@ -1,4 +0,0 @@ -Resultat[0]=0 -Resultat[1]=-1 -Resultat[2]=-2 -Resultat[3]=-3 diff --git a/Theorie/Threads/S6-src/pthread-philo.c b/Theorie/Threads/S6-src/pthread-philo.c deleted file mode 100644 index 33d63c137ecf32e6359464660adb269648fdfb91..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S6-src/pthread-philo.c +++ /dev/null @@ -1,68 +0,0 @@ -/************************************** - * pthread-philo.c - * - * Programme d'exemple de pthread avec - * philosophes qui dinent et mutex - * - **************************************/ - -///AAA -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <unistd.h> - -#define PHILOSOPHES 3 - -pthread_t phil[PHILOSOPHES]; -pthread_mutex_t baguette[PHILOSOPHES]; - -void mange(int id) { - printf("Philosophe [%d] mange\n",id); - for(int i=0;i< rand(); i++) { - // philosophe mange - } -} - -void* philosophe ( void* arg ) -{ - int *id=(int *) arg; - int left = *id; - int right = (left + 1) % PHILOSOPHES; - while(true) { - printf("Philosophe [%d] pense\n",*id); - pthread_mutex_lock(&baguette[left]); - printf("Philosophe [%d] possède baguette gauche [%d]\n",*id,left); - pthread_mutex_lock(&baguette[right]); - printf("Philosophe [%d] possède baguette droite [%d]\n",*id,right); - mange(*id); - pthread_mutex_unlock(&baguette[left]); - printf("Philosophe [%d] a libéré baguette gauche [%d]\n",*id,left); - pthread_mutex_unlock(&baguette[right]); - printf("Philosophe [%d] a libéré baguette droite [%d]\n",*id,right); - } - return (NULL); -} -///BBB -int main ( int argc, char *argv[]) -{ - long i; - int id[PHILOSOPHES]; - - srand(getpid()); - - for (i = 0; i < PHILOSOPHES; i++) - id[i]=i; - - for (i = 0; i < PHILOSOPHES; i++) - pthread_mutex_init( &baguette[i], NULL); - - for (i = 0; i < PHILOSOPHES; i++) - pthread_create(&phil[i], NULL, philosophe, (void*)&(id[i]) ); - - for (i = 0; i < PHILOSOPHES; i++) - pthread_join(phil[i], NULL); - - return (EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S6-src/pthread-philo2.c b/Theorie/Threads/S6-src/pthread-philo2.c deleted file mode 100644 index 1e4113b83c358a1e84571aa1ce5f792a9bc1d504..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S6-src/pthread-philo2.c +++ /dev/null @@ -1,95 +0,0 @@ -/************************************** - * pthread-philo2.c - * - * Programme d'exemple de pthread avec - * philosophes qui dinent et mutex - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> - -#define PHILOSOPHES 3 - -static pthread_mutex_t baguette[PHILOSOPHES]; - - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -void mange(int id) { - printf("Philosophe [%d] mange\n",id); - for(int i=0;i< rand(); i++) { - // philosophe mange - } -} - -///AAA - -void* philosophe ( void* arg ) -{ - int *id=(int *) arg; - int left = *id; - int right = (left + 1) % PHILOSOPHES; - while(true) { - // philosophe pense - if(left<right) { - pthread_mutex_lock(&baguette[left]); - pthread_mutex_lock(&baguette[right]); - } - else { - pthread_mutex_lock(&baguette[right]); - pthread_mutex_lock(&baguette[left]); - } - mange(*id); - pthread_mutex_unlock(&baguette[left]); - pthread_mutex_unlock(&baguette[right]); - } - return (NULL); -} -///BBB -int main ( int argc, char *argv[]) -{ - int i; - int id[PHILOSOPHES]; - int err; - pthread_t phil[PHILOSOPHES]; - - srand(getpid()); - - for (i = 0; i < PHILOSOPHES; i++) - id[i]=i; - - for (i = 0; i < PHILOSOPHES; i++) { - err=pthread_mutex_init( &baguette[i], NULL); - if(err!=0) - error(err,"pthread_mutex_init"); - } - - for (i = 0; i < PHILOSOPHES; i++) { - err=pthread_create(&phil[i], NULL, philosophe, (void*)&(id[i]) ); - if(err!=0) - error(err,"pthread_create"); - } - - for (i = 0; i < PHILOSOPHES; i++) { - pthread_join(phil[i], NULL); - if(err!=0) - error(err,"pthread_join"); - } - - for (i = 0; i < PHILOSOPHES; i++) { - pthread_mutex_destroy(&baguette[i]); - if(err!=0) - error(err,"pthread_mutex_destroy"); - } - - return (EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S6-src/pthread-spin.c b/Theorie/Threads/S6-src/pthread-spin.c deleted file mode 100644 index b4839da01400e690dfea38acab2bc7f8447fd916..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S6-src/pthread-spin.c +++ /dev/null @@ -1,66 +0,0 @@ -/************************************** - * pthread-spin.c - * - * Programme d'exemple de pthread avec - * utilisation de spinlock pour éviter une - * violation de section critique - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -///AAA - -#define NTHREADS 4 - -long global=0; - -static pthread_spinlock_t spinlock_global; - - -int increment(int i) { - return i+1; -} - -void *func(void * param) { - for(int j=0;j<1000000;j++) { - pthread_spin_lock(&spinlock_global); - global=increment(global); - pthread_spin_unlock(&spinlock_global); - } - return(NULL); -} - -int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - - pthread_spin_init( &spinlock_global, 0); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&func,NULL); - if(err!=0) - error(err,"pthread_create"); - } - for(int i=0; i<1000000000;i++) { /*...*/ } - - for(int i=NTHREADS-1;i>=0;i--) { - err=pthread_join(thread[i],NULL); - if(err!=0) - error(err,"pthread_join"); - } - - printf("global: %ld\n",global); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S6-src/pthread-test-if.c b/Theorie/Threads/S6-src/pthread-test-if.c deleted file mode 100644 index f3fa8e26e7d22850e8fdeb06f5b9725a6f8d7a81..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S6-src/pthread-test-if.c +++ /dev/null @@ -1,77 +0,0 @@ -/************************************** - * pthread-test.c - * - * Programme d'exemple de pthread avec condition de course - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - - -///AAA - -long global=0; -int even=0; -int odd=0; - -void test_even(int i) { - if((i%2)==0) - even++; -} - -int increment(int i) { - return i+1; -} - -void *inc(void * param) { - for(int j=0;j<1000000;j++) { - global=increment(global); - } - pthread_exit(NULL); -} - -void *is_even(void * param) { - for(int j=0;j<1000000;j++) { - test_even(global); - } - pthread_exit(NULL); -} -///BBB -int main (int argc, char *argv[]) { - pthread_t thread_inc; - pthread_t thread_even; - int err; - - err=pthread_create(&(thread_inc),NULL,&inc,NULL); - if(err!=0) { - error(err,"pthread_create"); - } - - err=pthread_create(&(thread_even),NULL,&is_even,NULL); - if(err!=0) { - error(err,"pthread_create"); - } - - err=pthread_join(thread_inc,NULL); - if(err!=0) { - error(err,"pthread_join"); - } - - err=pthread_join(thread_even,NULL); - if(err!=0) { - error(err,"pthread_join"); - } - - printf("global: %ld, even:%d\n",global,even); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S6-src/pthread.c b/Theorie/Threads/S6-src/pthread.c deleted file mode 100644 index 9f781d0c1025d8cf28ee58734a6dc903fa44fd32..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S6-src/pthread.c +++ /dev/null @@ -1,71 +0,0 @@ -/************************************** - * pthread.c - * - * Programme d'exemple de pthread - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -int global=0; - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -void *thread_first(void * param) { - global++; - return(NULL); -} - -void *thread_second(void * param) { - global++; - pthread_exit(NULL); -} - -int main (int argc, char *argv[]) { - - ///AAA - pthread_t first; - pthread_attr_t attr_first; - size_t stacksize; - - int err; - - err= pthread_attr_init(&attr_first); - if(err!=0) - error(err,"pthread_attr_init"); - - err= pthread_attr_getstacksize(&attr_first,&stacksize); - if(err!=0) - error(err,"pthread_attr_getstacksize"); - - printf("Taille par défaut du stack : %ld\n",stacksize); - - stacksize=65536; - - err= pthread_attr_setstacksize(&attr_first,stacksize); - if(err!=0) - error(err,"pthread_attr_setstacksize"); - - err=pthread_create(&first,&attr_first,&thread_first,NULL); - if(err!=0) - error(err,"pthread_create"); - ///BBB - - for(int i=0; i<1000000000;i++) { /*...*/ } - - - err=pthread_join(first,NULL); - if(err!=0) - error(err,"pthread_join"); - - printf("global: %d\n",global); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S6-src/thread_crash.c b/Theorie/Threads/S6-src/thread_crash.c deleted file mode 100644 index b9f34e91dea12772b85582bcec89d1589a73245c..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S6-src/thread_crash.c +++ /dev/null @@ -1,34 +0,0 @@ -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> - -#define N_THREADS 3 - -pthread_mutex_t global_mutex; - -static void *thread_work(void *arg) -{ - pthread_mutex_lock(&global_mutex); - - /* Do some work here */ - - pthread_exit(NULL); - pthread_mutex_unlock(&global_mutex); -} - - -int main (int argc, char const *argv[]) -{ - int i; - pthread_t threads[N_THREADS]; - - pthread_mutex_init(&global_mutex, NULL); - - for (i = 0; i < N_THREADS; ++i) - pthread_create(&threads[i], NULL, thread_work, NULL); - - for (i = 0; i < N_THREADS; ++i) - pthread_join(threads[i], NULL); - - return 0; -} diff --git a/Theorie/Threads/S7-src/Makefile b/Theorie/Threads/S7-src/Makefile deleted file mode 100644 index 7a5a1577fe951aeab09924492e8d2e02b4a8efc8..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S7-src/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# -# Makefile for source code -# -# Builds all .c files, assuming they are all independant and runs them -# to collect the output on stdout -# -# Automatically builds some of the examples to be included in the text -# - -GCC = gcc - -CFLAGS = -Wall -std=c99 -g -LDFLAGS = -lpthread - -ASMFLAGS = -Wall -std=c99 -O0 -fverbose-asm -fno-stack-protector -m32 -S - -CFILES := $(patsubst %.c,%.exe,$(wildcard *.c)) -ASMFILES := $(patsubst %.c,%.s,$(wildcard *.c)) -OUTPUT := $(patsubst %.c,%.out,$(wildcard *.c)) - - -all: ${CFILES} ${OUTPUT} - -%.s: %.c - @echo compiling $< - $(GCC) $(ASMFLAGS) $< - -%.exe: %.c - @echo compiling $< - $(GCC) $(CFLAGS) -o $@ $< $(LDFLAGS) - -%.out: %.exe - rm -f $@ - @echo executing $< - ./$< >$@ - diff --git a/Theorie/Threads/S7-src/pthread-barrier.c b/Theorie/Threads/S7-src/pthread-barrier.c deleted file mode 100644 index 02033916baf1f9d687c07e963a78c77d0c7faf08..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S7-src/pthread-barrier.c +++ /dev/null @@ -1,70 +0,0 @@ -/************************************** - * pthread-barrier.c - * - * Programme d'exemple de barrières - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - -void phase1(void) -{ - // - return; -} - - -void phase2(void) -{ - // - return; -} - -///AAA -#define NTHREADS 4 -pthread_barrier_t rendezvous; - -void *compute(void * param) { - phase1(); - pthread_barrier_wait(&rendezvous); - phase2(); - return(NULL); -} - -int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - - err=pthread_barrier_init(&rendezvous, NULL,NTHREADS); - if(err!=0) { - error(err,"pthread_barrier_init"); - } - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,func[i],NULL); - if(err!=0) { - error(err,"pthread_create"); - } - } - - for(int i=0;i<NTHREADS;i++) { - err=pthread_join(thread[i],NULL); - if(err!=0) { - error(err,"pthread_join"); - } - } - pthread_barrier_destroy(&srendezvous); - if(err!=0) { - error(err,"pthread_barrier_destroy); - } - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/Threads/S7-src/pthread-id.c b/Theorie/Threads/S7-src/pthread-id.c deleted file mode 100644 index e72193fcd9e29cbc5a7c62ee9fb57bb68f75f3cf..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S7-src/pthread-id.c +++ /dev/null @@ -1,95 +0,0 @@ -/************************************** - * pthread-specific.c - * - * Programme d'exemple de pthread qui utilise une - * zone mémoire pour stocker des données - * spécifiques au thread - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -#define MAXNUM 1000 -#define NTHREADS 4 - -struct result { - long x; - long y; - long z; -}; - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - - -long power(long i, long j) { - long r=i; - while(j>0) { - r=r*i; - j--; - } - return r; -} - -void g(); - -void *f1( void* param) { - - printf("f1 a calculé %d" - return(NULL); -} - - -void *fermat (void * param) { - - struct result *r=(struct result *)malloc(sizeof(struct result)); - if(r==NULL) - error(-1,"malloc"); - - long n=(long) param; - for(long x=1;x<MAXNUM;x++) { - for(long y=1;y<MAXNUM;y++) { - for(int z=1;z<MAXNUM;z++) { - if( (power(x,n)+power(y,n))==power(z,n) ) { - r->x=x; - r->y=y; - r->z=z; - return((void *) r); - } - } - } - } - return(NULL); -} - -int main (int argc, char *argv[]) { - pthread_t threads[NTHREADS]; - int err; - - err=pthread_create(&(threads[i]),NULL,&fermat,(void *)(long) i+2); - if(err!=0) - error(err,"pthread_create"); - - - - - for(int i=0;i<NTHREADS;i++) { - void *p; - err=pthread_join(threads[i],(void **)&(p)); - - if(err!=0) - error(err,"pthread_create"); - //if(p!=NULL) { - //struct result r; - // r=(struct result) p; - //printf("Trouvé pour %d : x=%ld, y=%ld, z=%ld\n",i+2,r[i].x,r[i].y, r[i].z); - } - - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S7-src/pthread-philo-sem.c b/Theorie/Threads/S7-src/pthread-philo-sem.c deleted file mode 100644 index 8d27d804b61277834c87a0cbc9d095413a8076a8..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S7-src/pthread-philo-sem.c +++ /dev/null @@ -1,69 +0,0 @@ -/************************************** - * pthread-philo-sem.c - * - * Programme d'exemple de pthread avec - * philosophes qui dinent et sémaphores - * - **************************************/ - -///AAA -#include <pthread.h> -#include <semaphore.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <unistd.h> - -#define PHILOSOPHES 3 - -pthread_t phil[PHILOSOPHES]; -sem_t baguette[PHILOSOPHES]; - -void mange(int id) { - printf("Philosophe [%d] mange\n",id); - for(int i=0;i< rand(); i++) { - // philosophe mange - } -} - -void* philosophe ( void* arg ) -{ - int *id=(int *) arg; - int left = *id; - int right = (left + 1) % PHILOSOPHES; - while(true) { - printf("Philosophe [%d] pense\n",*id); - sem_wait(&baguette[left]); - printf("Philosophe [%d] possède baguette gauche [%d]\n",*id,left); - sem_wait(&baguette[right]); - printf("Philosophe [%d] possède baguette droite [%d]\n",*id,right); - mange(*id); - sem_post(&baguette[left]); - printf("Philosophe [%d] a libéré baguette gauche [%d]\n",*id,left); - sem_post(&baguette[right]); - printf("Philosophe [%d] a libéré baguette droite [%d]\n",*id,right); - } - return (NULL); -} -///BBB -int main ( int argc, char *argv[]) -{ - long i; - int id[PHILOSOPHES]; - - srand(getpid()); - - for (i = 0; i < PHILOSOPHES; i++) - id[i]=i; - - for (i = 0; i < PHILOSOPHES; i++) - sem_init( &baguette[i], 0 , 1); - - for (i = 0; i < PHILOSOPHES; i++) - pthread_create(&phil[i], NULL, philosophe, (void*)&(id[i]) ); - - for (i = 0; i < PHILOSOPHES; i++) - pthread_join(phil[i], NULL); - - return (EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S7-src/pthread-rw.c b/Theorie/Threads/S7-src/pthread-rw.c deleted file mode 100644 index 22ab9328c59805f43bba9f2804d8edbf3f295143..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S7-src/pthread-rw.c +++ /dev/null @@ -1,76 +0,0 @@ -/************************************** - * pthread-rw.c - * - * Programme d'exemple de pthread avec - * readers-writers lock - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdbool.h> -#include <unistd.h> -#include <sys/types.h> - -#define SIZE 1000000 -#define READERS 10 -#define WRITERS 2 -#define LOOP 10000 - - -pthread_t p[READERS+WRITERS]; -pthread_rwlock_t lock; - -volatile int v[SIZE]; - -void *writer( void *arg) -{ - for(int i=0;i<SIZE;i++) { - pthread_rwlock_wrlock(&lock); - v[i]=rand()%SIZE; - pthread_rwlock_wrunlock(&lock); - } - // ... - printf ("Writer %d terminé\n",gettid()); - return(NULL); - - -} -void* reader ( void* arg ) -{ - int result; - for(int i=0;i<LOOP;i++) { - int id=rand()%SIZE; - pthread_rwlock_rdlock(&lock); - result=v[id]; - pthread_rwlock_rdunlock(&lock); - } - // ... - printf ("Reader %d terminé\n",gettid()); - return(NULL); -} - -///BBB -int main ( int argc, char *argv[]) -{ - int i; - - srand(getpid()); - - pthread_rwlock_init(&lock, 0); - - for (i = 0; i < READERS+WRITERS; i++) { - if(i<READERS) - pthread_create(&p[i], NULL, reader, NULL ); - else - pthread_create(&p[i], NULL, writer, NULL ); - } - - for (i = 0; i < READERS+WRITERS; i++) - pthread_join(p[i], NULL); - - pthread_rwlock_destroy(&lock); - - return (EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S7-src/pthread-sem-before.c b/Theorie/Threads/S7-src/pthread-sem-before.c deleted file mode 100644 index fd4567586f1ccd5c72a0b7e29848e960b898c6d9..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S7-src/pthread-sem-before.c +++ /dev/null @@ -1,70 +0,0 @@ -/************************************** - * pthread-sem-before.c - * - * Programme d'exemple de sémaphores - * La fonction after ne peut s'exécuter - * q'après la fonction before - **************************************/ - -#include <pthread.h> -#include <semaphore.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - - -///AAA -#define NTHREADS 2 -sem_t semaphore; - -void *before(void * param) { - // do something - for(int j=0;j<1000000;j++) { - } - sem_post(&semaphore); - return(NULL); -} - -void *after(void * param) { - sem_wait(&semaphore); - // do something - for(int j=0;j<1000000;j++) { - } - return(NULL); -} - -int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - void * (* func[])(void *)={before, after}; - int err; - - err=sem_init(&semaphore, 0,0); - if(err!=0) { - error(err,"sem_init"); - } - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,func[i],NULL); - if(err!=0) { - error(err,"pthread_create"); - } - } - - for(int i=0;i<NTHREADS;i++) { - err=pthread_join(thread[i],NULL); - if(err!=0) { - error(err,"pthread_join"); - } - } - sem_destroy(&semaphore); - if(err!=0) { - error(err,"sem_destroy"); - } - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/Threads/S7-src/pthread-sem-before.out b/Theorie/Threads/S7-src/pthread-sem-before.out deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/Theorie/Threads/S7-src/pthread-sem.c b/Theorie/Threads/S7-src/pthread-sem.c deleted file mode 100644 index 28890557548e5cdba7a052918cd5febf8c4fbe57..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S7-src/pthread-sem.c +++ /dev/null @@ -1,64 +0,0 @@ -/************************************** - * pthread-semt.c - * - * Programme d'exemple de sémaphores - * - **************************************/ - -#include <pthread.h> -#include <semaphore.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -#define NTHREADS 4 - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - - -///AAA - -static sem_t semaphore; -long global=0; - -int increment(int i) { - return i+1; -} - -void *inc(void * param) { - for(int j=0;j<1000000;j++) { - sem_wait(&semaphore); - global=increment(global); - sem_post(&semaphore); - } - pthread_exit(NULL); -} - -int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - - sem_init(&semaphore, 0,1); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&inc,NULL); - if(err!=0) { - error(err,"pthread_create"); - } - } - - for(int i=0;i<NTHREADS;i++) { - err=pthread_join(thread[i],NULL); - if(err!=0) { - error(err,"pthread_join"); - } - } - sem_destroy(&semaphore); - printf("global: %ld\n",global); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S7-src/pthread-sem.out b/Theorie/Threads/S7-src/pthread-sem.out deleted file mode 100644 index cb6ea05e0fe7b70523a0556e88ea20481eb28b72..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S7-src/pthread-sem.out +++ /dev/null @@ -1 +0,0 @@ -global: 3837069 diff --git a/Theorie/Threads/S7-src/pthread-specific.c b/Theorie/Threads/S7-src/pthread-specific.c deleted file mode 100644 index 38a347a126aa561951e49e6e782aa2a41eb8dd55..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S7-src/pthread-specific.c +++ /dev/null @@ -1,56 +0,0 @@ -/************************************** - * pthread-specific.c - * - * Programme d'exemple de pthread qui utilise une - * zone mémoire pour stocker des données - * spécifiques au thread - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - - -///AAA -#define LOOP 1000000 -#define NTHREADS 4 - -__thread int count=0; -int global_count=0; - -void *f( void* param) { - for(int i=0;i<LOOP;i++) { - count++; - global_count=global_count-1; - } - printf("Valeurs : count=%d, global_count=%d\n",count, global_count); - return(NULL); -} - -int main (int argc, char *argv[]) { - pthread_t threads[NTHREADS]; - int err; - - for(int i=0;i<NTHREADS;i++) { - count=i; // local au thread du programme principal - err=pthread_create(&(threads[i]),NULL,&f,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - for(int i=0;i<NTHREADS;i++) { - err=pthread_join(threads[i],NULL); - if(err!=0) - error(err,"pthread_create"); - } - - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/Threads/S7-src/pthread-specific.out b/Theorie/Threads/S7-src/pthread-specific.out deleted file mode 100644 index f0eb4d4432d5c6cd658ac2ff16f2487c2334216f..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S7-src/pthread-specific.out +++ /dev/null @@ -1,4 +0,0 @@ -Valeurs : count=1000000, global_count=-870754 -Valeurs : count=1000000, global_count=-880737 -Valeurs : count=1000000, global_count=-916383 -Valeurs : count=1000000, global_count=-923423 diff --git a/Theorie/Threads/S7-src/pthread-specific2.c b/Theorie/Threads/S7-src/pthread-specific2.c deleted file mode 100644 index 47cec0223ad8ae4f692c67f61fc754d46c731cfa..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S7-src/pthread-specific2.c +++ /dev/null @@ -1,77 +0,0 @@ -/************************************** - * pthread-specific.c - * - * Programme d'exemple de pthread qui utilise une - * zone mémoire pour stocker des données - * spécifiques au thread - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -void error(int err, char *msg) { - fprintf(stderr,"%s a retourné %d, message d'erreur : %s\n",msg,err,strerror(errno)); - exit(EXIT_FAILURE); -} - - -///AAA -#define LOOP 1000000 -#define NTHREADS 4 - -pthread_key_t count; -int global_count=0; - -void g(void ) { - void * data=pthread_getspecific(count); - if(data==NULL) - error(-1,"pthread_getspecific"); - int *count_ptr=(int *)data; - for(int i=0;i<LOOP;i++) { - *count_ptr=*(count_ptr)+1; - global_count=global_count-1; - } -} - -void *f( void* param) { - int err; - int *int_ptr=malloc(sizeof(int)); - *int_ptr=0; - err=pthread_setspecific(count, (void *)int_ptr); - if(err!=0) - error(err,"pthread_setspecific"); - g(); - printf("Valeurs : count=%d, global_count=%d\n",*int_ptr, global_count); - free(int_ptr); - return(NULL); -} - -int main (int argc, char *argv[]) { - pthread_t threads[NTHREADS]; - int err; - - err=pthread_key_create(&(count),NULL); - if(err!=0) - error(err,"pthread_key_create"); - - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(threads[i]),NULL,&f,NULL); - if(err!=0) - error(err,"pthread_create"); - } - - for(int i=0;i<NTHREADS;i++) { - err=pthread_join(threads[i],NULL); - if(err!=0) - error(err,"pthread_create"); - } - err=pthread_key_delete(count); - if(err!=0) - error(err,"pthread_key_delete"); - - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/Threads/S7-src/pthread-specific2.out b/Theorie/Threads/S7-src/pthread-specific2.out deleted file mode 100644 index c717fae88a16bed9a2e7040da20f76e80ee5e0be..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S7-src/pthread-specific2.out +++ /dev/null @@ -1,4 +0,0 @@ -Valeurs : count=1000000, global_count=-970217 -Valeurs : count=1000000, global_count=-2967957 -Valeurs : count=1000000, global_count=-2978745 -Valeurs : count=1000000, global_count=-3135210 diff --git a/Theorie/Threads/S7-src/reentrant.c b/Theorie/Threads/S7-src/reentrant.c deleted file mode 100644 index 89743445840f46c42dd7ec9331d6843bec7f5630..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S7-src/reentrant.c +++ /dev/null @@ -1,63 +0,0 @@ -/************************************** - * reentrant.c - * - * Programme d'exemple de fonctions reentrantes - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> - - -///AAA -#include <stdint.h> -#define SIZE 10000 - -int g_max=INT32_MIN; -int v[SIZE]; - -int max_vector(int n, int *v) { - int max=INT32_MIN; - for(int i=0;i<n;i++) { - if(v[i]>max) - max=v[i]; - } - return max; -} - -int max_global(int *v) { - if (*v>g_max) { - g_max=*v; - } - return(g_max); -} - -int max_static(int *v){ - static int s_max=INT32_MIN; - if (*v>s_max) { - s_max=*v; - } - return(s_max); -} - -///BBB - -int main (int argc, char *argv[]) { - srand((int) getpid()); - for (int i=0;i<SIZE;i++) { - v[i]=rand()%1000000; - } - printf("max_vector: %d\n",max_vector(SIZE,v)); - int max_g; - int max_s; - for(int i=0;i<SIZE;i++) { - max_g=max_global(&v[i]); - max_s=max_static(&v[i]); - } - printf("max_global: %d\n",max_g); - printf("max_static: %d\n",max_s); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S7-src/strerror.c b/Theorie/Threads/S7-src/strerror.c deleted file mode 100644 index a1571c52fdea21e2ad2003a79ccaa430417a4ed0..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S7-src/strerror.c +++ /dev/null @@ -1,21 +0,0 @@ -/************************************** - * strerror.c - * - * Programme d'exemple strerror - * - **************************************/ - -#include <pthread.h> -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> - -int main (int argc, char *argv[]) { - - for(int i=0; i<999;i++) { - printf("strerror[%d] est à l'adresse %p\n",i,strerror(i)); - }; - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S8-src/Makefile b/Theorie/Threads/S8-src/Makefile deleted file mode 100644 index 7a5a1577fe951aeab09924492e8d2e02b4a8efc8..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# -# Makefile for source code -# -# Builds all .c files, assuming they are all independant and runs them -# to collect the output on stdout -# -# Automatically builds some of the examples to be included in the text -# - -GCC = gcc - -CFLAGS = -Wall -std=c99 -g -LDFLAGS = -lpthread - -ASMFLAGS = -Wall -std=c99 -O0 -fverbose-asm -fno-stack-protector -m32 -S - -CFILES := $(patsubst %.c,%.exe,$(wildcard *.c)) -ASMFILES := $(patsubst %.c,%.s,$(wildcard *.c)) -OUTPUT := $(patsubst %.c,%.out,$(wildcard *.c)) - - -all: ${CFILES} ${OUTPUT} - -%.s: %.c - @echo compiling $< - $(GCC) $(ASMFLAGS) $< - -%.exe: %.c - @echo compiling $< - $(GCC) $(CFLAGS) -o $@ $< $(LDFLAGS) - -%.out: %.exe - rm -f $@ - @echo executing $< - ./$< >$@ - diff --git a/Theorie/Threads/S8-src/Makefile-lib b/Theorie/Threads/S8-src/Makefile-lib deleted file mode 100644 index 6cbf869aa0354706af10c9a5ddd0b3bb98e9ab15..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/Makefile-lib +++ /dev/null @@ -1,30 +0,0 @@ -# -# Makefile for library imax and imath -# - -GCC = gcc -AR = ar -ARFLAGS = -cvq -CFLAGS = -Wall -std=c99 -g -c -LDFLAGS = --static -g - -all: imath - -imax.o: imax.c - @echo compiling imax - $(GCC) $(CFLAGS) imax.c - -libimax.a: imax.o - @echo building libimax - $(AR) $(ARFLAGS) libimax.a imax.o - -imath.o: imath.c imax.h - @echo compiling imath.o - $(GCC) $(CFLAGS) imath.c - -imath: imath.o libimax.a - @echo building imath - $(GCC) $(LDFLAGS) -o imath libimax.a imath.o - -clean: - rm imath libimax.a imax.o imath.o diff --git a/Theorie/Threads/S8-src/atexit.c b/Theorie/Threads/S8-src/atexit.c deleted file mode 100644 index deb7367e8301e57e585a929ad7c0e54a913b92b6..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/atexit.c +++ /dev/null @@ -1,27 +0,0 @@ -/************************************** - * atexit.c - * - * Programme d'exemple d'utilisation de - * atexit - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> - -void e1() { - printf("Exécution de la fonction e1\n"); -} - -int main (int argc, char *argv[]) { - - int err; - err=atexit(e1); - if(err==-1) { - perror("atexit"); - exit(EXIT_FAILURE); - } - return(EXIT_SUCCESS); - -} -///BBB diff --git a/Theorie/Threads/S8-src/execve-long.c b/Theorie/Threads/S8-src/execve-long.c deleted file mode 100644 index 0b5e7916dd31dee8385f92d3db6df24818c8c01e..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/execve-long.c +++ /dev/null @@ -1,32 +0,0 @@ -/************************************** - * execve-long.c - * - * Programme d'exemple pour execve - * - *************************************/ - -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> - -extern char **environ; - -int main (int argc, char *argv[]) { - - if(argc==1) { - fprintf(stderr,"Erreur, nom de l'exécutable nécessaire\n"); - return(EXIT_FAILURE); - } - - int err=execve(argv[1], &(argv[1]), environ); - if(err!=0) { - fprintf(stderr,"Impossible d'exécuter %s, erreur %d %s\n",argv[1],err, strerror(errno)); - exit(EXIT_FAILURE); - } - return(EXIT_SUCCESS); - -} - diff --git a/Theorie/Threads/S8-src/execve.c b/Theorie/Threads/S8-src/execve.c deleted file mode 100644 index 64367f79f0b8db5996b6b5a25a57b04206b62a7c..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/execve.c +++ /dev/null @@ -1,30 +0,0 @@ -/************************************** - * execve.c - * - * Programme d'exemple pour execve - * - *************************************/ - -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -int main (int argc, char *argv[]) { - - char *arguments[]={"expr", "1", "+", "2", NULL}; - char *environnement[]={"LANG=fr",NULL}; - - printf("Exécution du processus %d\n",getpid()); - printf("Exécution de /usr/bin/expr\n"); - int err=execve("/usr/bin/expr", arguments, environnement); - if(err!=0) { - perror("execve"); - exit(EXIT_FAILURE); - } - // jamais atteint - printf("Ce message ne sera jamais affiché\n"); - return(EXIT_SUCCESS); - -} - diff --git a/Theorie/Threads/S8-src/execve.out b/Theorie/Threads/S8-src/execve.out deleted file mode 100644 index 00750edc07d6415dcc07ae0351e9397b0222b7ba..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/execve.out +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/Theorie/Threads/S8-src/fork-buf.c b/Theorie/Threads/S8-src/fork-buf.c deleted file mode 100644 index 718004df8a0181b578017599dee900be7c67bd8f..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/fork-buf.c +++ /dev/null @@ -1,58 +0,0 @@ -/************************************** - * fork.c - * - * Programme d'exemple d'utilisation de - * fork - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <time.h> - - -void output(char c) { - printf("Processus : %d\n",getpid()); - srand(getpid()+time(NULL)); - for(int i=0;i<60;i++) { - putchar(c); - int err=usleep((unsigned int) (rand()%10000)); - if(err<0) { - perror("usleep"); - exit(EXIT_FAILURE); - } - } -} - -int main (int argc, char *argv[]) { - - if(argc > 1) { - setbuf(stdout,NULL); - } - - pid_t pid; - - pid=fork(); - if (pid==-1) { - // erreur à l'exécution de fork - perror("fork"); - exit(EXIT_FAILURE); - } - // pas d'erreur - if (pid==0) { - // processus fils - output('f'); - return(EXIT_SUCCESS); - } - else { - // processus père - output('P'); - printf("\n"); - sleep(1); - // ... - return(EXIT_SUCCESS); - } -} -///BBB diff --git a/Theorie/Threads/S8-src/fork-execve.c b/Theorie/Threads/S8-src/fork-execve.c deleted file mode 100644 index 52e771c15271001b8c48b511236e847bb3b1c231..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/fork-execve.c +++ /dev/null @@ -1,57 +0,0 @@ -/************************************** - * fork-execve.c - * - * Programme d'exemple d'utilisation de - * fork et execve - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/wait.h> -#include <sys/types.h> - - -int main (int argc, char *argv[]) { - int status; - pid_t pid; - - pid=fork(); - - if (pid==-1) { - // erreur à l'exécution de fork - perror("fork"); - exit(EXIT_FAILURE); - } - // pas d'erreur - if (pid==0) { - // fils - char *arguments[]={"expr", "1", "+", "2", NULL}; - char *environnement[]={"PATH=/bin:/usr/bin",NULL}; - int err=execve("/usr/bin/expr", arguments, environnement); - if(err!=0) { - perror("execve"); - return(EXIT_FAILURE); - } - } - else { - // processus père - int fils=waitpid(pid,&status,0); - if(fils==-1) { - perror("wait"); - exit(EXIT_FAILURE); - } - if(WIFEXITED(status)) { - printf("Le fils %d s'est terminé correctement et a retourné la valeur %d\n",fils,WEXITSTATUS(status)); - return(EXIT_SUCCESS); - } - else { - if( WIFSIGNALED(status)) { - printf("Le fils %d a été tué par le signal %d\n",fils,WTERMSIG(status)); - } - return(EXIT_FAILURE); - } - } -} -///BBB diff --git a/Theorie/Threads/S8-src/fork-manyexec.c b/Theorie/Threads/S8-src/fork-manyexec.c deleted file mode 100644 index b0742d45b66bd85e56c17d3626626e3db0cbf431..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/fork-manyexec.c +++ /dev/null @@ -1,64 +0,0 @@ -/************************************** - * fork-manyexec.c - * - * Programme d'exemple d'utilisation de - * fork et execve - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/wait.h> -#include <sys/types.h> -#include <libgen.h> - -extern char **environ; - -int main (int argc, char *argv[]) { - int status; - pid_t pid; - - for(int i=1;i<argc;i++) { - // création du fils - pid=fork(); - if (pid==-1) { - perror("fork"); - exit(EXIT_FAILURE); - } - if (pid==0) { - // fils - printf ("Exécution de la commande %s [pid=%d]\n",argv[i],getpid()); - fflush(stdout); - char *arguments[2]; - arguments[0]=basename(argv[i]); - arguments[1]=NULL; - int err=execve(argv[i], arguments, environ); - if(err!=0) - return(127); - } // fils - else { - // processus père - int fils=waitpid(pid,&status,0); - if(fils==-1) { - perror("wait"); - exit(EXIT_FAILURE); - } - if(WIFEXITED(status)) { - if(WEXITSTATUS(status)==0) - printf("La commande %s [%d] s'est terminée correctement\n",argv[i],fils); - else - if (WEXITSTATUS(status)==127) - printf("La commande %s n'a pu être exécutée\n",argv[i]); - else - printf("La commande %s [%d] a retourné %d\n",argv[i],fils,WEXITSTATUS(status)); - } - else { - if( WIFSIGNALED(status)) - printf("La commande %s [%d] ne s'est pas terminée correctement\n",argv[i],fils); - } - fflush(stdout); - } // père - } // for loop - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S8-src/fork-manyexec.out b/Theorie/Threads/S8-src/fork-manyexec.out deleted file mode 100644 index 942f0cdf2a69fa0ddd52340e28f0feb9392b0884..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/fork-manyexec.out +++ /dev/null @@ -1,7 +0,0 @@ -$./fork-manyexec /bin/true /bin/false /bin/none -Exécution de la commande /bin/true [pid=14217] -La commande /bin/true [14217] s'est terminée correctement -Exécution de la commande /bin/false [pid=14218] -La commande /bin/false [14218] a retourné 1 -Exécution de la commande /bin/none [pid=14219] -La commande /bin/none n'a pu être exécutée diff --git a/Theorie/Threads/S8-src/fork-nice.c b/Theorie/Threads/S8-src/fork-nice.c deleted file mode 100644 index e746a7d109259baf9e316f8fbff860c1dff12229..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/fork-nice.c +++ /dev/null @@ -1,67 +0,0 @@ -/************************************** - * fork-zombie.c - * - * Programme d'exemple d'utilisation de - * fork qui crée un zombie - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/wait.h> -#include <sys/types.h> - -void usage() { - printf("Usage :\n"); - printf("prog -p num\navec num entier\n"); - -} - -int main (int argc, char *argv[]) { - pid_t pid; - char *endptr, *str; - int err; - int ch; - int priority; - while ((ch = getopt(argc, argv, "p:")) != -1) { - switch (ch) { - case 'p': - priority=(int) strtol(optarg, &endptr, 10); - if( (priority < 0) || (priority >20) ) { - printf("La priorité doit être comprise entre 0 et 20\n"); - } - return(EXIT_FAILURE); - break; - case '?': - default: - usage(); - return(EXIT_FAILURE); - } - } - pid=fork(); - - if (pid==-1) { - // erreur à l'exécution de fork - perror("fork"); - exit(EXIT_FAILURE); - } - // pas d'erreur - if (pid==0) { - // fils - printf("pid du zombie: %d\n",getpid()); - return(EXIT_SUCCESS); - } - else { - // processus père - sleep(50); - err=wait(NULL); - if(err!=0) { - perror("fork"); - exit(EXIT_FAILURE); - } - printf("Fin du processus père [%d]\n",getpid()); - return(EXIT_SUCCESS); - } -} -///BBB diff --git a/Theorie/Threads/S8-src/fork-orphan.c b/Theorie/Threads/S8-src/fork-orphan.c deleted file mode 100644 index 751d5a123d9035862047b6308b1fc894eaef63af..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/fork-orphan.c +++ /dev/null @@ -1,41 +0,0 @@ -/************************************** - * fork-ophan.c - * - * Programme d'exemple d'utilisation de - * fork avec fils orphelin - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/wait.h> -#include <sys/types.h> - - -int main (int argc, char *argv[]) { - pid_t pid; - - pid=fork(); - - if (pid==-1) { - // erreur à l'exécution de fork - perror("fork"); - exit(EXIT_FAILURE); - } - // pas d'erreur - if (pid==0) { - printf("Processus : %d, père : %d\n",getpid(),getppid()); - fflush(stdout); - sleep(3); - printf("Processus : %d, père : %d\n",getpid(),getppid()); - return(EXIT_SUCCESS); - } - else { - // processus père - sleep(1); - printf("Fin du processus père [%d]\n",getpid()); - return(EXIT_FAILURE); - } -} -///BBB diff --git a/Theorie/Threads/S8-src/fork-orphan.out b/Theorie/Threads/S8-src/fork-orphan.out deleted file mode 100644 index 6f5395e9eb46edac55b814bb46d43ca9149d7990..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/fork-orphan.out +++ /dev/null @@ -1,3 +0,0 @@ -Processus : 28750, père : 28749 -Fin du processus père [28749] -Processus : 28750, père : 1 diff --git a/Theorie/Threads/S8-src/fork-perf.c b/Theorie/Threads/S8-src/fork-perf.c deleted file mode 100644 index 3c330d9569d6b947e69c2f0c557656898257f01b..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/fork-perf.c +++ /dev/null @@ -1,47 +0,0 @@ -/************************************** - * fork-perf.c - * - * Programme d'exemple pour calculer le coût - * de fork - * - *************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/wait.h> -#include <sys/types.h> - -#define N 100000 - -int main (int argc, char *argv[]) { - int status; - pid_t pid; - - for(int i=0;i<N;i++) { - pid=fork(); - if (pid==-1) { - // erreur à l'exécution de fork - perror("fork"); - exit(EXIT_FAILURE); - } - // pas d'erreur - if (pid==0) { - return(EXIT_SUCCESS); - } - else { - int fils=waitpid(pid,&status,0); - if(fils==-1) { - perror("wait"); - exit(EXIT_FAILURE); - } - if(!WIFEXITED(status)) { - fprintf(stderr,"Erreur de waitpid\n"); - exit(EXIT_FAILURE); - } - } - } - return(EXIT_SUCCESS); - -} - diff --git a/Theorie/Threads/S8-src/fork-pthread.c b/Theorie/Threads/S8-src/fork-pthread.c deleted file mode 100644 index ebb9b6d6bd6e9580d7942c92af6167ba8d2a993b..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/fork-pthread.c +++ /dev/null @@ -1,78 +0,0 @@ -/************************************** - * fork-pthread.c - * - * Programme d'exemple pour voir le contenu de /proc - * - *************************************/ - -#define _GNU_SOURCE -#include <stdio.h> -#include <stdlib.h> -#include <pthread.h> -#include <unistd.h> -#include <sys/wait.h> -#include <sys/types.h> -#include <sys/syscall.h> - -#define DELAY 600 - -pid_t gettid() { - pid_t tid; - tid = syscall(SYS_gettid); - return tid; -} - - -void *func(void * param) { - int slept=DELAY; - printf("thread : %d\n",gettid()); - fflush(stdout); - while((slept=sleep(slept))!=0) ; - pthread_exit(NULL); -} - -int main (int argc, char *argv[]) { - int err; - pid_t pid; - int status; - pthread_t thread; - int slept=DELAY; - printf("père : %d\n",getpid()); - fflush(stdout); - pid=fork(); - if (pid==-1) { - perror("fork"); - exit(EXIT_FAILURE); - } - if (pid==0) { - // fils - printf("fils : %d\n",getpid()); - fflush(stdout); - while((slept=sleep(slept))!=0) ; - return(EXIT_SUCCESS); - } - else { - // père - err=pthread_create(&(thread),NULL,&func,NULL); - if(err!=0) { - perror("pthread_create"); - exit(EXIT_FAILURE); - } - err=pthread_join(thread,NULL); - if(err!=0) { - perror("pthread_join"); - exit(EXIT_FAILURE); - } - int fils=waitpid(pid,&status,0); - if(fils==-1) { - perror("wait"); - exit(EXIT_FAILURE); - } - if(!WIFEXITED(status)) { - fprintf(stderr,"Erreur de waitpid\n"); - exit(EXIT_FAILURE); - } - } - return(EXIT_SUCCESS); -} - diff --git a/Theorie/Threads/S8-src/fork-wait.c b/Theorie/Threads/S8-src/fork-wait.c deleted file mode 100644 index 9d8fa3b903351bc0344b3a42bfc385eadb836675..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/fork-wait.c +++ /dev/null @@ -1,51 +0,0 @@ -/************************************** - * fork-wait.c - * - * Programme d'exemple d'utilisation de - * fork - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/wait.h> -#include <sys/types.h> - - -int main (int argc, char *argv[]) { - int status; - pid_t pid; - - pid=fork(); - - if (pid==-1) { - // erreur à l'exécution de fork - perror("fork"); - exit(EXIT_FAILURE); - } - // pas d'erreur - if (pid==0) { - sleep(8); - return(42); - } - else { - // processus père - int fils=waitpid(pid,&status,0); - if(fils==-1) { - perror("wait"); - exit(EXIT_FAILURE); - } - if(WIFEXITED(status)) { - printf("Le fils %d s'est terminé correctement et a retourné la valeur %d\n",fils,WEXITSTATUS(status)); - return(EXIT_SUCCESS); - } - else { - if( WIFSIGNALED(status)) { - printf("Le fils %d a été tué par le signal %d\n",fils,WTERMSIG(status)); - } - return(EXIT_FAILURE); - } - } -} -///BBB diff --git a/Theorie/Threads/S8-src/fork-zombie.c b/Theorie/Threads/S8-src/fork-zombie.c deleted file mode 100644 index 33959bf53a1bbcd70d980bd9fae5164fe48115d9..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/fork-zombie.c +++ /dev/null @@ -1,45 +0,0 @@ -/************************************** - * fork-zombie.c - * - * Programme d'exemple d'utilisation de - * fork qui crée un zombie - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/wait.h> -#include <sys/types.h> - - -int main (int argc, char *argv[]) { - pid_t pid; - int err; - - pid=fork(); - - if (pid==-1) { - // erreur à l'exécution de fork - perror("fork"); - exit(EXIT_FAILURE); - } - // pas d'erreur - if (pid==0) { - // fin du fils - printf("pid du zombie: %d\n",getpid()); - return(EXIT_SUCCESS); - } - else { - // processus père - sleep(50); - err=wait(NULL); - if(err!=0) { - perror("fork"); - exit(EXIT_FAILURE); - } - printf("Fin du processus père [%d]\n",getpid()); - return(EXIT_SUCCESS); - } -} -///BBB diff --git a/Theorie/Threads/S8-src/fork.c b/Theorie/Threads/S8-src/fork.c deleted file mode 100644 index 6cd78db0a9484b656e6b9710fc6ca1363bbe5165..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/fork.c +++ /dev/null @@ -1,49 +0,0 @@ -/************************************** - * fork.c - * - * Programme d'exemple d'utilisation de - * fork - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -int g=0; // segment données - -int main (int argc, char *argv[]) { - int l=1252; // sur la pile - int *m; // sur le heap - m=(int *) malloc(sizeof(int)); - *m=-1; - - pid_t pid; - - pid=fork(); - - if (pid==-1) { - // erreur à l'exécution de fork - perror("fork"); - exit(EXIT_FAILURE); - } - // pas d'erreur - if (pid==0) { - // processus fils - l++; - g++; - *m=17; - printf("Dans le processus fils g=%d, l=%d et *m=%d\n",g,l,*m); - free(m); - return(EXIT_SUCCESS); - } - else { - // processus père - sleep(2); - printf("Dans le processus père g=%d, l=%d et *m=%d\n",g,l,*m); - free(m); - // ... - return(EXIT_SUCCESS); - } -} -///BBB diff --git a/Theorie/Threads/S8-src/fork.out b/Theorie/Threads/S8-src/fork.out deleted file mode 100644 index 1f71b8911b5f970a3e0012f03e3c4e800553bfbe..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/fork.out +++ /dev/null @@ -1,2 +0,0 @@ -Dans le processus fils g=1, l=1253 et *m=17 -Dans le processus père g=0, l=1252 et *m=-1 diff --git a/Theorie/Threads/S8-src/getpid.c b/Theorie/Threads/S8-src/getpid.c deleted file mode 100644 index fddef731a947678c8a615b3bbfdddec52e9ea461..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/getpid.c +++ /dev/null @@ -1,21 +0,0 @@ -/************************************** - * getpid.c - * - * Programme d'exemple de getpid - * - **************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> - - -int main (int argc, char *argv[]) { - int pid=getpid(); - int ppid=getppid(); - printf("Processus %d, parent:%d\n",pid,ppid); - - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/Threads/S8-src/imath.c b/Theorie/Threads/S8-src/imath.c deleted file mode 100644 index 3c2887a56e3763f57e5237fa94ab07081d4f2a3f..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/imath.c +++ /dev/null @@ -1,20 +0,0 @@ -/************************************** - * math.c - * - * Programme d'exemple d'utilisation de - * la librairie math - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include "imax.h" - -int main (int argc, char *argv[]) { - int n1=1; - int n2=-3; - printf("Maximum : %d\n",imax(n1,n2)); - - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/Threads/S8-src/imax.c b/Theorie/Threads/S8-src/imax.c deleted file mode 100644 index 92b80fee674638cbf2c7ae9a52c0c1dbe7d5c4a7..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/imax.c +++ /dev/null @@ -1,14 +0,0 @@ -/************************************** - * imax.c - * - * Programme d'exemple d'utilisation de - * librairie - * - *************************************/ -///AAA - -int imax(int i, int j) { - return ((i>j) ? i : j); - -} -///BBB diff --git a/Theorie/Threads/S8-src/imax.h b/Theorie/Threads/S8-src/imax.h deleted file mode 100644 index 444fb1ab002477eecfb88e226b1a2ae23436d657..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/imax.h +++ /dev/null @@ -1,12 +0,0 @@ -/************************************** - * imax.h - * - * Programme d'exemple d'utilisation de - * librairie - * - *************************************/ -///AAA - -int imax(int,int); - -///BBB diff --git a/Theorie/Threads/S8-src/math.c b/Theorie/Threads/S8-src/math.c deleted file mode 100644 index 55e23123df634f6f0c075ecc23521a711731f397..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/math.c +++ /dev/null @@ -1,21 +0,0 @@ -/************************************** - * math.c - * - * Programme d'exemple d'utilisation de - * la librairie math - * - *************************************/ -///AAA -#include <stdio.h> -#include <stdlib.h> -#include <math.h> - - -int main (int argc, char *argv[]) { - double n1=1.0; - double n2=-3.14; - printf("Maximum : %f\n",fmax(n1,n2)); - - return(EXIT_SUCCESS); -} -///BBB diff --git a/Theorie/Threads/S8-src/max.c b/Theorie/Threads/S8-src/max.c deleted file mode 100644 index bab26965fb534d534034116f03af788642d01b79..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/max.c +++ /dev/null @@ -1,20 +0,0 @@ -/************************************** - * math.c - * - * Programme d'exemple d'utilisation de - * la librairie math - * - *************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <math.h> - - -int main (int argc, char *argv[]) { - double n1=1.0; - double n2=-3.14; - printf("Maximum : %f\n",fmax(n1,n2)); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S8-src/mini8.c b/Theorie/Threads/S8-src/mini8.c deleted file mode 100644 index b69b1aefa12db155a77c248310b4078af838fcd1..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/mini8.c +++ /dev/null @@ -1,117 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <pthread.h> -#include <limits.h> -#include <time.h> - -/* Necessary for the correct compilation */ -#define _POSIX_C_SOURCE 199309L - -#define N_ITERATIONS (100) -#define N_CONSUMERS (4) -#define N_PRODUCERS (2) -#define N_RETRIEVES ((N_ITERATIONS) * (N_PRODUCERS) / (N_CONSUMERS)) -#define MIN(a, b) ((a) > (b) ? (b) : (a)) - -/* A COMPLETER */ - -/* - * Insert val in the bounded-buffer. Should wait if there are no empty spaces - * available. - */ -void insert(int val) -{ - /* A COMPLETER */ -} - -/* - * Returns and removes the next element from the bounded buffer. - */ -int retrieve(void) -{ - /* A COMPLETER */ - return -1; -} - - -void *producer(void *arg) -{ - int i, val; - - for (i = 0; i < N_ITERATIONS; ++i) { - /* sleep for few miliseconds */ - struct timespec sleep; - sleep.tv_sec = 0; - sleep.tv_nsec = (long) rand() % 100000000; - nanosleep(&sleep, NULL); - - /* generate a value and insert it in the buffer */ - val = abs(rand()); - insert(val); - } - return NULL; -} - -void *consumer(void *arg) -{ - int i, *min = (int *)arg; - - for (i = 0; i < N_RETRIEVES; ++i) { - /* sleep for few miliseconds */ - struct timespec sleep; - sleep.tv_sec = 0; - sleep.tv_nsec = (long) rand() % 100000000; - nanosleep(&sleep, NULL); - - /* maintain the minimum value up to now */ - *min = MIN(*min, retrieve()); - } - return (void *)min; -} - -int main (int argc, char const *argv[]) -{ - int i, min = INT_MAX, *ret; - pthread_t producers[N_PRODUCERS]; - pthread_t consumers[N_CONSUMERS]; - int returns[N_CONSUMERS]; - int err; - - /* seed the PRNG */ - srand(time(NULL)); - - /* A COMPLETER */ - - for (i = 0; i < N_PRODUCERS; ++i) { - err = pthread_create(&producers[i], NULL, producer, NULL); - if (err) - goto error; - } - - for (i = 0; i < N_CONSUMERS; ++i) { - err = pthread_create(&consumers[i], NULL, consumer, &returns[i]); - if (err) - goto error; - } - - for (i = 0; i < N_PRODUCERS; ++i) { - err = pthread_join(producers[i], NULL); - if (err) - goto error; - } - - for (i = 0; i < N_CONSUMERS; ++i) { - err = pthread_join(consumers[i], (void **)&ret); - if (err) - goto error; - min = MIN(min, *ret); - } - - printf("The minimal value generated is %d.\n", min); - - return (EXIT_SUCCESS); - -error: - perror("Error happened:\n"); - return (EXIT_FAILURE); -} diff --git a/Theorie/Threads/S8-src/pthread-perf.c b/Theorie/Threads/S8-src/pthread-perf.c deleted file mode 100644 index 07772a2c21ab37b146401686b55c6945b23ba375..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/pthread-perf.c +++ /dev/null @@ -1,41 +0,0 @@ -/************************************** - * pthread-perf.c - * - * Programme d'exemple pour calculer le coût - * de pthread - * - *************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <pthread.h> - -#define N 100000 - -void *func(void * param) { - pthread_exit(NULL); -} - - -int main (int argc, char *argv[]) { - int err; - pthread_t thread; - - - for(int i=0;i<N;i++) { - - err=pthread_create(&(thread),NULL,&func,NULL); - if(err!=0) { - perror("pthread_create"); - exit(EXIT_FAILURE); - } - err=pthread_join(thread,NULL); - if(err!=0) { - perror("pthread_join"); - exit(EXIT_FAILURE); - } - } - return(EXIT_SUCCESS); - -} - diff --git a/Theorie/Threads/S8-src/script.sh b/Theorie/Threads/S8-src/script.sh deleted file mode 100755 index cfd6015e4989e6a37c97c0b8950c868f98b35761..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/script.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -# script.sh -if [ $# -ne 1 ] -then - echo "Usage: `basename $0` fichier" - exit 1 -fi -if [ -x ${1} ] -then - head -1 $1 | grep "^#\!" >>/dev/null - if [ $? ] - then - echo "Script interprétable" - exit 0 - else - echo "Script non-interprétable" - exit 1 - fi -else - echo "Bit x non mis dans les métadonnées" - exit 1 -fi diff --git a/Theorie/Threads/S8-src/syscall.c b/Theorie/Threads/S8-src/syscall.c deleted file mode 100644 index f102291addc712aefd597e9599441b81d9832c60..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/syscall.c +++ /dev/null @@ -1,20 +0,0 @@ -/************************************** - * syscall.c - * - * Programme d'exemple d'utilisation de syscall - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/syscall.h> - - -int main (int argc, char *argv[]) { - int pid=getpid(); - int pid2=syscall(SYS_getpgid); - printf("Processus %d, pid:%d\n",pid,pid2); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/Threads/S8-src/test.tail b/Theorie/Threads/S8-src/test.tail deleted file mode 100755 index 242953177ecd4d6f101fe13221388c466b0081bf..0000000000000000000000000000000000000000 --- a/Theorie/Threads/S8-src/test.tail +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/tail -n +1 -Hello, world -SINF1252 diff --git a/Theorie/Threads/coordination.rst b/Theorie/Threads/coordination.rst deleted file mode 100644 index df087173da4ab3e8ba638447559c583338231144..0000000000000000000000000000000000000000 --- a/Theorie/Threads/coordination.rst +++ /dev/null @@ -1,419 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012, 2019 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -.. _coordinationthreads: - -Les sémaphores -============== - -Le problème de la coordination entre threads est un problème majeur. Outre les :term:`mutex` que nous avons présenté, d'autres solutions à ce problème ont été développées. Historiquement, une des premières propositions de coordination sont les sémaphores [Dijkstra1965b]_. Un :term:`sémaphore` est une structure de données qui est maintenue par le système d'exploitation et contient : - - - un entier qui stocke la valeur, positive ou nulle, du sémaphore. - - une queue qui contient les pointeurs vers les threads qui sont bloqués en attente sur ce sémaphore. - -Tout comme pour les :term:`mutex`, la queue associée à un sémaphore permet de bloquer les threads qui sont en attente d'une modification de la valeur du sémaphore. - -.. spelling:: - - décrémentée - s'implémenter - l'implémentation - -Une implémentation des sémaphores se compose en général de quatre fonctions : - - - une fonction d'initialisation qui permet de créer le sémaphore et de lui attribuer une valeur initiale nulle ou positive. - - une fonction permettant de détruire un sémaphore et de libérer les ressources qui lui sont associées. - - une fonction ``post`` qui est utilisée par les threads pour modifier la valeur du sémaphore. S'il n'y a pas de thread en attente dans la queue associée au sémaphore, sa valeur est incrémentée d'une unité. Sinon, un des threads en attente est libéré et passe à l'état `Ready`. - - une fonction ``wait`` qui est utilisée par les threads pour tester la valeur d'un sémaphore. Si la valeur du sémaphore est positive, elle est décrémentée d'une unité et la fonction réussit. Si le sémaphore a une valeur nulle, le thread est bloqué jusqu'à ce qu'un autre thread le débloque en appelant la fonction ``post``. - -.. [Dijkstra1965b]_ - -Les sémaphores sont utilisés pour résoudre de nombreux problèmes de coordination [Downey2008]_. Comme ils permettent de stocker une valeur entière, ils sont plus flexibles que les :term:`mutex` qui sont utiles surtout pour les problèmes d'exclusion mutuelle. - - -Sémaphores POSIX ----------------- - -La librairie POSIX comprend une implémentation des sémaphores [#fSysV]_ qui expose plusieurs fonctions aux utilisateurs. La page de manuel `sem_overview(7)`_ présente de façon sommaire les fonctions de la librairie relatives aux sémaphores. Les quatre principales sont les suivantes : - -.. code-block:: c - - #include <semaphore.h> - - int sem_init(sem_t *sem, int pshared, unsigned int value); - int sem_destroy(sem_t *sem); - int sem_wait(sem_t *sem); - int sem_post(sem_t *sem); - -Le fichier `semaphore.h`_ contient les différentes définitions de structures qui sont nécessaires au bon fonctionnement des sémaphores ainsi que les signatures des fonctions de cette API. Un sémaphore est représenté par une structure de données de type ``sem_t``. Toutes les fonctions de manipulation des sémaphores prennent comme argument un pointeur vers le sémaphore concerné. - -Pour pouvoir utiliser un sémaphore, il faut d'abord l'initialiser. Cela se fait en utilisant la fonction `sem_init(3)`_ qui prend comme argument un pointeur vers le sémaphore à initialiser. Nous n'utiliserons pas le second argument dans ce chapitre. Le troisième argument est la valeur initiale, positive ou nulle, du sémaphore. - -La fonction `sem_destroy(3)`_ permet de libérer un sémaphore qui a été initialisé avec `sem_init(3)`_. Les sémaphores consomment des ressources qui peuvent être limitées dans certains environnements. Il est important de détruire proprement les sémaphores dès qu'ils ne sont plus nécessaires. - -Les deux principales fonctions de manipulation des sémaphores sont `sem_wait(3)`_ et `sem_post(3)`_. Certains auteurs utilisent ``down`` ou ``P`` à la place de `sem_wait(3)`_ et ``up`` ou ``V`` à la place de `sem_post(3)`_ [Downey2008]_. Schématiquement, l'opération ``sem_wait`` peut s'implémenter en utilisant le pseudo-code suivant : - -.. code-block:: c - - int sem_wait(semaphore *s) - { - s->val=s->val-1; - if(s->val<0) - { - // Place this thread in s.queue; - // This thread is blocked; - } - } - -La fonction `sem_post(3)`_ quant à elle peut schématiquement s'implémenter comme suit : - - -.. code-block:: c - - int sem_post(semaphore *s) - { - s->val=s->val+1; - if(s.val<=0) - { - // Remove one thread(T) from s.queue; - // Mark Thread(T) as ready to run; - } - } - -Ces deux opérations sont bien entendu des opérations qui ne peuvent s'exécuter simultanément. Leur implémentation réelle comprend des sections critiques qui doivent être construites avec soin. Le pseudo-code ci-dessus ignore ces sections critiques. Des détails complémentaires sur l'implémentation des sémaphores peuvent être obtenus dans livre sur les systèmes d'exploitation [Stallings2011]_ [Tanenbaum+2009]_ . - -La meilleure façon de comprendre leur utilisation est d'analyser des problèmes classiques de coordination qui peuvent être résolus en utilisant des sémaphores. - -Exclusion mutuelle ------------------- - -Les sémaphores permettent de résoudre de nombreux problèmes classiques. Le premier est celui de l'exclusion mutuelle. Lorsqu'il est initialisé à ``1``, un sémaphore peut être utilisé de la même façon qu'un :term:`mutex`. En utilisant des sémaphores, une exclusion mutuelle peut être protégée comme suit : - - -.. code-block:: c - - #include <semaphore.h> - - //... - - sem_t semaphore; - - sem_init(&semaphore, 0, 1); - - sem_wait(&semaphore); - // section critique - sem_post(&semaphore); - - sem_destroy(&semaphore); - -Les sémaphores peuvent être utilisés pour d'autres types de synchronisation. Par exemple, considérons une application découpée en threads dans laquelle la fonction ``after`` ne peut jamais être exécutée avant la fin de l'exécution de la fonction ``before``. Ce problème de coordination peut facilement être résolu en utilisant un sémaphore qui est initialisé à la valeur ``0``. La fonction ``after`` doit démarrer par un appel à `sem_wait(3)`_ sur ce sémaphore tandis que la fonction ``before`` doit se terminer par un appel à la fonction `sem_post(3)`_ sur ce sémaphore. De cette façon, si le thread qui exécute la fonction ``after`` est trop rapide, il sera bloqué sur l'appel à `sem_wait(3)`_. S'il arrive à cette fonction après la fin de la fonction ``before`` dans l'autre thread, il pourra passer sans être bloqué. Le programme ci-dessous illustre cette utilisation des sémaphores POSIX. - -.. literalinclude:: /Threads/S7-src/pthread-sem-before.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -Si un sémaphore initialisé à la valeur ``1`` est généralement utilisé comme un :term:`mutex`, il y a une différence importante entre les implémentations des sémaphores et des :term:`mutex`. Un sémaphore est conçu pour être manipulé par différents threads et il est fort possible qu'un thread exécute `sem_wait(3)`_ et qu'un autre exécute `sem_post(3)`_. Pour les mutex, certaines implémentations supposent que le même thread exécute `pthread_mutex_lock(3posix)`_ et `pthread_mutex_unlock(3posix)`_. Lorsque ces opérations doivent être effectuées dans des threads différents, il est préférable d'utiliser des sémaphores à la place de mutex. - - - -Problème des producteurs-consommateurs --------------------------------------- - -Le problème des producteurs-consommateurs est un problème extrêmement fréquent et important dans les applications découpées en plusieurs threads. Il est courant de structurer une telle application, notamment si elle réalise de longs calculs, en deux types de threads : - - - les `producteurs` : Ce sont des threads qui produisent des données et placent le résultat de leurs calculs dans une zone mémoire accessible aux consommateurs. - - les `consommateurs` : Ce sont des threads qui utilisent les valeurs calculées par les producteurs. - -Ces deux types de threads communiquent en utilisant un buffer qui a une capacité limitée à `N` places comme illustré dans la figure ci-dessous. - -.. figure:: /Threads/figures/figures-S7-001-c.png - :align: center - :scale: 80 - - Problème des producteurs-consommateurs - -La difficulté du problème est de trouver une solution qui permet aux producteurs et aux consommateurs d'avancer à leur rythme sans que les producteurs ne bloquent inutilement les consommateurs et inversement. Le nombre de producteurs et de consommateurs ne doit pas nécessairement être connu à l'avance et ne doit pas être fixe. Un producteur peut arrêter de produire à n'importe quel moment. - -Le buffer étant partagé entre les producteurs et les consommateurs, il doit nécessairement être protégé par un :term:`mutex`. Les producteurs doivent pouvoir ajouter de l'information dans le buffer partagé tant qu'il y a au moins une place de libre dans le buffer. Un producteur ne doit être bloqué que si tout le buffer est rempli. Inversement, les consommateurs doivent être bloqués uniquement si le buffer est entièrement vide. Dès qu'une donnée est ajoutée dans le buffer, un consommateur doit être réveillé pour traiter cette donnée. - -Ce problème peut être résolu en utilisant deux sémaphores et un mutex. L'accès au buffer, que ce soit par les consommateurs ou les producteurs est une section critique. Cet accès doit donc être protégé par l'utilisation d'un mutex. Quant aux sémaphores, le premier, baptisé ``empty`` dans l'exemple ci-dessous, sert à compter le nombre de places qui sont vides dans le buffer partagé. Ce sémaphore doit être initialisé à la taille du buffer puisque celui-ci est initialement vide. Le second sémaphore est baptisé ``full`` dans le pseudo-code ci-dessous. Sa valeur représente le nombre de places du buffer qui sont occupées. Il doit être initialisé à la valeur ``0``. - -.. code-block:: c - - // Initialisation - #define N 10 // places dans le buffer - pthread_mutex_t mutex; - sem_t empty; - sem_t full; - - pthread_mutex_init(&mutex, NULL); - sem_init(&empty, 0 , N); // buffer vide - sem_init(&full, 0 , 0); // buffer vide - -Le fonctionnement général d'un producteur est le suivant. Tout d'abord, le producteur est mis en attente sur le sémaphore ``empty``. Il ne pourra passer que si il y a au moins une place du buffer qui est vide. Lorsque la ligne ``sem_wait(&empty);`` réussit, le producteur s'approprie le ``mutex`` et modifie le buffer de façon à insérer l'élément produit (dans ce cas un entier). Il libère ensuite le ``mutex`` pour sortir de sa section critique. - -.. code-block:: c - - // Producteur - void producer(void) - { - int item; - while(true) - { - item=produce(item); - sem_wait(&empty); // attente d'une place libre - pthread_mutex_lock(&mutex); - // section critique - insert_item(); - pthread_mutex_unlock(&mutex); - sem_post(&full); // il y a une place remplie en plus - } - } - - -Le consommateur quant à lui essaie d'abord de prendre le sémaphore ``full``. Si celui-ci est positif, cela indique la présence d'au moins un élément dans le buffer partagé. Ensuite, il entre dans la section critique protégée par le ``mutex`` et récupère la donnée se trouvant dans le buffer. Puis, il incrémente la valeur du sémaphore ``empty`` de façon à indiquer à un producteur qu'une nouvelle place est disponible dans le buffer. - -.. code-block:: c - - // Consommateur - void consumer(void) - { - int item; - while(true) - { - sem_wait(&full); // attente d'une place remplie - pthread_mutex_lock(&mutex); - // section critique - item=remove(item); - pthread_mutex_unlock(&mutex); - sem_post(&empty); // il y a une place libre en plus - } - } - -De nombreux programmes découpés en threads fonctionnent avec un ensemble de producteurs et un ensemble de consommateurs. - -.. spelling:: - - Solaris - - -Compléments sur les threads POSIX -================================= - -Il existe différentes implémentations des threads POSIX. Les mécanismes de coordination utilisables varient parfois d'une implémentation à l'autre. Dans les sections précédentes, nous nous sommes focalisés sur les fonctions principales qui sont en général bien implémentées. Une discussion plus détaillée des fonctions implémentées sous Linux peut se trouver dans [Kerrisk2010]_. [Gove2011]_ présente de façon détaillée les mécanismes de coordination utilisables sous Linux, Windows et Oracle Solaris. [StevensRago2008]_ comprend également une description des threads POSIX mais présente des exemples sur des versions plus anciennes de Linux, FreeBSD, Solaris et MacOS. - -Il reste cependant quelques concepts qu'il est utile de connaître lorsque l'on développe des programmes découpés en threads en langage C. - - -Variables ``volatile`` ----------------------- - -Normalement, dans un programme C, lorsqu'une variable est définie, ses accès sont contrôlés entièrement par le compilateur. Si la variable est utilisée dans plusieurs calculs successifs, il peut être utile d'un point de vue des performances de stocker la valeur de cette variable dans un registre pendant au moins le temps correspondant à l'exécution de quelques instructions [#fregister]_. Cette optimisation peut éventuellement poser des difficultés dans certains programmes utilisant des threads puisqu'une variable peut être potentiellement modifiée ou lue par plusieurs threads simultanément. - -Les premiers compilateurs C avaient pris en compte un problème similaire. Lorsqu'un programme ou un système d'exploitation interagit avec des dispositifs d'entrée-sortie, cela se fait parfois en permettant au dispositif d'écrire directement en mémoire à une adresse connue par le système d'exploitation. La valeur présente à cette adresse peut donc être modifiée par le dispositif d'entrée-sortie sans que le programme ne soit responsable de cette modification. Face à ce problème, les inventeurs du langage C ont introduit le qualificatif ``volatile``. Lorsqu'une variable est ``volatile``, cela indique au compilateur qu'il doit recharger la variable de la mémoire chaque fois qu'elle est utilisée. - -Pour bien comprendre l'impact de ce qualificatif, il est intéressant d'analyser le code assembleur généré par un compilateur C dans l'exemple suivant. - -.. code-block:: c - - int x=1; - int v[2]; - - void f(void ) { - v[0]=x; - v[1]=x; - } - -Dans ce cas, la fonction ``f`` est traduite en la séquence d'instructions suivante : - -.. code-block:: nasm - - f: - movl x, %eax - movl %eax, v - movl %eax, v+4 - ret - -Si par contre la variable ``x`` est déclarée comme étant ``volatile``, le compilateur ajoute une instruction ``movl x, %eax`` qui permet de recharger la valeur de ``x`` dans un registre avant la seconde utilisation. - -.. code-block:: nasm - - f: - movl x, %eax - movl %eax, v - movl x, %eax - movl %eax, v+4 - ret - -Le qualificatif ``volatile`` force le compilateur à recharger la variable depuis la mémoire avant chaque utilisation. Ce qualificatif est utile lorsque le contenu stocké à une adresse mémoire peut être modifié par une autre source que le programme lui-même. C'est le cas dans les threads, mais marquer les variables partagées par des threads comme ``volatile`` ne suffit pas. Si ces variables sont modifiées par certains threads, il est nécessaire d'utiliser des :term:`mutex` ou d'autres techniques de coordination pour réguler l'accès en ces variables partagées. En pratique, la documentation du programme devra spécifier quelles variables sont partagées entre les threads et la technique de coordination éventuelle qui est utilisée pour en réguler les accès. L'utilisation du qualificatif ``volatile`` permet de forcer le compilateur à recharger le contenu de la variable depuis la mémoire avant toute utilisation. C'est une règle de bonne pratique qu'il est utile de suivre. Il faut cependant noter que dans l'exemple ci-dessus, l'utilisation du qualificatif ``volatile`` augmente le nombre d'accès à la mémoire et peut donc dans certains cas réduire les performances. - - -Variables spécifiques à un thread ---------------------------------- - -Dans un programme C séquentiel, on doit souvent combiner les variables globales, les variables locales et les arguments de fonctions. Lorsque le programme est découpé en threads, les variables globales restent utilisables, mais il faut faire attention aux problèmes d'accès concurrent. En pratique, il est parfois utile de pouvoir disposer dans chaque thread de variables qui tout en étant accessibles depuis toutes les fonctions du thread ne sont pas accessibles aux autres threads. Il y a différentes solutions pour résoudre ce problème. - -Une première solution serait d'utiliser une zone mémoire qui est spécifique au thread et d'y placer par exemple une structure contenant toutes les variables auxquelles on souhaite pouvoir accéder depuis toutes les fonctions du thread. Cette zone mémoire pourrait être créée avant l'appel à `pthread_create(3)`_ et un pointeur vers cette zone pourrait être passé comme argument à la fonction qui démarre le thread. Malheureusement l'argument qui est passé à cette fonction n'est pas équivalent à une variable globale et n'est pas accessible à toutes les fonctions du thread. - -Une deuxième solution serait d'avoir un tableau global qui contiendrait des pointeurs vers des zones de mémoires qui ont été allouées pour chaque thread. Chaque thread pourrait alors accéder à ce tableau sur base de son identifiant. Cette solution pourrait fonctionner si le nombre de threads est fixe et que les identifiants de threads sont des entiers croissants. Malheureusement la librairie threads POSIX ne fournit pas de tels identifiants croissants. Officiellement, la fonction `pthread_self(3)`_ retourne un identifiant unique d'un thread qui a été créé. Malheureusement cet identifiant est de type ``pthread_t`` et ne peut pas être utilisé comme index dans un tableau. Sous Linux, l'appel système non-standard `gettid(2)`_ retourne l'identifiant du thread, mais il ne peut pas non plus être utilisé comme index dans un tableau. - -Pour résoudre ce problème, deux solutions sont possibles. La première combine une extension au langage C qui est supportée par `gcc(1)`_ avec la librairie threads POSIX. Il s'agit du qualificatif ``__thread`` qui peut être utilisé avant une déclaration de variable. Lorsqu'il est utilisé dans la déclaration d'une variable globale, il indique au compilateur et à la libraire POSIX qu'une copie de cette variable doit être créée pour chaque thread. Cette variable est initialisée au démarrage du thread et est utilisable uniquement à l'intérieur de ce thread. Le programme ci-dessous illustre cette utilisation du qualificatif ``__thread``. - -.. literalinclude:: /Threads/S7-src/pthread-specific.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Lors de son exécution, ce programme affiche la sortie suivante sur :term:`stdout`. Cette sortie illustre bien que les variables dont la déclaration est précédée du qualificatif ``__thread`` sont utilisables uniquement à l'intérieur d'un thread. - -.. literalinclude:: /Threads/S7-src/pthread-specific.out - :encoding: utf-8 - :language: console - - -La seconde solution proposée par la librairie POSIX est plus complexe. Elle nécessite l'utilisation des fonctions `pthread_key_create(3posix)`_, `pthread_setspecific(3posix)`_, `pthread_getspecific(3posix)`_ et `pthread_key_delete(3posix)`_. Cette API est malheureusement plus difficile à utiliser que le qualificatif ``__thread``, mais elle illustre ce qu'il se passe en pratique lorsque ce qualificatif est utilisé. - -Pour avoir une variable accessible depuis toutes les fonctions d'un thread, il faut tout d'abord créer une clé qui identifie cette variable. Cette clé est de type ``pthread_key_t`` et c'est l'adresse de cette structure en mémoire qui est utilisée comme identifiant pour la variable spécifique à chaque thread. Cette clé ne doit être créée qu'une seule fois. Cela peut se faire dans le programme qui lance les threads ou alors dans le premier thread lancé en utilisant la fonction `pthread_once(3posix)`_. Une clé est créée grâce à la fonction `pthread_key_create(3posix)`_. Cette fonction prend deux arguments. Le premier est un pointeur vers une structure de type ``pthread_key_t``. Le second est la fonction optionnelle à appeler lorsque le thread utilisant la clé se termine. - -Il faut noter que la fonction `pthread_key_create(3posix)`_ associe en pratique le pointeur ``NULL`` à la clé qui a été créée dans chaque thread. Le thread qui veut utiliser la variable correspondant à cette clé doit réserver la zone mémoire correspondante. Cela se fait en général en utilisant `malloc(3)`_ puis en appelant la fonction `pthread_setspecific(3posix)`_. Celle-ci prend deux arguments. Le premier est une clé de type ``pthread_key_t`` qui a été préalablement créée. Le second est un pointeur (de type ``void *``) vers la zone mémoire correspondant à la variable spécifique. Une fois que le lien entre la clé et le pointeur a été fait, la fonction `pthread_getspecific(3posix)`_ peut être utilisée pour récupérer le pointeur depuis n'importe quelle fonction du thread. L'implémentation des fonctions `pthread_setspecific(3posix)`_ et `pthread_getspecific(3posix)`_ garantit que chaque thread aura sa variable qui lui est propre. - -.. spelling:: - - L'implémentation - -L'exemple ci-dessous illustre l'utilisation de cette API. Elle est nettement plus lourde à utiliser que le qualificatif ``__thread``. Dans ce code, chaque thread démarre par la fonction ``f``. Celle-ci crée une variable spécifique de type ``int`` qui joue le même rôle que la variable ``__thread int count;`` dans l'exemple précédent. La fonction ``g`` qui est appelée sans argument peut accéder à la zone mémoire créée en appelant ``pthread_getspecific(count)``. Elle peut ensuite exécuter ses calculs en utilisant le pointeur ``count_ptr``. Avant de se terminer, la fonction ``f`` libère la zone mémoire qui avait été allouée par `malloc(3)`_. Une alternative à l'appel explicite à `free(3)`_ aurait été de passer ``free`` comme second argument à `pthread_key_create(3posix)`_ lors de la création de la clé ``count``. En effet, ce second argument est la fonction à appeler à la fin du thread pour libérer la mémoire correspondant à cette clé. - -.. literalinclude:: /Threads/S7-src/pthread-specific2.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -En pratique, on préférera évidemment d'utiliser le qualificatif ``__thread`` plutôt que d'utiliser une API explicite lorsque c'est possible. Cependant, il ne faut pas oublier que lorsque ce qualificatif est utilisé, le compilateur doit introduire dans le programme du code permettant de faire le même genre d'opérations que les fonctions explicites de la librairie. - -.. spelling:: - - thread-safe - -Fonctions ``thread-safe`` -------------------------- - -Dans un programme séquentiel, il n'y a qu'un thread d'exécution et de nombreux programmeurs, y compris ceux qui ont développé la librairie standard, utilisent cette hypothèse lors de l'écriture de fonctions. Lorsqu'un programme est découpé en threads, chaque fonction peut être appelée par plusieurs threads simultanément. Cette exécution simultanée d'une fonction peut poser des difficultés notamment lorsque la fonction utilise des variables globales ou des variables statiques. - -Pour comprendre le problème, il est intéressant de comparer plusieurs implémentations d'une fonction simple. Considérons le problème de déterminer l'élément maximum d'une structure de données contenant des entiers. Si la structure de données est un tableau, une solution simple est de le parcourir entièrement pour déterminer l'élément maximum. C'est ce que fait la fonction ``max_vector`` dans le programme ci-dessous. Dans un programme purement séquentiel dans lequel le tableau peut être modifié de temps en temps, parcourir tout le tableau pour déterminer son maximum n'est pas nécessairement la solution la plus efficace. Une alternative est de mettre à jour la valeur du maximum chaque fois qu'un élément du tableau est modifié. Les fonctions ``max_global`` et ``max_static`` sont deux solutions possibles. Chacune de ces fonctions doit être appelée chaque fois qu'un élément du tableau est modifié. ``max_global`` stocke dans une variable globale la valeur actuelle du maximum du tableau et met à jour cette valeur à chaque appel. La fonction ``max_static`` fait de même en utilisant une variable statique. Ces deux solutions sont équivalentes et elles pourraient très bien être intégrées à une librairie utilisée par de nombreux programmes. - - -.. literalinclude:: /Threads/S7-src/reentrant.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Considérons maintenant un programme découpé en plusieurs threads qui chacun maintient un tableau d'entiers dont il faut connaître le maximum. Ces tableaux d'entiers sont distincts et ne sont pas partagés entre les threads. La fonction ``max_vector`` peut être utilisée par chaque thread pour déterminer le maximum du tableau. Par contre, les fonctions ``max_global`` et ``max_static`` ne peuvent pas être utilisées. En effet, chacune de ces fonctions maintient *un* état (dans ce cas le maximum calculé) alors qu'elle peut être appelée par différents threads qui auraient chacun besoin d'un état qui leur est propre. Pour que ces fonctions soient utilisables, il faudrait que les variables ``s_max`` et ``g_max`` soient spécifiques à chaque thread. - -En pratique, ce problème de l'accès concurrent à des fonctions se pose pour de nombreuses fonctions et notamment celles de la librairie standard. Lorsque l'on développe une fonction qui peut être réutilisée, il est important de s'assurer que cette fonction peut être exécutée par plusieurs threads simultanément sans que cela ne pose de problèmes à l'exécution. - -Ce problème affecte certaines fonctions de la librairie standard et plusieurs d'entre elles ont dû être modifiées pour pouvoir supporter les threads. A titre d'exemple, considérons la fonction `strerror(3)`_. Cette fonction prend comme argument le numéro de l'erreur et retourne une chaîne de caractères décrivant cette erreur. Cette fonction ne peut pas être utilisée telle quelle par des threads qui pourraient l'appeler simultanément. Pour s'en convaincre, regardons une version simplifiée d'une implémentation de cette fonction [#fstrerror]_. Cette fonction utilise le tableau `sys_errlist(3)`_ qui contient les messages d'erreur associés aux principaux codes numériques d'erreur. Lorsque l'erreur est une erreur standard, tout se passe bien et la fonction retourne simplement un pointeur vers l'entrée du tableau ``sys_errlist`` correspondante. Par contre, si le code d'erreur n'est pas connu, un message est généré dans le tableau ``buf[32]`` qui est déclaré de façon statique. Si plusieurs threads exécutent ``strerror``, ce sera le même tableau qui sera utilisé dans les différents threads. On pourrait remplacer le tableau statique par une allocation de zone mémoire faite via `malloc(3)`_, mais alors la zone mémoire créée risque de ne jamais être libérée par `free(3)`_ car l'utilisateur de `strerror(3)`_ ne doit pas libérer le pointeur qu'il a reçu, ce qui pose d'autres problèmes en pratique. - -.. code-block:: c - - char * strerror (int errnoval) - { - char * msg; - static char buf[32]; - if ((errnoval < 0) || (errnoval >= sys_nerr)) - { // Out of range, just return NULL - msg = NULL; - } - else if ((sys_errlist == NULL) || (sys_errlist[errnoval] == NULL)) - { // In range, but no sys_errlist or no entry at this index. - sprintf (buf, "Error %d", errnoval); - msg = buf; - } - else - { // In range, and a valid message. Just return the message. - msg = (char *) sys_errlist[errnoval]; - } - return (msg); - } - - -La fonction `strerror_r(3)`_ évite ce problème de tableau statique en utilisant trois arguments : le code d'erreur, un pointeur ``char *`` vers la zone devant stocker le message d'erreur et la taille de cette zone. Cela permet à `strerror_r(3)`_ d'utiliser une zone mémoire qui lui est passée par le thread qu'il appelle et garantit que chaque thread disposera de son message d'erreur. Voici une implémentation possible de `strerror_r(3)`_ [#fstrerror_r]_. - - -.. code-block:: c - - strerror_r(int num, char *buf, size_t buflen) - { - #define UPREFIX "Unknown error: %u" - unsigned int errnum = num; - int retval = 0; - size_t slen; - if (errnum < (unsigned int) sys_nerr) { - slen = strlcpy(buf, sys_errlist[errnum], buflen); - } else { - slen = snprintf(buf, buflen, UPREFIX, errnum); - retval = EINVAL; - } - if (slen >= buflen) - retval = ERANGE; - return retval; - } - -Lorsque l'on intègre des fonctions provenant de la librairie standard ou d'une autre librairie dans un programme découpé en threads, il est important de vérifier que les fonctions utilisées sont bien :term:`thread-safe`. La page de manuel `pthreads(7)`_ liste les fonctions qui ne sont pas :term:`thread-safe` dans la librairie standard. - -.. spelling:: - - Gene - Amdahl - -Loi de Amdahl -============= - -En découpant un programme en threads, il est théoriquement possible d'améliorer les performances du programme en lui permettant d'exécuter plusieurs threads d'exécution simultanément. Dans certains cas, la découpe d'un programme en différents threads est naturelle et relativement facile à réaliser. Dans d'autres cas, elle est nettement plus compliquée. Pour s'en convaincre, il suffit de considérer un grand tableau contenant plusieurs centaines de millions de nombres. Considérons un programme simple qui doit trouver dans ce tableau quel est l'élément du tableau pour lequel l'application d'une fonction complexe ``f`` donne le résultat minimal. Une implémentation purement séquentielle se contenterait de parcourir l'entièreté du tableau et d'appliquer la fonction ``f`` à chacun des éléments. A la fin de son exécution, le programme retournera l'élément qui donne la valeur minimale. Un tel problème est très facile à découper en threads. Il suffit de découper le tableau en ``N`` sous-tableaux, de lancer un thread de calcul sur chaque sous-tableau et ensuite de fusionner les résultats de chaque thread. - -Un autre problème est de trier le contenu d'un tel tableau dans l'ordre croissant. De nombreux algorithmes séquentiels de tri existent pour ordonner un tableau. La découpe de ce problème en thread est nettement moins évidente que dans le problème précédent et les algorithmes de tri adaptés à une utilisation dans plusieurs threads ne sont pas une simple extension des algorithmes séquentiels. - -Dans les années 1960s, à l'époque des premières réflexions sur l'utilisation de plusieurs processeurs pour résoudre un problème, Gene Amdahl [Amdahl1967]_ a analysé quelles étaient les gains que l'on pouvait attendre de l'utilisation de plusieurs processeurs. Dans sa réflexion, il considère un programme ``P`` qui peut être découpé en deux parties : - - - une partie purement séquentielle. Il s'agit par exemple de l'initialisation de l'algorithme utilisé, de la collecte des résultats, ... - - une partie qui est peut être parallélisée. Il s'agit en général du coeur de l'algorithme. - -Plus les opérations réalisées à l'intérieur d'un programme sont indépendantes entre elles, plus le programme fonction en parallèle et inversement. Pour Amdahl, si le temps d'exécution d'un programme séquentiel est `T` et qu'une fraction `f` de ce programme peut être parallélisée, alors le gain qui peut être obtenu de la parallélisation est :math:`\frac{T}{T \times( (1-f)+\frac{f}{N})}=\frac{1}{ (1-f)+\frac{f}{N}}` lorsque le programme est découpé en `N` threads. Cette formule, connue sous le nom de la :term:`loi de Amdahl` fixe une limite théorique sur le gain que l'on peut obtenir en parallélisant un programme. La figure ci-dessous [#famdahl]_ illustre le gain théorique que l'on peut obtenir en parallélisant un programme en fonction du nombre de processeur et pour différentes fractions parallélisées. - -.. figure:: /Threads/figures/500px-AmdahlsLaw.png - :align: center - :scale: 80 - - Loi de Amdahl (source `wikipedia <http://en.wikipedia.org/wiki/Amdahl's_law>`_) - -.. spelling:: - - profiling - -La loi de Amdahl doit être considérée comme un maximum théorique qui est difficile d'atteindre. Elle suppose que la parallélisation est parfaite, c'est-à -dire que la création et la terminaison de threads n'ont pas de coût en terme de performance. En pratique, c'est loin d'être le cas et il peut être difficile d'estimer a priori le gain qu'une parallélisation permettra d'obtenir. En pratique, avant de découper un programme séquentiel en threads, il est important de bien identifier la partie séquentielle et la partie du programme pouvant être parallélisée. Si la partie séquentielle est trop importante, le gain dû à la parallélisation risque d'être faible. Si par contre la partie purement séquentielle est faible, il est possible d'obtenir théoriquement des gains élevés. Le tout sera de trouver des solutions efficaces qui permettront aux threads de fonctionner le plus indépendamment possible. - -En pratique, avant de s'attaquer à la découpe d'un programme séquentiel en threads, il est important de bien comprendre quelles sont les parties du programme qui sont les plus consommatrices de temps CPU. Ce seront souvent les boucles ou les grandes structures de données. Si le programme séquentiel existe, il est utile d'analyser son exécution avec des outils de `profiling` tels que `gprof(1)`_ [Graham+1982]_ ou `oprofile <http://oprofile.sourceforge.net/>`_. Un profiler est un logiciel qui permet d'analyser l'exécution d'un autre logiciel de façon à pouvoir déterminer notamment quelles sont les fonctions ou parties du programmes les plus exécutées. Ces parties de programme sont celles sur lesquelles l'effort de parallélisation devra porter en pratique. - -Dans un programme découpé en threads, toute utilisation de fonctions de coordination comme des sémaphores ou des mutex, bien qu'elle soit nécessaire pour la correction du programme, risque d'avoir un impact négatif sur les performances. Pour s'en convaincre, il est intéressant de réfléchir au problème des producteurs-consommateurs. Il correspond à de nombreux programmes réels. Les performances d'une implémentation du problème des producteurs consommateurs dépendront fortement de la taille du buffer entre les producteurs et les consommateurs et de leur nombre et/ou vitesses relatives. Idéalement, il faudrait que le buffer soit en moyenne rempli à moitié. De cette façon, chaque producteur pourra déposer de l'information dans le buffer et chaque consommateur pourra en retirer. Si le buffer est souvent vide, cela indique que les consommateurs sont plus rapides que les producteurs. Ces consommateurs risquent d'être inutilement bloqués, ce qui affectera les performances. Il en va de même si le buffer était plein. Dans ce cas, les producteurs seraient souvent bloqués. - -.. rubric:: Footnotes - -.. [#fSysV] Les systèmes Unix supportent également des sémaphores dits `System V` du nom de la version de Unix dans laquelle ils ont été introduits. Dans ces notes, nous nous focalisons sur les sémaphores POSIX qui ont une API un peu plus simple que les es sémaphores `System V`. Les principales fonctions pour les sémaphores `System V` sont `semget(3posix)`_, `semctl(3posix)`_ et `semop(3posix)`_. - - -.. [#fregister] Les premiers compilateurs C permettaient au programmeur de donner des indications au compilateur en faisant précéder les déclarations de certaines variables avec le qualificatif ``register`` [KernighanRitchie1998]_. Ce qualificatif indiquait que la variable était utilisée fréquemment et que le compilateur devrait en placer le contenu dans un registre. Les compilateurs actuels sont nettement plus performants et ils sont capables de détecter quelles sont les variables qu'il faut placer dans un registre. Il est inutile de chercher à influencer le compilateur en utilisant le qualificatif ``register``. Les compilateurs actuels, dont `gcc(1)`_ supportent de nombreuses `options <http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html>`_ permettant d'optimiser les performances des programmes compilés. Certaines ont comme objectif d'accélérer l'exécution du programme, d'autres visent à réduire sa taille. Pour les programmes qui consomment beaucoup de temps CPU, il est utile d'activer l'optimisation du compilateur. - -.. [#fstrerror] Cette implémentation est adaptée de http://opensource.apple.com/source/gcc/gcc-926/libiberty/strerror.c et est dans le domaine public. - -.. [#fstrerror_r] Cette implémentation est adaptée de https://www-asim.lip6.fr/trac/netbsdtsar/browser/vendor/netbsd/5/src/lib/libc/string/strerror_r.c?rev=2 et est `Copyright (c) 1988 Regents of the University of California.` - -.. [#famdahl] Source : http://en.wikipedia.org/wiki/Amdahl's_law - - diff --git a/Theorie/Threads/figures/188px-Matrix_multiplication_diagram.png b/Theorie/Threads/figures/188px-Matrix_multiplication_diagram.png deleted file mode 100644 index dab4d022d19e7ec9a5c5e319624e06b83c4b8e6a..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/figures/188px-Matrix_multiplication_diagram.png and /dev/null differ diff --git a/Theorie/Threads/figures/500px-AmdahlsLaw.png b/Theorie/Threads/figures/500px-AmdahlsLaw.png deleted file mode 100644 index 88f5ca4a67c9ef54f4524406af8be2c6e0b4de03..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/figures/500px-AmdahlsLaw.png and /dev/null differ diff --git a/Theorie/Threads/figures/534px-Transistor_Count_and_Moore's_Law_-_2011.png b/Theorie/Threads/figures/534px-Transistor_Count_and_Moore's_Law_-_2011.png deleted file mode 100644 index 59e3a76c16693c6ab9b23408b80a0684f83344a7..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/figures/534px-Transistor_Count_and_Moore's_Law_-_2011.png and /dev/null differ diff --git a/Theorie/Threads/figures/figures-001-c.png b/Theorie/Threads/figures/figures-001-c.png deleted file mode 100644 index a0ff019643f3ca8dc37280af260db5b8705ad6b6..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/figures/figures-001-c.png and /dev/null differ diff --git a/Theorie/Threads/figures/figures-002-c.png b/Theorie/Threads/figures/figures-002-c.png deleted file mode 100644 index 688d0bcf532749b37b71add50e6c7e2f3a25ae4c..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/figures/figures-002-c.png and /dev/null differ diff --git a/Theorie/Threads/figures/figures-S7-001-c.png b/Theorie/Threads/figures/figures-S7-001-c.png deleted file mode 100644 index 974e4c0f84ef855d882f4814f0458baefa3ee289..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/figures/figures-S7-001-c.png and /dev/null differ diff --git a/Theorie/Threads/figures/figures-S7.001.png b/Theorie/Threads/figures/figures-S7.001.png deleted file mode 100644 index c4d7204a604b7051abdbae8a0ffca652e5bfc145..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/figures/figures-S7.001.png and /dev/null differ diff --git a/Theorie/Threads/figures/figures.001.png b/Theorie/Threads/figures/figures.001.png deleted file mode 100644 index 1eafaaf6424b4e487ecc5bade3da7fbbc379ece0..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/figures/figures.001.png and /dev/null differ diff --git a/Theorie/Threads/figures/figures.002.png b/Theorie/Threads/figures/figures.002.png deleted file mode 100644 index c628b10544100f2505b2442139dcc5da9acc23cb..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/figures/figures.002.png and /dev/null differ diff --git a/Theorie/Threads/figures/figures.003.png b/Theorie/Threads/figures/figures.003.png deleted file mode 100644 index b82cd30a4334bc15f26d27da2e9e245beb5ca91b..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/figures/figures.003.png and /dev/null differ diff --git a/Theorie/Threads/figures/figures.004.png b/Theorie/Threads/figures/figures.004.png deleted file mode 100644 index 3445a331b7c406b02d4d801708041982a18afcac..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/figures/figures.004.png and /dev/null differ diff --git a/Theorie/Threads/figures/figures.005.png b/Theorie/Threads/figures/figures.005.png deleted file mode 100644 index 27881b8978fbc2b348e172c99ff3e45936ff4b0a..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/figures/figures.005.png and /dev/null differ diff --git a/Theorie/Threads/figures/figures.006.png b/Theorie/Threads/figures/figures.006.png deleted file mode 100644 index 32116684e932b767b2fcab2a87a5d6304b3a29ec..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/figures/figures.006.png and /dev/null differ diff --git a/Theorie/Threads/figures/figures.007.png b/Theorie/Threads/figures/figures.007.png deleted file mode 100644 index d1bb346e918b4b94f3b67bde3dc0a9ebcad16be3..0000000000000000000000000000000000000000 Binary files a/Theorie/Threads/figures/figures.007.png and /dev/null differ diff --git a/Theorie/Threads/processus.rst b/Theorie/Threads/processus.rst deleted file mode 100644 index 57e8657acb3a49b93b3b79512cdfca94dfed1743..0000000000000000000000000000000000000000 --- a/Theorie/Threads/processus.rst +++ /dev/null @@ -1,646 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. _processus: - - -Les processus -============= - -Un système d'exploitation multitâche et multi-utilisateurs tel que Unix ou Linux permet d'exécuter de nombreux programmes simultanément. Sous Unix, les programmes sont exécutés sous la forme de :term:`processus`. Un processus peut être défini comme étant une instance de programme qui est en train d'être exécutée sur un ou plusieurs processeurs sous le contrôle d'un système d'exploitation. Un processus comprend donc un ensemble d'instructions pour le processeur, mais aussi des données qui sont stockées en mémoire et un contexte (si le processus utilise un seul thread d'exécution, plusieurs contextes sinon). En outre, le système d'exploitation maintient un certain nombre de structures de données qui sont nécessaires au bon fonctionnement du processus. Ces structures de données sont créées au démarrage du processus, mises à jour durant la vie du processus et supprimées lorsque le processus se termine. - - -Les librairies --------------- - -Lorsqu'un programme s'exécute à l'intérieur d'un processus, il exécute des instructions qui ont différentes `origines`. Il y a bien entendu les instructions qui proviennent du code source du programme qui a été converti en assembleur par le compilateur. Ces instructions correspondent au code source développé par le programmeur. Il s'agit notamment de toutes les opérations mathématiques et logiques, les boucles et les appels de fonctions internes au programme. Comme nous l'avons vu précédemment, ces instructions peuvent provenir d'un seul module ou de plusieurs modules. Dans ce dernier cas, le linker intervient pour combiner différents modules en un exécutable complet. - -A côté des instructions qui correspondent aux lignes de code écrites par le développeur du programme, un processus va également exécuter de nombreuses fonctions qui font partie d'une des librairies standard du système. Tout environnement de développement comprend des librairies qui permettent de faciliter le travail des programmeurs en leur fournissant des fonctions permettant de résoudre de nombreux problèmes classiques. Un système d'exploitation tel que Unix ou Linux contient de nombreuses librairies de ce type. Nous avons déjà eu l'occasion de discuter des fonctions provenant de la librairie standard comme `printf(3)`_ ou `malloc(3)`_ et celles de la librairie `pthreads(7)`_. Ce ne sont que deux librairies parmi d'autres. Un système Linux contient plusieurs centaines de librairies utilisables par le programmeur. - -A titre d'exemple, considérons la librairie `math.h(7posix)`_. Cette librairie contient de nombreuses fonctions mathématiques. Pour les utiliser dans un programme, il faut non seulement y inclure le fichier header `math.h`_ qui contient les prototypes et constantes utilisées par la librairie, mais aussi indiquer au linker que l'exécutable doit être lié avec la librairie `math.h(7posix)`_. Cela se fait en utilisant le flag ``-l`` de `gcc(1)`_. - -.. literalinclude:: /Threads/S8-src/math.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Le programme :download:`/Threads/S8-src/math.c` ci-dessus doit être compilé en utilisant la commande ``gcc -Wall -Werror math.c -o math -lm``. Le paramètre ``-lm`` indique au compilateur qu'il doit charger la librairie ``m``. Cette librairie, est une des librairies standard du système, elle réside généralement dans le répertoire ``/usr/lib`` [#flib]_. En pratique, `gcc(1)`_ charge automatiquement la librairie ``C`` standard lors de la compilation de tout programme. Cela revient à utiliser implicitement le paramètre ``-lc``. - -Lors de l'utilisation de telles librairies, on s'attendrait à ce que toutes les instructions correspondant aux fonctions de la librairie utilisée soient présentes à l'intérieur de l'exécutable. En pratique, ce n'est pas exactement le cas. Même si notre programme d'exemple utilise `fmax(3)`_ de la librairie `math.h(7posix)`_ et `printf(3)`_ de la librairie standard, son exécutable ne contient que quelques milliers d'octets. - -.. code-block:: console - - $ ls -l math* - -rwxr-xr-x 1 obo stafinfo 6764 Mar 15 2012 math - -rw-r--r-- 1 obo stafinfo 373 Mar 15 2012 math.c - -Une analyse plus détaillée de l'exécutable avec `objdump(1)`_ révèle que si l'exécutable contient bien des appels à ces fonctions, leur code n'y est pas entièrement inclus. - -.. code-block:: console - - $gcc -g -lm math.c -o math - $objdump -S -d math - math: file format elf64-x86-64 - ... - 0000000000400468 <fmax@plt>: - 400468: ff 25 fa 04 20 00 jmpq *0x2004fa(%rip) # 600968 < - _GLOBAL_OFFSET_TABLE_+0x28> - 40046e: 68 02 00 00 00 pushq $0x2 - 400473: e9 c0 ff ff ff jmpq 400438 <_init+0x18> - ... - #include <stdio.h> - #include <stdlib.h> - #include <math.h> - int main (int argc, char *argv[]) { - 400564: 55 push %rbp - 400565: 48 89 e5 mov %rsp,%rbp - 400568: 48 83 ec 20 sub $0x20,%rsp - 40056c: 89 7d ec mov %edi,-0x14(%rbp) - 40056f: 48 89 75 e0 mov %rsi,-0x20(%rbp) - double n1=1.0; - 400573: 48 b8 00 00 00 00 00 mov $0x3ff0000000000000,%rax - 40057a: 00 f0 3f - 40057d: 48 89 45 f0 mov %rax,-0x10(%rbp) - double n2=-3.14; - 400581: 48 b8 1f 85 eb 51 b8 mov $0xc0091eb851eb851f,%rax - 400588: 1e 09 c0 - 40058b: 48 89 45 f8 mov %rax,-0x8(%rbp) - printf("Maximum : %f\n",fmax(n1,n2)); - 40058f: f2 0f 10 4d f8 movsd -0x8(%rbp),%xmm1 - 400594: f2 0f 10 45 f0 movsd -0x10(%rbp),%xmm0 - 400599: e8 ca fe ff ff callq 400468 <fmax@plt> - 40059e: b8 b8 06 40 00 mov $0x4006b8,%eax - 4005a3: 48 89 c7 mov %rax,%rdi - 4005a6: b8 01 00 00 00 mov $0x1,%eax - 4005ab: e8 98 fe ff ff callq 400448 <printf@plt> - return(EXIT_SUCCESS); - 4005b0: b8 00 00 00 00 mov $0x0,%eax - } - -La taille réduite des exécutables sous Linux et de nombreuses variantes de Unix s'explique par l'utilisation de librairies partagées. Un programme peut utiliser deux types de librairies : des librairies statiques et des librairies partagées. Une :term:`librairie statique` (ou :term:`static library` en anglais) est une librairie de fonctions qui est intégrée directement avec le programme. Elle fait entièrement partie de l'exécutable. C'est la première solution pour intégrer des librairies dans un programme. Son avantage principal est que l'exécutable est complet et comprend toutes les instructions qui sont nécessaires au fonctionnement du programme. Malheureusement, tous les programmes qui utilisent des fonctions d'une librairie courante, comme par exemple la librairie standard, doivent inclure le code relatif à toutes les fonctions qu'ils utilisent. Sachant que chaque programme ou presque utilise des fonctions comme `printf(3)`_, cela conduit à sauvegarder de très nombreuses copies du même code. Ce problème peut être résolu en utilisant des librairies partagées [#fdynamic]_ . Une :term:`librairie partagée` (ou :term:`shared library` en anglais) est un ensemble de fonctions qui peuvent être appelées par un programme mais sont stockées dans un seul fichier sur disque. Ce fichier unique est utilisé automatiquement par tous les programmes qui utilisent des fonctions de la librairie. - -Il est parfois intéressant de pouvoir créer une librairie qui peut être liée de façon statique avec des programmes, par exemple lorsque ceux-ci doivent être exécutés sur d'autres ordinateurs que ceux sur lesquels ils ont été compilés. A titre d'illustration, considérons une librairie minuscule contenant une seule fonction ``imax`` qui calcule le maximum entre deux entiers. L'implémentation de cette fonction est très simple. - -.. literalinclude:: /Threads/S8-src/imax.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -Cette fonction est déclarée dans le fichier header ``imax.h`` et peut être utilisée dans un programme comme ci-dessous. - -.. literalinclude:: /Threads/S8-src/imath.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -En pratique, la construction d'une librairie se fait en deux étapes principales. Tout d'abord, il faut compiler les fichiers objet correspondant aux différents modules de la librairie. Cela peut se faire avec `gcc(1)`_ comme pour un programme C classique. Ensuite, il faut regrouper les différents modules dans une archive qui constituera la librairie qui peut être utilisée par des programmes. Par convention, toutes les librairies ont un nom qui commence par ``lib`` et se termine par l'extension ``.a``. Sous Linux, cette opération est réalisée par l'utilitaire `ar(1)`_. La page de manuel de `ar(1)`_ décrit plus en détails son utilisation. En pratique, les opérations les plus fréquentes avec `ar(1)`_ sont : - - - ajout d'un module objet à une librairie : ``ar r libname.a module.o`` - - suppression d'un module objet d'une librairie : ``ar d libname.a module.o`` - -Il est aussi possible de lister le contenu de la librairie ``libname.a`` avec la commande ``ar tv libname.a``. - -L'archive contenant la librairie peut être liée en utilisant le linker à n'importe quel programme qui en utilise une ou plusieurs fonctions. Le linker de `gcc(1)`_ peut effectuer cette opération comme illustré par le ``Makefile`` ci-dessous. Il faut noter que l'argument ``--static`` permet de forcer le compilateur à inclure le code de la librairie dans l'exécutable. - -.. literalinclude:: /Threads/S8-src/Makefile-lib - :encoding: utf-8 - :language: makefile - -Ce ``Makefile`` est un petit peu plus long que ceux que nous avons utilisés jusque maintenant. Il illustre une structure courante pour de nombreux fichiers ``Makefile``. La première partie définit des constantes qui sont utilisées dans le reste du ``Makefile``. Il s'agit tout d'abord du compilateur et du programme de construction de librairies qui sont utilisés. Définir ces programmes comme des constantes dans le ``Makefile`` permet de facilement en changer lorsque c'est nécessaire. Ensuite, trois constantes sont définies avec les arguments de base du compilateur et de ``ar``. A nouveau, définir ces constantes une fois pour toutes facilite leur modification. Ensuite, la première cible est la cible ``all:``. Comme c'est la première, c'est la cible par défaut qui sera utilisée lorsque `make(1)`_ est appelé sans argument. Elle dépend de l'exécutable ``imath`` qui est une des cibles du ``Makefile``. La cible ``clean:`` permet d'effacer les fichiers objet et exécutables construites par le ``Makefile``. Il est utile d'avoir une telle cible lorsque l'on doit diffuser un projet en C ou le rendre dans le cadre d'un cours. Enfin, les autres cibles correspondent aux fichiers objet, à la librairie et à l'exécutable qui sont construits. La commande ``@echo`` affiche ses arguments sur la sortie standard. Enfin, la chaîne de caractères ``$(GCC)`` est remplacée par le constante définie au début du fichier. Des compléments d'information sur `make(1)`_ peuvent être obtenus dans divers documents dont `make(1)`_, [Mecklenburg+2004]_ ou [GNUMake]_. - -Lorsqu'un programme est compilé de façon à utiliser une librairie dynamique, c'est le système d'exploitation qui analyse le programme lors de son chargement et intègre automatiquement les fonctions des librairies qui sont nécessaires à son exécution. L'entête de l'exécutable contient de l'information générée par le compilateur qui permet de localiser les librairies dynamiques qui doivent être intégrées de cette façon. L'utilitaire `ldd(1)`_ permet de visualiser quelles sont les librairies partagées utilisées par un programme. - -.. code-block:: console - - $ ldd imath - linux-vdso.so.1 => (0x00007fffe41ff000) - libc.so.6 => /lib64/libc.so.6 (0x0000003eb2400000) - /lib64/ld-linux-x86-64.so.2 (0x0000003eb2000000) - - -Appels Système ---------------- -.. index:: kernel - -Outre l'utilisation de fonctions de librairies, les programmes doivent interagir avec le système d'exploitation. Un système d'exploitation tel que Unix comprend à la fois des utilitaires comme `grep(1)`_, `ls(1)`_, ... qui sont directement exécutables depuis le shell et un noyau ou :term:`kernel` en anglais. Le :term:`kernel` contient les fonctions de base du système d'exploitation qui lui permettent à la fois d'interagir avec le matériel mais aussi de gérer les processus des utilisateurs. En pratique, le kernel peut être vu comme étant un programme spécial qui est toujours présent en mémoire. Parmi l'ensemble des fonctions contenues dans le :term:`kernel`, il y en a un petit nombre, typiquement de quelques dizaines à quelques centaines, qui sont utilisables par les processus lancés par les utilisateurs. Ce sont les appels système. Un :term:`appel système` est une fonction du :term:`kernel` qui peut être appelée par n'importe quel processus. Comme nous l'avons vu lorsque nous avons décrit le fonctionnement du langage d'assemblage, l'exécution d'une fonction dans un programme comprend plusieurs étapes : - - 1. Placer les arguments de la fonction à un endroit (la pile) où la fonction peut y accéder - 2. Sauvegarder sur la pile l'adresse de retour - 3. Modifier le registre ``%eip`` de façon à ce que la prochaine instruction à exécuter soit celle de la fonction à exécuter - 4. La fonction récupère ses arguments (sur la pile) et réalise son calcul - 5. La fonction sauve son résultat à un endroit (``%eax``) convenu avec la fonction appelante - 6. La fonction récupère l'adresse de retour sur la pile et modifie ``%eip`` de façon à retourner à la fonction appelante - -L'exécution d'un appel système comprend les mêmes étapes avec une différence importante c'est que le flux d'exécution des instructions doit passer du programme utilisateur au noyau du système d'exploitation. Pour comprendre le fonctionnement et l'exécution d'un appel système, il est utile d'analyser les six points mentionnés ci-dessus. - -Le premier problème à résoudre pour exécuter un appel système est de pouvoir placer les arguments de l'appel système dans un endroit auquel le :term:`kernel` pourra facilement accéder. Il existe de nombreux appels systèmes avec différents arguments. La liste complète des appels systèmes est reprise dans la page de manuel `syscalls(2)`_. La table ci-dessous illustre quelques appels systèmes et leurs arguments. - -============== ===================== -Appel système Arguments -============== ===================== -`getpid(2)`_ ``void`` -`fork(2)`_ ``void`` -`read(2)`_ ``int fildes, void *buf, size_t nbyte`` -`kill(2)`_ ``pid_t pid, int sig`` -`brk(2)`_ ``const void *addr`` -============== ===================== - -Sous Linux, les arguments d'un appel système sont placés par convention dans des registres. Sur [IA32]_, le premier argument est placé dans le registre ``%ebx``, le second dans ``%ecx``, ... Le :term:`kernel` peut donc facilement récupérer les arguments d'un appel système en lisant le contenu des registres. - -Le second problème à résoudre est celui de l'adresse de retour. Celle-ci est automatiquement sauvegardée lors de l'exécution de l'instruction qui fait appel au kernel, tout comme l'instruction ``calll`` sauvegarde directement l'adresse de retour d'une fonction appelée sur la pile. - -.. index:: mode utilisateur, mode protégé - -Le troisième problème à résoudre est de passer de l'exécution du processus utilisateur à l'exécution du :term:`kernel`. Les processeurs actuels peuvent fonctionner dans au minimum deux modes : le :term:`mode utilisateur` et le :term:`mode protégé`. Lorsque le processeur fonctionne en mode protégé, toutes les instructions du processeur et toutes les adresses mémoire sont utilisables. Lorsqu'il fonctionne en mode utilisateur, quelques instructions spécifiques de manipulation du matériel et certaines adresses mémoire ne sont pas utilisables. Cette division en deux modes de fonctionnement permet d'avoir une séparation claire entre le système d'exploitation et les processus lancés par les utilisateurs. Le noyau du système d'exploitation s'exécute en mode protégé et peut donc utiliser entièrement le processeur et les dispositifs matériels de l'ordinateur. Les processus utilisateurs par contre s'exécutent en mode utilisateur. Ils ne peuvent donc pas directement exécuter les instructions permettant une interaction avec des dispositifs matériel. Cette interaction doit passer par le noyau du système d'exploitation qui sert de médiateur et vérifie la validité des demandes faites par un processus utilisateur. - -.. index:: init - -Les transitions entre les modes protégé et utilisateur sont importantes car elles rythment le fonctionnement du système d'exploitation. Lorsque l'ordinateur démarre, le processeur est placé en mode protégé et le :term:`kernel` se charge. Il initialise différentes structures de données et lance `init(8)`_ le premier processus du système. Dès que `init(8)`_ a été lancé, le processeur passe en mode utilisateur et exécute les instructions de ce processus. Après cette phase de démarrage, les instructions du :term:`kernel` seront exécutées lorsque soit une interruption matérielle surviendra ou qu'un processus utilisateur exécutera un appel système. L'interruption matérielle place automatiquement le processeur en mode protégé et le :term:`kernel` exécute la routine de traitement d'interruption correspondant à l'interruption qui est apparue. Un appel système démarre par l'exécution d'une instruction spéciale (parfois appelée interruption logicielle) qui place le processeur en mode protégé et puis démarre l'exécution d'une instruction placée à une adresse spéciale en mémoire. Sur certains processeurs de la famille [IA32]_, l'instruction ``int 0x80`` permet ce passage du mode utilisateur au mode protégé. Sur d'autres processeurs, c'est l'instruction ``syscall`` qui joue ce rôle. L'exécution de cette instruction est la seule possibilité pour un programme d'exécuter des instructions du :term:`kernel`. En pratique, cette instruction fait passer le processeur en mode protégé et démarre l'exécution d'une routine du :term:`kernel`. Cette routine commence par sauvegarder le contexte du processus qui exécute l'appel système demandé. Chaque appel système est identifié par un nombre entier et le :term:`kernel` contient une table avec pour chaque appel système l'adresse de la fonction à exécuter pour cet appel système. En pratique, le numéro de l'appel système à exécuter est placé par le processus appelant dans le registre ``%eax``. - -L'appel système peut donc s'exécuter en utilisant les arguments qui se trouvent dans les différents registres. Lorsque l'appel système se termine, le résultat est placé dans le registre ``%eax`` et une instruction spéciale permet de retourner en mode utilisateur et d'exécuter dans le processus appelant l'instruction qui suit celle qui a provoqué l'exécution de l'appel système. Si l'appel système a échoué, le :term:`kernel` doit aussi mettre à jour le contenu de ``errno`` avant de retourner au processus appelant. - -Ces opérations sont importantes pour comprendre le fonctionnement d'un système informatique et la différence entre un appel système et une fonction de la librairie. En pratique, la librairie cache cette complexité au programmeur en lui permettant d'utiliser des fonctions de plus haut niveau [#fsyscall]_ . Cependant, il faut être conscient que ces fonctions s'appuient elles-même sur des appels systèmes pour s'exécuter. Ainsi par exemple, la fonction `printf(3)`_ utilise l'appel système `write(2)`_ pour écrire sur la sortie standard. La commande `strace(1)`_ permet de tracer l'ensemble des appels systèmes faits par un processus. A titre d'exemple, voici les appels systèmes effectués par le programme ``imath`` présenté plus haut. - -.. code-block:: console - - $ strace ./imath - execve("./imath", ["./imath"], [/* 34 vars */]) = 0 - uname({sys="Linux", node="baluran.info.ucl.ac.be", ...}) = 0 - brk(0) = 0xa31000 - brk(0xa32180) = 0xa32180 - arch_prctl(ARCH_SET_FS, 0xa31860) = 0 - brk(0xa53180) = 0xa53180 - brk(0xa54000) = 0xa54000 - fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0 - mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1f8fd44000 - write(1, "Maximum : 1\n", 12Maximum : 1 - ) = 12 - exit_group(0) = ? - - -.. Ces opérations sont réalisées en utilisant des appels systèmes. Lors de son exécution un programme exécute non seulement des instructions qui ont été compilées sur base du code source du programme, mais aussi des fonctions faisant partie d'une des librairies standard du système. Certaines librairies contiennent des fonctions indépendantes, comme la librairie mathématique, d'autres font appel au système d'exploitation directement ou indirectement. font partie du programme, ce sont les peut faire appels à trois petits de fonctions prin Dans les chapitres précédents, nous avons développé des programmes qui d'abord utilisaient des fonctions faisant partie Jusque maintenant, nous - - -.. index:: fork - -Création d'un processus ------------------------ - -Pour comprendre le fonctionnement de Unix, il est utile d'analyser plus en détails toutes les opérations qui sont effectuées à chaque fois que l'on lance un programme depuis un shell tel que `bash(1)`_. Considérons l'exécution de la commande ``/bin/true`` depuis le shell. - -Schématiquement, l'exécution de ce programme se déroule comme suit. Le shell va d'abord localiser [#fpath]_ l'exécutable ``/bin/true`` qui est stocké dans le système de fichiers. Ensuite, il va créer un processus et y exécuter l'exécutable. Le shell va ensuite attendre la fin de l'exécution du programme ``true`` et récupérer sa valeur de retour (retournée par `exit(2)`_) pour ensuite poursuivre son exécution. - - -.. todo:: figure à ajouter plus tard pour illustrer ce fonctionnement - -Comme nous l'avons expliqué plus haut, le :term:`kernel` Linux gère l'ensemble des processus qui sont utilisés à un moment. Il intervient pour toutes les opérations de création et de fin d'un processus. La création d'un processus est un événément important dans un système d'exploitation. Elle permet notamment l'exécution de programmes. Ces opérations nécessitent une interaction avec le :term:`kernel` et se font donc en utilisant des appels systèmes. Avant d'analyser en détails comment Linux supporte précisément la création de processus, il est intéressant de réfléchir aux opérations qui doivent être effectuées lors de l'exécution d'un programme. Considérons par exemple un utilisateur qui exécute la commande ``/usr/bin/expr 1 + 2`` depuis un shell `bash(1)`_ interactif. Pour exécuter cette commande, il va falloir exécuter un nouveau processus contenant les instructions assembleur se trouvant dans l'exécutable ``/usr/bin/expr``, lui passer les arguments ``1 + 2``, l'exécuter, récupérer sa valeur de retour et la retourner au shell qui pourra l'utiliser et poursuivre son exécution. - -.. index:: processus père, processus fils - -Les designers de Unix ont choisi de construire un appel système pour chacune de ces opérations. Le premier est l'appel système `fork(2)`_. C'est l'appel système qui permet de créer un processus. Schématiquement, cet appel système crée une copie complète du processus qui l'a exécuté. Après exécution de `fork(2)`_, il y a deux copies du même processus en mémoire. Le processus qui a exécuté `fork(2)`_ est considéré comme étant le :term:`processus père` tandis que celui qui a été créé par l'exécution de `fork(2)`_ est le :term:`processus fils`. - -.. code-block:: c - - #include <unistd.h> - - pid_t fork(void); - - -L'appel système `fork(2)`_ est atypique car il est exécuté par un processus mais provoque la création d'un second processus qui est identique au premier. Après l'exécution de l'appel système `fork(2)`_, il y a donc deux séquences d'instructions qui vont s'exécuter, l'une dans le processus père et l'autre dans le processus fils. Le processus fils démarre son exécution à la récupération du résultat de l'appel système `fork(2)`_ effectué par son père. Le processus père et le processus fils récupèrent une valeur de retour différente pour cet appel système. Cette valeur de retour est d'ailleurs la seule façon de distinguer le :term:`processus père` du :term:`processus fils` lorsque celui-ci démarre. - - - l'appel système `fork(2)`_ retourne la valeur ``-1`` en cas d'erreur et met à jour la variable ``errno``. En cas d'erreur, aucun processus n'est créé. - - l'appel système `fork(2)`_ retourne la valeur ``0`` dans le processus fils. - - l'appel système `fork(2)`_ retourne une valeur positive dans le processus père. Cette valeur est l'identifiant du processus fils créé. - -Pour bien comprendre le fonctionnement de `fork(2)`_, analysons l'exemple :download:`/Threads/S8-src/fork.c` ci-dessous : - -.. literalinclude:: /Threads/S8-src/fork.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Lors de son exécution, ce programme affiche les deux lignes suivantes sur sa sortie standard : - -.. literalinclude:: /Threads/S8-src/fork.out - :encoding: utf-8 - :language: console - -Lors de l'exécution de ce programme, deux variables sont initialisées en mémoire. La variable globale ``g`` est initialisée à la valeur ``0`` tandis que le variable locale ``l`` est initialisée à la valeur ``1252``. `malloc(3)`_ est utilisé pour réserver une zone mémoire sur le :term:`heap` et son contenu est initialisé à ``-1``. Lorsque le processus père fait appel à `fork(2)`_ le noyau du système d'exploitation crée une copie identique à celui-ci en mémoire. Cette copie contient tous les segments du processus père (code, données, heap et stack) dans l'état exact dans lequel ils étaient au moment de l'exécution de l'appel système `fork(2)`_. Le contexte du processus père est copié et devient le contexte du processus fils. A cet instant, les deux processus sont complètement identiques à l'exception de certaines données qui sont maintenues par le système d'exploitation, comme l'identifiant de processus. Chaque processus qui s'exécute sur un système Unix a un identifiant unique et est retourné par l'appel système `getpid(2)`_. Le processus père et le processus fils ont un identifiant différent. - -Les deux processus vont se différencier dès la fin de l'exécution de l'appel système `fork(2)`_. Comme tout appel système, `fork(2)`_ place sa valeur de retour dans le registre ``%eax``. Comme indiqué plus haut, cette valeur sera positive dans le processus père. Celui-ci exécute ``sleep(2);`` et reste donc bloqué pendant deux secondes avant d'afficher un message sur sa sortie standard. Le processus fils de son côté incrémente les variables ``l`` et ``g`` et modifie la zone mémoire pointée par ``*m`` puis affiche leur contenu sur sa sortie standard puis se termine. - -L'exécution de ce programme illustre bien que le processus fils démarre avec une copie du processus père lorsque l'appel système `fork(2)`_ se termine. Le processus fils peut modifier les variables qui ont été initialisées par le processus mais ces modifications n'ont aucun impact sur les variables utilisées dans le processus père. Même si le processus père et le processus fils sont identiques au moment de la création du processus fils, ils sont complètement indépendants par après. C'est une différence importante avec les threads. Contrairement à ce qu'il se passe avec les threads, un processus père et un processus fils ne partagent ni le segment de données, ni le heap ni le stack. Ces zones mémoires ne peuvent pas être utilisées directement pour permettre à un processus père de communiquer avec son fils. - - -.. note:: Quel est le processus qui s'exécute en premier après `fork(2)`_ ? - - Après l'exécution de l'appel système `fork(2)`_ et la création du processus fils, le :term:`kernel` se trouve face à deux processus qui sont dans l'état `Ready`. Si il y a deux processeurs libres, le :term:`kernel` pourra les démarrer quasi simultanément. Par contre, si un seul processeur est disponible, le :term:`kernel` devra exécuter l'un des deux processus en premier. En pratique, rien ne permet de contrôler si le :term:`kernel` commencera d'abord l'exécution du processus père ou l'exécution du processus fils. Tout programme utilisant `fork(2)`_ doit pouvoir fonctionner correctement quel que soit l'ordre d'exécution des processus père et fils. - -Le :term:`kernel` gère les processus et attribue un identifiant à chaque processus. Le type ``pid_t`` est utilisé pour les identifiants de processus sous Unix. Ce type correspond à un nombre entier généralement non-signé. Le nombre maximum de processus qui peuvent être lancés sur un système Linux est un des paramètres fixés à la compilation ou au démarrage du kernel. L'appel système `getpid(2)`_ retourne l'identifiant du processus courant tandis que l'appel système `getppid(2)`_ retourne l'identifiant du processus père. - -.. literalinclude:: /Threads/S8-src/getpid.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Après l'exécution de `fork(2)`_ le processus père et le processus fils ont un identifiant de processus différent mais ils partagent certaines ressources qui sont gérées par le :term:`kernel`. C'est le cas notamment des flux standard :term:`stdin`, :term:`stdout` et :term:`stderr`. Lorsque le :term:`kernel` crée un processus fils, il conserve la même sortie standard que le processus père. C'est ce qui nous permet de visualiser le résultat de l'exemple précédent. Cependant, le processus père et le processus fils sont en concurrence pour écrire sur la sortie standard. Si aucune précaution n'est prise, ces deux processus risquent d'écrire de façon désordonnée sur la sortie standard. - -Pour mieux comprendre le problème, analysons l'exécution du programme ci-dessous. Il crée un processus fils puis le père et le fils écrivent sur :term:`stdout`. - -.. literalinclude:: /Threads/S8-src/fork-buf.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Lors de son exécution, il affiche les lignes suivantes sur :term:`stdout`. - -.. code-block:: console - - $ ./fork-buf - Processus : 852 - Processus : 853 - PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP - ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - -A première vue, on pourrait penser qu'il n'y a pas de problèmes d'accès concurrents à :term:`stdout` puisque la sortie produite par ce programme semble claire. Cependant, la fonction ``output`` utilisée par le père et le fils pour afficher les caractères ``P`` et ``f`` devrait permettre aux deux processus d'afficher des caractères ``P`` et ``f`` avec une certaine alternance. Il n'en est rien et la sortie standard semble indiquer que le processus père a affiché tous les caractères ``P`` simultanément. Ce n'est pas possible si l'on regarde le code source de la fonction ``output``. - -L'utilitaire `strace(1)`_ qui permet de tracer tous les appels systèmes effectués par un processus nous permet d'analyser comment le processus père et le processus fils écrivent sur :term:`stdout`. Lorsqu'ils utilisent les fonctions `printf(3)`_ et `putchar(3)`_ de la librairie standard, ils utilisent des fonctions qui finalement utilisent l'appel système `write(2)`_ qui est le seul permettant d'écrire sur un flux tel que :term:`stdout`. L'exécution de `strace(1)`_ montre que chaque processus effectue deux appels systèmes `write(2)`_. Le premier correspond à l'appel à `printf(3)`_ et le second à tous les appels à `putchar(3)`_ fait par le processus. - -.. code-block:: console - - strace -f -e trace=write ./fork-buf - Process 1398 attached - [pid 1398] write(1, "Processus : 1398\n", 17 <unfinished ...> - [pid 1397] write(1, "Processus : 1397\n", 17Processus : 1397 - ) = 17 - Processus : 1398 - [pid 1398] <... write resumed> ) = 17 - [pid 1398] write(1, "ffffffffffffffffffffffffffffffff"..., 60ffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffff) = 60 - Process 1398 detached - --- SIGCHLD (Child exited) @ 0 (0) --- - write(1, "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP"..., 61PPPPPPPPPPPPPPPPPPPPPP PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP - ) = 61 - -L'exécution d'un appel système tel que `write(2)`_ peut être couteux au niveau des performances. Une règle de bonne pratique est d'essayer de minimiser le nombre d'appels systèmes effectués par un programme. La librairie standard prend en compte cette règle et utilise un buffer dans lequel elle stocke temporairement les données produites par les fonctions telles que `printf(3)`_ ou `putchar(3)`_ avant de les écrire via `write(2)`_. Ce buffer peut être contrôlé via les fonctions `setvbuf(3)`_ et `setbuf(3)`_. Ces fonctions permettent de fixer la taille du buffer utilisé par la librairie standard. - -Lorsque le buffer de la librairie `stdio(3)`_ est désactivé en faisant ``setbuf(stdout,NULL);``, le processus père et le processus fils écrivent bien de façon entrelacée sur la sortie standard. - -.. code-block:: console - - $ ./fork-buf 1 - Processus : 1419 - PProcessus : 1420 - fffPffPffPffPfPfffPPfPPPfPfffPfPfPPfffPfPffPPfPPPPfPPfPPfPfPPfPfPffPfPfPffffPPfPPffPffPPfPfPfPPfPfPfPfPfPPffPPfffPfPPPP - -L'utilisation de `strace(1)` lors de cette exécution montre effectivement que chaque appel à la fonction `putchar(3)`_ provoque une exécution de l'appel système `write(2)`_ : - -.. code-block:: console - - [pid 1420] write(1, "f", 1f) = 1 - [pid 1419] write(1, "P", 1P) = 1 - [pid 1419] write(1, "P", 1P) = 1 - [pid 1420] write(1, "f", 1f) = 1 - - -.. note:: Faut-il modifier le buffer de la librairie `stdio(3)`_ ? - - En pratique, il est préférable de ne pas désactiver le buffer utilisé par la librairie `stdio(3)`_ car cela peut avoir des conséquences négatives sur les performances des programmes. Par contre, lorsque l'on développe des programmes qui utilisent plusieurs processus il est important de se souvenir de l'existence de ce buffer car il peut expliquer certains comportements qui pourraient apparaître comme étant bizarres lorsque l'on observe l'exécution de processus via les messages qu'ils affichent sur :term:`stderr` ou :term:`stdout`. Lorsque l'on soupçonne un comportement bizarre qui pourrait être expliqué par des interactions avec ce buffer, il est possible d'ajouter dans le programme des appels explicites à la fonction `fflush(3)`_ qui a pour effet de vider immédiatement le buffer de `stdio(3)`_. - - -.. note:: Génération de nombres aléatoires - - Le programme :download:`/Threads/S8-src/fork-buf.c` présenté ci-dessus est un exemple d'utilisation de nombres aléatoires. Ceux-ci sont générés avec la fonction `rand(3)`_ de la librairie standard. Cette fonction utilise un générateur de nombres aléatoires qui génère toujours la même séquence de nombres aléatoires lorsqu'elle est initialisée avec la même semence par la fonction `srand(3)`_. Souvent, les programmeurs qui utilisent des nombres aléatoires cherchent à ce que la séquence générée diffère d'une exécution du programme à l'autre. Une façon simple de procéder est d'utiliser comme semence la somme entre le temps courant retourné par `time(3posix)`_ et l'identifiant du processus obtenu via `getpid(2)`_. Une telle semence n'est cependant pas suffisante pour toutes les applications. Certaines applications cryptographiques notamment nécessitent des nombres aléatoires qui ne peuvent pas être facilement prédits. Pour ces applications, il est nécessaire d'utiliser des semences qui sont parfaitement aléatoires, comme `random(4)`_. - -.. index:: atexit, exit, wait, waitpid - -Fin d'un processus ------------------- - -Il y a deux événements importants dans la vie d'un processus sous Unix. Sa création avec l'appel système `fork(2)`_ et sa terminaison. Nous avons déjà vu qu'un programme C (et donc un processus) pouvait se terminer de deux façons principales [#fthread]_ : - - - par l'exécution de ``return(...)`` dans la fonction ``main`` - - par un appel explicite à la fonction `exit(3)`_ dans la fonction ``main`` ou n'importe quelle fonction du processus - -Ces fonctions appellent en fait la fonction de la librairie `exit(3)`_. Cette fonction permet de faire plus que simplement terminer le processus en cours d'exécution et retourner sa valeur de retour. Il est en effet possible d'associer une ou plusieurs fonctions de terminaison à `exit(3)`_ via la fonction `atexit(3)`_. Lorsque `exit(3)`_ est appelée, elle lance d'abord les fonctions enregistrées par `atexit(3)`_ puis termine correctement le processus. Ces fonctions de terminaison d'un processus sont utilisées lorsque par exemple un processus utilise des services particuliers du système d'exploitation comme par exemple une mémoire partagée entre plusieurs processus. Ces services consomment des ressources et il est nécessaire de les libérer correctement lorsqu'un processus se termine comme nous le verrons ultérieurement. - -L'exemple ci-dessous illustre brièvement l'utilisation de `atexit(3)`_. - -.. literalinclude:: /Threads/S8-src/atexit.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -.. index:: _exit - -Après avoir exécuté les fonctions de terminaison, la fonction `exit(3)`_ appelle `fflush(3)`_ sur tous les flux existants puis les ferme proprement. Ensuite, la fonction `exit(3)`_ exécute l'appel système `exit(2)`_. Cet appel système est particulier. C'est le seul appel système qui n'a pas de valeur de retour, et pour cause ! Il ferme tous les fichiers qui étaient encore ouverts (normalement un processus devrait fermer proprement tous ses fichiers avant de s'arrêter) et libère les ressources qui étaient associées au processus. - -.. code-block:: c - - #include <unistd.h> - - void _exit(int status); - -L'appel système `exit(2)`_ permet au processus qui se termine de retourner un statut à son processus père. Pour récupérer le statut de son fils, un processus père doit utiliser l'appel système `waitpid(2)`_. - - -.. code-block:: c - - #include <sys/types.h> - #include <sys/wait.h> - - pid_t waitpid(pid_t pid, int *status, int options); - -L'appel système `waitpid(2)`_ prend trois arguments. C'est un appel système bloquant. Le premier argument permet de spécifier quel est le processus fils dont la terminaison est attendue. Un premier argument négatif indique que `waitpid(2)`_ attend la terminaison de n'importe quel processus fils. Si le premier argument est positif, alors il contient un identifiant de processus fils et `waitpid(2)`_ attendra la terminaison de ce processus [#fwaitpid]_. Le second argument est un pointeur vers un entier qui après le retour de `waitpid(2)`_ contiendra le statut retourné par le processus fils. Le troisième argument permet de spécifier des options à `waitpid(2)`_ que nous n'utiliserons pas. La fonction `wait(2)`_ est une simplification de `waitpid(2)`_ qui permet d'attendre n'importe quel processus fils. ``wait(p)`` est en pratique équivalent à ``waitpid(-1,p,0)``. - -Un processus qui lance un processus fils avec `fork(2)`_ *doit* attendre la terminaison de son processus fils en utilisant `waitpid(2)`_. Le programme ci-dessous illustre l'utilisation de `waitpid(2)`_. - -.. literalinclude:: /Threads/S8-src/fork-wait.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -Dans ce programme, le processus père récupère la valeur retournée par le fils qu'il a créé. Lors de l'exécution de ``waitpid(pid,&status,0);``, la valeur de retour du fils est placée dans l'entier dont l'adresse est ``status``. Cet entier contient non-seulement la valeur de retour du processus fils (dans les 8 bits de poids faible), mais aussi une information permettant de déterminer si le processus fils s'est terminé correctement ou a été terminé de façon abrupte via l'utilisation de `kill(1)`_. Les macros ``WEXITSTATUS`` et ``WTERMSIG`` utilisées pour extraire la valeur de retour et la raison de la terminaison abrupte sont décrites dans `waitpid(2)`_. - -Même si un processus *doit* attendre la terminaison de tout processus fils qu'il a lancé, il arrive parfois qu'un processus n'attende pas ses fils. Cela peut arriver lorsqu'un processus s'arrête suite à une erreur avant de pouvoir récupérer ses fils. Ce cas est illustré par l'exemple ci-dessous dans lequel le processus père se termine sans attendre son fils. - -.. literalinclude:: /Threads/S8-src/fork-orphan.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -Du point de vue du :term:`kernel` cette situation est ennuyeuse car il maintient pour chaque processus non seulement son identifiant de processus mais également l'identifiant de son processus père qui est retourné par `getpid(2)`_. Lorsque le père se termine avant son fils, le processus fils est dit `orphelin` et le kernel modifie ses structures de données pour que le père de ce :term:`processus orphelin` soit le processus dont l'identifiant est ``1``. Ce processus est le processus `init(8)`_ qui est lancé au démarrage du système et n'est jamais arrêté. - -.. literalinclude:: /Threads/S8-src/fork-orphan.out - :encoding: utf-8 - :language: console - -A côté des processus orphelins dont nous venons de parler, un système Unix peut également héberger des :term:`processus zombie`. Un :term:`processus zombie` est un processus qui s'est terminé mais dont la valeur de retour n'a pas encore été récupérée par son père. Dans ce cas, le :term:`kernel` libère l'ensemble des ressources associées au processus fils et ne conserve de ce processus qu'une petite structure de données contenant notamment son identifiant, l'identifiant de son processus père et sa valeur de retour. En pratique, il est préférable d'éviter les processus zombie car ils consomment quand même un peu de ressources. - -.. index:: execve - -Exécution d'un programme ------------------------- - -`fork(2)`_ et `waitpid(2)`_ permettent respectivement de créer et de terminer des processus. Pour comprendre la façon dont les programmes sont exécutés, il nous reste à expliquer le fonctionnement de l'appel système `execve(2)`_. Cet appel système permet l'exécution d'un programme. Lors de son exécution, l'image en mémoire du processus qui effectue `execve(2)`_ est remplacée par l'image de l'exécutable passé en argument à `execve(2)`_ et son exécution démarre à sa fonction ``main``. - -.. code-block:: c - - #include <unistd.h> - - int execve(const char *path, char *const argv[], char *const envp[]); - -`execve(2)`_ prend trois arguments. Le premier est le nom complet du fichier exécutable qui doit être lancé. Le second est un pointeur vers un tableau de chaines de caractères contenant les arguments à passer à l'exécutable. Le troisième est un pointeur vers l'environnement qui sera nécessaire à l'exécution du programme. Comme `execve(2)`_ remplace l'image mémoire du programme en cours d'exécution, il ne retourne une valeur de retour que si l'appel système échoue. Cela peut être le cas si son premier argument n'est pas un fichier exécutable accessible par exemple. - -`execve(2)`_ s'utilise souvent juste après l'exécution de `fork(2)`_, mais il est aussi possible de l'utiliser directement dans un programme. Dans ce cas, le programme qui exécute avec succès `execve(2)`_ disparaît et est remplacé par le programme appelé. Le programme ci-dessous illustre une utilisation simple de `execve(2)`_. - -.. literalinclude:: /Threads/S8-src/execve.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - -Lors de son exécution, ce programme affiche sur sa sortie standard les lignes suivantes : - -.. literalinclude:: /Threads/S8-src/execve.out - :encoding: utf-8 - :language: console - -Il y a quelques points importants à noter concernant l'utilisation de `execve(2)`_. Tout d'abord, `execve(2)`_ remplace l'entièreté de l'image mémoire du processus qui exécute cet appel système, y compris les arguments, les variables d'environnement. Par contre, le :term:`kernel` conserve certaines informations qu'il maintenait pour le processus. C'est le cas notamment de l'identifiant du processus et de l'identifiant du processus père. Si le processus qui a effectué `execve(2)`_ avait lancé des threads, ceux-ci seraient immédiatement supprimés puisque l'image du processus en cours d'exécution est remplacé lors de l'exécution de `execve(2)`_. Les flux standard (:term:`stdin`, :term:`stdout` et :term:`stderr`) sont utilisables par le programme exécuté via `execve(2)`_. Il faut cependant noter que lors de l'appel à `execve(2)`_, les données qui se trouveraient éventuellement dans le buffer de la librairie :term:`stdio` ne sont pas automatiquement envoyées vers leurs flux respectifs. Cela pourrait paraître étonnant puisque lorsqu'un processus se termine avec `exit(3)`_, `exit(3)`_ vide les buffers de :term:`stdio` avant d'appeler `exit(2)`_. `execve(2)`_ est un appel système qui est exécuté par le kernel. Celui-ci ne peut pas savoir si il y a des données en attente d'écriture dans :term:`stdio`. Il ne peut donc pas automatiquement vider les buffers maintenus par la librairie :term:`stdio`. Si des données ont été écrites avec `printf(3)`_ avant l'exécution de `execve(2)`_, il est préférable de forcer leur écriture via `fflush(3)`_ avant d'appeler `execve(2)`_. - -L'appel système `execve(2)`_ est très souvent exécuté dans un shell tel que `bash(1)`_. Lorsqu'un shell lance un programme externe, il doit d'abord utiliser `fork(2)`_ pour créer une copie de lui-même. Ensuite, le processus père se met en attente via `waitpid(2)`_ de la valeur de retour du processus fils créé. Le processus fils quant à lui utilise `execve(2)`_ pour exécuter le programme demandé. - -La programme ci-dessous est un exemple un peu plus complexe de l'utilisation de `fork(2)`_, `execve(2)`_ et `waitpid(2)`_. Ce programme prend comme argument une liste d'exécutables et il essaye de les exécuter l'un à la suite de l'autre. Pour cela, il parcourt ses arguments et essaye pour chaque argument de créer un processus fils et d'y exécuter le programme correspondant. Si le programme a pu être exécuté, sa valeur de retour est récupérée par le processus père. Si l'appel à `execve(2)`_ a échoué, le processus fils se termine avec ``127`` comme valeur de retour. Comme celle-ci est stockée sur 8 bits, c'est la plus grande valeur de retour positive qu'il est possible de retourner depuis un processus fils. Cette valeur indique au processus père que le fils n'a pas réussi à exécuter `execve(2)`_. - -.. literalinclude:: /Threads/S8-src/fork-manyexec.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - - -Lors de son exécution, ce programme affiche sur sa sortie standard les lignes suivantes : - -.. literalinclude:: /Threads/S8-src/fork-manyexec.out - :encoding: utf-8 - :language: console - -En pratique, il existe plusieurs fonctions de la librairie standard qui apportent de petites variations à `execve(2)`_. Il s'agit de `execl(3)`_, `execlp(3)`_, `execle(3)`_, `execv(3posix)`_ et `execv(3)`_. Ces fonctions utilisent toutes l'appel système `execve(2)`_. Elles permettent de spécifier de différentes façons le programme à exécuter ou les variables d'environnement. Enfin, la fonction `system(3)`_ de la librairie permet d'exécuter une commande du shell directement depuis un programme. - -Outre les exécutables compilés, Unix et Linux supportent également l'exécution de programmes interprétés. Contrairement aux programmes compilés que nous avons manipulé jusque maintenant, un programme interprété est un programme écrit dans un langage qui doit être utilisé via un :term:`interpréteur`. Un :term:`interpréteur` est un programme qui lit des commandes sous la forme de texte et exécute directement les instructions correspondant à ces commandes. Unix supporte de nombreux interpréteurs et comme nous allons le voir il est très facile de rajouter de nouveaux interpréteurs de commande. L'interpréteur le plus connu est `bash(1)`_ et ses nombreuses variantes. En voici quelques autres : - - - `awk(1)`_ est un langage de programmation interprété qui permet de facilement manipuler des textes - - `perl(1)`_ est un langage de programmation complet qui a été initialement développé pour la manipulation de textes, mais est utilisé dans de nombreuses autres applications - - `python(1)`_ est un langage de programmation complet - -Pour comprendre la façon dont Unix interagit avec les interpréteurs de commande, il est bon de voir en détails comment `execve(2)`_ reconnaît qu'un fichier contient un programme qui peut être exécuté. Tout d'abord, le système de fichiers contient pour chaque fichier des métadonnées qui fournissent de l'information sur le possesseur du fichier, sa date de création, ... Une de ces métadonnées est un bit [#fchmod]_ qui indique si le fichier est exécutable ou non. Ce bit peut être manipulé en utilisant la commande `chmod(1)`_. Lorsqu'un programme est compilé avec `gcc(1)`_, celui-ci utilise `chmod(1)`_ pour marquer le programme comme étant exécutable. - -.. code-block:: console - - $ ls -l a.out - -rwxr-xr-x 1 obo stafinfo 8178 Mar 16 13:42 a.out - $ chmod -x a.out - $ ./a.out - -bash: ./a.out: Permission denied - $ chmod +x a.out - $ ./a.out - exécution de a.out - $ ls -l a.out - -rwxr-xr-x 1 obo stafinfo 8178 Mar 16 13:42 a.out - - -Lorsqu'`execve(2)`_ est appelé, il vérifie d'abord ce bit de permission. Si il n'indique pas que le programme est exécutable, `execve(2)`_ retourne une erreur. Ensuite, `execve(2)`_ ouvre le fichier dont le nom a été passé comme premier argument. Par convention, le début du fichier contient une séquence d'octets ou de caractères qui indiquent le type de fichier dont il s'agit. La commande `file(1)`_ permet de tester le type d'un fichier inconnu. - -.. code-block:: console - - $ file fork-execve.c - fork-execve.c: UTF-8 C program text - $ file script.sh - script.sh: Bourne-Again shell script text executable - $ file a.out - a.out: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped - -Pour les exécutables, deux cas de figure sont possibles: - - 1. le fichier contient un programme compilé et directement exécutable. Sur les systèmes Linux actuels, ce fichier sera au format `elf(5)`_. Il débute par une entête qui contient une chaîne de caractères utilisée comme marqueur ou chaîne magique. L'entête fournit de l'information sur le type d'exécutable et sa structure. Voici à titre d'illustration le contenu de l'entête d'un programme compilé décortiqué par l'utilitaire `readelf(1)`_ : - - .. code-block:: console - - $ readelf -h a.out - ELF Header: - Magic: 7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00 - Class: ELF64 - Data: 2's complement, little endian - Version: 1 (current) - OS/ABI: UNIX - Linux - ABI Version: 0 - Type: EXEC (Executable file) - Machine: Advanced Micro Devices X86-64 - Version: 0x1 - Entry point address: 0x4006e0 - Start of program headers: 64 (bytes into file) - Start of section headers: 3712 (bytes into file) - Flags: 0x0 - Size of this header: 64 (bytes) - Size of program headers: 56 (bytes) - Number of program headers: 8 - Size of section headers: 64 (bytes) - Number of section headers: 30 - Section header string table index: 27 - - 2. Le fichier contient un programme en langage interprété. Dans ce cas, la première ligne débute par ``#!`` suivi du nom complet de l'interpréteur à utiliser et de ses paramètres éventuels. Le programme interprété commence sur la deuxième ligne. A titre d'exemple, voici un petit script `bash(1)`_ qui permet de tester si un fichier est interprétable ou non en testant la valeur des deux premiers caractères du fichier et ses métadonnées. - - .. literalinclude:: /Threads/S8-src/script.sh - :encoding: utf-8 - :language: bash - - -Sous Unix et Linux, n'importe quel programmeur peut définir son propre interpréteur. Il suffit qu'il s'agisse d'un exécutable compilé et que le nom de cet interpréteur soit présent dans la première ligne du fichier à interpréter. Lors de l'exécution d'un programme utilisant cet interpréteur, celui-ci recevra le contenu du fichier et pourra l'interpréter. Ainsi, par exemple le programme interprété ci-dessous est tout à fait valide. - -.. literalinclude:: /Threads/S8-src/test.tail - :encoding: utf-8 - :language: bash - -Lors de son exécution via `execve(2)`_, l'interpréteur `tail(1)`_ va être chargé avec comme arguments ``-n +1`` et il affichera sur :term:`stdout` la ligne ``SINF1252``. - -Cette facilité d'ajouter de nouveaux interpréteurs de commande est une des forces des systèmes d'exploitation de la famille Unix. - -.. index:: table des processus - -Table des processus -------------------- - -Un système d'exploitation tel que Linux maintient certaines informations concernant chaque processus dans sa :term:`table des processus`. Une description complète du contenu de cette table des processus sort du cadre de ce chapitre. Par contre, il est intéressant de noter que sous Linux il existe de nombreux utilitaires qui permettent de consulter le contenu de la table des processus et notamment : - - - `ps(1)`_ qui est l'utilitaire de base pour accéder à la table de processus et lister les processus en cours d'exécution - - `top(1)`_ qui affiche de façon interactive les processus qui consomment actuellement du temps CPU, de la mémoire, ... - - `pstree(1)`_ qui affiche l'arbre des processus avec les relations père-fils - -Tous ces utilitaires utilisent les informations contenues dans le répertoire ``/proc``. Il s'agit d'un répertoire spécial qui contient de l'information à propos du système d'exploitation y compris la table de processus. Son contenu est détaillé dans la page de manuel qui lui est consacrée : `proc(5)`_. - -A titre d'illustration, considérons le shell d'un utilisateur en cours. Les informations maintenues dans la table des processus pour ce processus sont accessibles depuis ``/proc/pid`` où ``pid`` est l'identifiant du processus en cours d'exécution. Linux stocke de très nombreuses informations sur chaque processus. Celles-ci sont structurées dans des fichiers et des répertoires : - -.. code-block:: console - - $ ls -l /proc/18557 - total 0 - dr-xr-xr-x 2 obo stafinfo 0 Mar 18 16:37 attr - -r-------- 1 obo stafinfo 0 Mar 18 16:37 auxv - -r--r--r-- 1 obo stafinfo 0 Mar 18 16:37 cgroup - --w------- 1 obo stafinfo 0 Mar 18 16:37 clear_refs - -r--r--r-- 1 obo stafinfo 0 Mar 18 14:56 cmdline - -rw-r--r-- 1 obo stafinfo 0 Mar 18 16:37 coredump_filter - -r--r--r-- 1 obo stafinfo 0 Mar 18 16:37 cpuset - lrwxrwxrwx 1 obo stafinfo 0 Mar 18 16:37 cwd -> /etinfo/users2/obo/sinf1252/SINF1252/ - -r-------- 1 obo stafinfo 0 Mar 18 16:37 environ - lrwxrwxrwx 1 obo stafinfo 0 Mar 18 16:37 exe -> /bin/bash - dr-x------ 2 obo stafinfo 0 Mar 18 14:56 fd - dr-x------ 2 obo stafinfo 0 Mar 18 16:37 fdinfo - -r--r--r-- 1 obo stafinfo 0 Mar 18 16:37 io - -rw------- 1 obo stafinfo 0 Mar 18 16:37 limits - -rw-r--r-- 1 obo stafinfo 0 Mar 18 16:37 loginuid - -r--r--r-- 1 obo stafinfo 0 Mar 18 16:37 maps - -rw------- 1 obo stafinfo 0 Mar 18 16:37 mem - -r--r--r-- 1 obo stafinfo 0 Mar 18 16:37 mountinfo - -r--r--r-- 1 obo stafinfo 0 Mar 18 16:37 mounts - -r-------- 1 obo stafinfo 0 Mar 18 16:37 mountstats - dr-xr-xr-x 6 obo stafinfo 0 Mar 18 16:37 net - -r--r--r-- 1 obo stafinfo 0 Mar 18 16:37 numa_maps - -rw-r--r-- 1 obo stafinfo 0 Mar 18 16:37 oom_adj - -r--r--r-- 1 obo stafinfo 0 Mar 18 16:37 oom_score - -r-------- 1 obo stafinfo 0 Mar 18 16:37 pagemap - -r-------- 1 obo stafinfo 0 Mar 18 16:37 personality - lrwxrwxrwx 1 obo stafinfo 0 Mar 18 16:37 root -> / - -rw-r--r-- 1 obo stafinfo 0 Mar 18 16:37 sched - -r--r--r-- 1 obo stafinfo 0 Mar 18 16:37 schedstat - -r--r--r-- 1 obo stafinfo 0 Mar 18 16:37 sessionid - -r--r--r-- 1 obo stafinfo 0 Mar 18 16:37 smaps - -r-------- 1 obo stafinfo 0 Mar 18 16:37 stack - -r--r--r-- 1 obo stafinfo 0 Mar 18 14:56 stat - -r--r--r-- 1 obo stafinfo 0 Mar 18 16:37 statm - -r--r--r-- 1 obo stafinfo 0 Mar 18 14:56 status - -r-------- 1 obo stafinfo 0 Mar 18 16:37 syscall - dr-xr-xr-x 3 obo stafinfo 0 Mar 18 15:59 task - -r--r--r-- 1 obo stafinfo 0 Mar 18 16:37 wchan - -Certaines des entrées dans ``/proc`` sont des fichiers, d'autres sont des répertoires. A titre d'exemple, voici quelques unes des entrées utiles à ce stade de notre exploration de Linux. - - - ``cmdline`` est un fichier texte contenant la ligne de commande utilisée pour lancer le processus - - ``environ`` est un fichier texte contenant les variables d'environnement passées au processus - - .. code-block:: console - - $ (cat /proc/18557/environ; echo) | tr '\000' '\n' - USER=obo - LOGNAME=obo - HOME=/etinfo/users2/obo - PATH=/usr/local/bin:/bin:/usr/bin - MAIL=/var/mail/obo - SHELL=/bin/bash - - - ``status`` est une indication sur l'état actuel du processus. Les premières lignes indiquent dans quel état le processus se trouve ainsi que son identifiant, l'identifiant de son père, ... - - .. code-block:: console - - $ cat /proc/$$/status | head -5 - Name: bash - State: S (sleeping) - Tgid: 18557 - Pid: 18557 - PPid: 18556 - - - ``limits`` est un fichier texte contenant les limites actuelles imposées par le système sur le processus. Ces limites peuvent être modifiées en utilisant `ulimit(1)` à l'intérieur de `bash(1)`_ ou via les appels systèmes `getrlimit(2)`_/`setrlimit(2)`_. - - .. code-block:: console - - $ cat /proc/18557/limits - Limit Soft Limit Hard Limit Units - Max cpu time unlimited unlimited seconds - Max file size unlimited unlimited bytes - Max data size unlimited unlimited bytes - Max stack size 10485760 unlimited bytes - Max core file size 0 unlimited bytes - Max resident set unlimited unlimited bytes - Max processes 1024 24064 processes - Max open files 1024 1024 files - Max locked memory 65536 65536 bytes - Max address space unlimited unlimited bytes - Max file locks unlimited unlimited locks - Max pending signals 24064 24064 signals - Max msgqueue size 819200 819200 bytes - Max nice priority 0 0 - Max realtime priority 0 0 - Max realtime timeout unlimited unlimited us - - - ``task`` est un répertoire qui contient pour chaque thread lancé par le processus un sous-répertoire avec toutes les informations qui sont relatives à ce thread. - -Nous aurons l'occasion de présenter ultérieurement d'autres éléments utiles se trouvant dans ``/proc``. Une description plus détaillée est disponible dans la page de manuel `proc(5)`_ et des livres de référence tels que [Kerrisk2010]_. - - - -.. rubric:: Footnotes - -.. [#fdynamic] Dans certains cas, on parle également de librairies dynamiques car ces librairies sont chargées dynamiquement à l'exécution du programme. - -.. [#fpath] La variable d'environnement ``PATH`` contient la liste des répertoires que le shell parcoure afin de localiser un exécutable à lancer lorsque l'utilisateur ne fournit par le chemin complet de l'exécutable à lancer. - -.. [#fsyscall] En pratique, il correspond une fonction de la librairie à chaque appel système. Cette fonction a le même nom que l'appel système et les mêmes arguments et fait appel à `syscall(2)`_ pour l'exécution de l'appel système. - -.. [#flib] Par défaut, `gcc(1)`_ cherche après les librairies spécifiées dans les répertoires de librairies standards, mais aussi dans les répertoires listés dans la variable d'environnement ``LD_LIBRARY_PATH``. Il est également possible de spécifier des répertoires supplémentaires contenant les librairies avec l'argument ``-L`` de `gcc(1)`_. - -.. [#fthread] Si le processus a été découpé en threads, le processus peut aussi se terminer lorsque son dernier thread se termine en exécutant ``return(...)`` dans sa fonction de démarrage ou par un appel explicite à `pthread_exit(3)`_. - -.. [#fwaitpid] Si le processus dont l'identifiant est passé comme argument s'est déjà terminé, alors `waitpid(2)`_ retourne en indiquant une erreur. - -.. [#fchmod] En pratique, il y a trois bits qui jouent ce rôle en fonction du possesseur du fichier et de l'utilisateur qui souhaite l'exécuter. Nous décrirons ces bits en détails dans un prochain chapitre. - - diff --git a/Theorie/Threads/threads.rst b/Theorie/Threads/threads.rst deleted file mode 100644 index 044def23dc7f0af9cdd2e4f4eb3708d30071633b..0000000000000000000000000000000000000000 --- a/Theorie/Threads/threads.rst +++ /dev/null @@ -1,226 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. _threads: - -Utilisation de plusieurs threads -================================ - -Les performances des microprocesseurs se sont continuellement améliorées depuis les années 1960s. Cette amélioration a été possible grâce aux progrès constants de la micro-électronique qui a permis d'assembler des microprocesseurs contenant de plus en plus de transistors sur une surface de plus en plus réduite. La figure [#ftransistors]_ ci-dessous illustre bien cette évolution puisqu'elle représente le nombre de transistors par microprocesseur en fonction du temps. - -.. spelling:: - - Moore - intel - - -.. figure:: /Threads/figures/534px-Transistor_Count_and_Moore's_Law_-_2011.png - :align: center - - Evolution du nombre de transistors par microprocesseur - - -Cette évolution avait été prédite par Gordon Moore dans les années 1960s [Stokes2008]_. Il a formulé en 1965 une hypothèse qui prédisait que le nombre de composants par puce continuerait à doubler tous les douze mois pour la prochaine décennie. Cette prédiction s'est avérée tout à fait réaliste. Elle est maintenant connue sous le nom de :term:`Loi de Moore` et est fréquemment utilisée pour expliquer les améliorations de performance des ordinateurs. - -Le fonctionnement d'un microprocesseur est régulé par une horloge. Celle-ci rythme la plupart des opérations du processeur et notamment le chargement des instructions depuis la mémoire. Pendant de nombreuses années, les performances des microprocesseurs ont fortement dépendu de leur vitesse d'horloge. Les premiers microprocesseurs avaient des fréquences d'horloge de quelques centaines de :term:`kHz`. A titre d'exemple, le processeur intel 4004 avait une horloge à 740 kHz en 1971. Aujourd'hui, les processeurs rapides dépassent la fréquence de 3 :term:`GHz`. La figure ci-dessous présente l'évolution de la fréquence d'horloge des microprocesseurs depuis les années 1970s [#fperf]_. On remarque une évolution rapide jusqu'aux environs du milieu de la dernière décennie. La barrière des 10 MHz a été franchie à la fin des années 1970s. Les 100 :term:`MHz` ont étés atteints en 1994 et le GHz aux environs de l'an 2000. - -.. figure:: /Threads/figures/figures-001-c.png - :align: center - - Evolution de la vitesse d'horloge des microprocesseurs - -Pendant près de quarante ans, l'évolution technologique a permis une amélioration continue des performances des microprocesseurs. Cette amélioration a directement profité aux applications informatiques car elles ont pu s'exécuter plus rapidement au fur et à mesure que la vitesse d'horloge des microprocesseurs augmentait. - -Malheureusement, vers 2005 cette croissance continue s'est arrêtée. La barrière des 3 GHz s'est avérée être une barrière très difficile à franchir d'un point de vue technologique. Aujourd'hui, les fabricants de microprocesseurs n'envisagent plus de chercher à continuer à augmenter les fréquences d'horloge des microprocesseurs. - -Si pendant longtemps la fréquence d'horloge d'un microprocesseur a été une bonne heuristique pour prédire les performances du microprocesseur, ce n'est pas un indicateur parfait de performance. Certains processeurs exécutent une instruction durant chaque cycle d'horloge. D'autres processeurs prennent quelques cycles d'horloge pour exécuter chaque instruction et enfin certains processeurs sont capables d'exécuter plusieurs instructions durant chaque cycle d'horloge. - -.. spelling:: - - d'Instructions - -Une autre façon de mesurer les performances d'un microprocesseur est de comptabiliser le nombre d'instructions qu'il exécute par seconde. On parle en général de Millions d'Instructions par Seconde (ou :term:`MIPS`). Si les premiers microprocesseurs effectuaient moins de 100.000 instructions par seconde, la barrière du MIPS a été franchie en 1979. Mesurées en MIPS, les performances des microprocesseurs ont continué à augmenter durant les dernières années malgré la barrière des 3 GHz comme le montre la figure ci-dessous. - - -.. figure:: /Threads/figures/figures-002-c.png - :align: center - - Evolution des performances des microprocesseurs en MIPS - -.. spelling:: - - Evaluation - benchmark - benchmarks - -.. note:: Evaluation des performances de systèmes informatiques - - La fréquence d'horloge d'un processeur et le nombre d'instructions qu'il est capable d'exécuter chaque seconde ne sont que quelques uns des paramètres qui influencent les performances d'un système informatique qui intègre ce processeur. Les performances globales d'un système informatique dépendent de nombreux autres facteurs comme la capacité de mémoire et ses performances, la vitesse des bus entre les différents composants, les performances des dispositifs de stockage ou des cartes réseaux. Les performances d'un système dépendront aussi fortement du type d'application utilisé. Un serveur web, un serveur de calcul scientifique et un serveur de bases de données n'auront pas les mêmes contraintes en termes de performance. L'évaluation complète des performances d'un système informatique se fait généralement en utilisant des benchmarks. Un :term:`benchmark` est un ensemble de logiciels qui reproduisent le comportement de certaines classes d'applications de façon à pouvoir tester les performances de systèmes informatiques de façon reproductible. Différents organismes publient de tels benchmarks. Le plus connu est probablement `Standard Performance Evaluation Corporation <http://www.spec.org>`_ qui publie des benchmarks et des résultats de benchmarks pour différents types de systèmes informatiques et d'applications. - - -Cette progression continue des performances en MIPS a été possible grâce à l'introduction de processeurs qui sont capables d'exécuter plusieurs threads d'exécution simultanément. On parle alors de processeur :term:`multi-coeurs` ou :term:`multi-threadé`. - - - - -La notion de thread d'exécution est très importante dans un système informatique. Elle permet non seulement de comprendre comme un ordinateur équipé d'un seul microprocesseur peut exécuter plusieurs programmes simultanément, mais aussi comment des programmes peuvent profiter des nouveaux processeurs capables d'exécuter plusieurs threads simultanément. Pour comprendre cette notion, il est intéressant de revenir à nouveau sur l'exécution d'une fonction en langage assembleur. Considérons la fonction ``f`` : - - .. code-block:: c - - int f(int a, int b ) { - int m=0; - int c=0; - while(c<b) { - m+=a; - c=c+1; - } - return m; - } - -En assembleur, cette fonction se traduit en : - - -.. code-block:: nasm - - f: - subl $16, %esp - movl 24(%esp), %eax - movl 20(%esp), %ecx - movl %ecx, 12(%esp) - movl %eax, 8(%esp) - movl $0, 4(%esp) - movl $0, (%esp) - .LBB0_1: - movl (%esp), %eax - cmpl 8(%esp), %eax - jge .LBB0_3 - - movl 12(%esp), %eax - movl 4(%esp), %ecx - addl %eax, %ecx - movl %ecx, 4(%esp) - movl (%esp), %eax - addl $1, %eax - movl %eax, (%esp) - jmp .LBB0_1 - .LBB0_3: - movl 4(%esp), %eax - addl $16, %esp - ret - - -Pour qu'un processeur puisse exécuter cette séquence d'instructions, il faut non seulement qu'il implémente chacune de ces instructions, mais également qu'il puisse accéder : - - - à la mémoire contenant les instructions à exécuter - - à la mémoire contenant les données manipulées par cette séquence d'instruction. Pour rappel, cette mémoire est divisée en plusieurs parties : - - - la zone contenant les variables globales - - le tas - - la pile - - - aux registres et plus particulièrement, il doit accéder : - - - aux registres de données pour stocker les résultats de chacune des instructions - - au registre ``%esp`` directement ou indirectement via les instructions ``push`` et ``pop`` qui permettent de manipuler la pile - - au registre ``%eip`` qui contient l'adresse de l'instruction en cours d'exécution - - au registre ``eflags`` qui contient l'ensemble des drapeaux - -.. spelling:: - - multithreadé - -Un processeur `multithreadé` a la capacité d'exécuter plusieurs programmes simultanément. En pratique, ce processeur disposera de plusieurs copies des registres. Chacun de ces blocs de registres pourra être utilisé pour exécuter ces programmes simultanément à raison d'un thread d'exécution par bloc de registres. Chaque thread d'exécution va correspondre à une séquence différente d'instructions qui va modifier son propre bloc de registres. C'est grâce à cette capacité d'exécuter plusieurs threads d'exécution simultanément que les performances en :term:`MIPS` des microprocesseurs ont pu continuer à croître alors que leur fréquence d'horloge stagnait. - -Cette capacité d'exécuter plusieurs threads d'exécution simultanément n'est pas limitée à un thread d'exécution par programme. Sachant qu'un thread d'exécution n'est finalement qu'une séquence d'instructions qui utilisent un bloc de registres, il est tout à fait possible à plusieurs séquences d'exécution appartenant à un même programme de s'exécuter simultanément. Si on revient à la fonction assembleur ci-dessus, il est tout à fait possible que deux invocations de cette fonction s'exécutent simultanément sur un microprocesseur. Pour démarrer une telle instance, il suffit de pouvoir initialiser le bloc de registres nécessaire à la nouvelle instance et ensuite de démarrer l'exécution à la première instruction de la fonction. En pratique, cela nécessite la coopération du système d'exploitation. Différents mécanismes ont été proposés pour permettre à un programme de lancer différents threads d'exécution. Aujourd'hui, le plus courant est connu sous le nom de threads POSIX. C'est celui que nous allons étudier en détail, mais il en existe d'autres. - -.. note:: D'autres types de threads - - A côté des threads POSIX, il existe d'autres types de threads. [Gove2011]_ présente comment implémenter des threads sur différents systèmes d'exploitation. Sous Linux, NTPL [DrepperMolnar2005]_ et LinuxThreads [Leroy]_ sont deux anciennes implémentations des threads POSIX. GNU PTH [GNUPTH]_ est une librairie qui implémente les threads sans interaction directe avec le système d'exploitation. Cela permet à la librairie d'être portable sur de nombreux systèmes d'exploitation. Malheureusement, tous les threads GNU PTH d'un programme doivent s'exécuter sur le même processeur. - - - -Les threads POSIX ------------------ - -Les threads POSIX sont supportés par la plupart des variantes de Unix. Ils sont souvent implémentés à l'intérieur d'une librairie. Sous Linux, il s'agit de la librairie `pthreads(7)`_ qui doit être explicitement compilée avec le paramètre ``-lpthread`` lorsque l'on utilise `gcc(1)`_. - -La librairie threads POSIX contient de nombreuses fonctions qui permettent de décomposer un programme en plusieurs threads d'exécution et de les gérer. Toutes ces fonctions nécessitent l'inclusion du fichier `pthread.h`_. La première fonction importante est `pthread_create(3)`_ qui permet de créer un nouveau thread d'exécution. Cette fonction prend quatre arguments et retourne une valeur entière. - -.. code-block:: c - - #include <pthread.h> - - int - pthread_create(pthread_t *restrict thread, - const pthread_attr_t *restrict attr, - void *(*start_routine)(void *), - void *restrict arg); - - -Le premier argument est un pointeur vers une structure de type ``pthread_t``. Cette structure est définie dans `pthread.h`_ et contient toutes les informations nécessaires à l'exécution d'un thread. Chaque thread doit disposer de sa structure de données de type ``pthread_t`` qui lui est propre. - -Le second argument permet de spécifier des attributs spécifiques au thread qui est créé. Ces attributs permettent de configurer différents paramètres associés à un thread. Nous y reviendrons ultérieurement. Si cet argument est mis à ``NULL``, la librairie ``pthreads`` utilisera les attributs par défaut qui sont en général largement suffisants. - -Le troisième argument contient l'adresse de la fonction par laquelle le nouveau thread va démarrer son exécution. Cette adresse est le point de départ de l'exécution du thread et peut être comparée à la fonction ``main`` qui est lancée par le système d'exploitation lorsqu'un programme est exécuté. Un thread doit toujours débuter son exécution par une fonction dont la signature est ``void * function(void *)``, c'est-à -dire une fonction qui prend comme argument un pointeur générique (de type ``void *``) et retourne un résultat du même type. - -Le quatrième argument est l'argument qui est passé à la fonction qui débute le thread qui vient d'être créé. Cet argument est un pointeur générique de type ``void *``, mais la fonction peut bien entendu le convertir dans un autre type. - -La fonction `pthread_create(3)`_ retourne un résultat entier. Une valeur de retour non-nulle indique une erreur et ``errno`` est mise à jour. - -Un thread s'exécute en général pendant une certaine période de temps puis il peut retourner un résultat au thread d'exécution principal. Un thread peut retourner son résultat (de type ``void *``) de deux façons au thread qui l'a lancé. Tout d'abord, un thread qui a démarré par la fonction ``f`` se termine lorsque cette fonction exécute ``return(...)``. L'autre façon de terminer un thread d'exécution est d'appeler explicitement la fonction `pthread_exit(3)`_. Celle-ci prend un argument de type ``void *`` et le retourne au thread qui l'avait lancé. - -Pour récupérer le résultat d'un thread d'exécution, le thread principal doit utiliser la fonction `pthread_join(3)`_. Celle-ci prend deux arguments et retourne un entier. - -.. code-block:: c - - #include <pthread.h> - - int - pthread_join(pthread_t thread, void **value_ptr); - - -Le premier argument de `pthread_join(3)`_ est la structure ``pthread_t`` correspondant au thread dont le résultat est attendu. Le second argument est un pointeur vers un pointeur générique (``void **``) qui après la terminaison du thread passé comme premier argument pointera vers la valeur de retour de ce thread. - -L'exemple ci-dessous illustre une utilisation simple des fonctions `pthread_create(3)`_, `pthread_join(3)`_ et `pthread_exit(3)`_. - -.. literalinclude:: /Threads/S5-src/pthread.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - -Dans ce programme, la fonction ``main`` lance deux threads. Le premier exécute la fonction ``thread_first`` et le second la fonction ``thread_second``. Ces deux fonctions incrémentent une variable globale et n'utilisent pas leur argument. ``thread_first`` se termine par ``return`` tandis que ``thread_second`` se termine par un appel à `pthread_exit(3)`_. Après avoir créé ses deux threads, la fonction ``main`` démarre une longue boucle puis appelle ``pthread_join`` pour attendre la fin des deux threads qu'elle avait lancé. - -Afin d'illustrer la possibilité de passer des arguments à un thread et d'en récupérer la valeur de retour, considérons l'exemple ci-dessous. - -.. literalinclude:: /Threads/S5-src/pthread-neg.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - -Ce programme lance 4 threads d'exécution en plus du thread principal. Chaque thread d'exécution exécute la fonction ``neg`` qui récupère un entier comme argument et retourne l'opposé de cet entier comme résultat. - -Lors d'un appel à `pthread_create(3)`_, il est important de se rappeler que cette fonction crée le thread d'exécution, mais que ce thread ne s'exécute pas nécessairement immédiatement. En effet, il est très possible que le système d'exploitation ne puisse pas activer directement le nouveau thread d'exécution, par exemple parce que l'ensemble des processeurs de la machine sont actuellement utilisés. Dans ce cas, le thread d'exécution est mis en veille par le système d'exploitation et il sera démarré plus tard. Sachant que le thread peut devoir démarrer plus tard, il est important de s'assurer que la fonction lancée par `pthread_create(3)`_ aura bien accès à son argument au moment où finalement elle démarrera. Dans l'exemple ci-dessous, cela se fait en passant comme quatrième argument l'adresse d'un entier casté en ``void *``. Cette valeur est copiée sur la pile de la fonction ``neg``. Celle-ci pourra accéder à cet entier via ce pointeur sans problème lorsqu'elle démarrera. - -.. note:: Un thread doit pouvoir accéder à son argument - - Lorsque l'on démarre un thread via la fonction `pthread_create(3)`_, il faut s'assurer que la fonction lancée pourra bien accéder à ses arguments. Ce n'est pas toujours le cas comme le montre l'exemple ci-dessous. Dans cet exemple, c'est l'adresse de la variable locale ``i`` qui est passée comme quatrième argument à la fonction `pthread_create(3)`_. Cette adresse sera copiée sur la pile de la fonction ``neg`` pour chacun des threads créés. Malheureusement, lorsque la fonction ``neg`` sera exécutée, elle trouvera sur sa pile l'adresse d'une variable qui risque fort d'avoir été modifiée après l'appel à `pthread_create(3)`_ ou pire risque d'avoir disparu car la boucle ``for`` s'est terminée. Il est très important de bien veiller à ce que le quatrième argument passé à `pthread_create(3)`_ existe toujours au moment de l'exécution effective de la fonction qui démarre le thread lancé. - - .. code-block:: c - - /// erroné ! - for(long i=0;i<NTHREADS;i++) { - err=pthread_create(&(threads[i]),NULL,&neg,(void *)&i); - if(err!=0) - error(err,"pthread_create"); - } - -Concernant `pthread_join(3)`_, le code ci-dessus illustre la récupération du résultat via un pointeur vers un entier. Comme la fonction ``neg`` retourne un résultat de type ``void *`` elle doit nécessairement retourner un pointeur qui peut être casté vers un pointeur de type ``void *``. C'est ce que la fonction ``neg`` dans l'exemple réalise. Elle alloue une zone mémoire permettant de stocker un entier et place dans cette zone mémoire la valeur de retour de la fonction. Ce pointeur est ensuite casté en un pointeur de type ``void *`` avant d'appeler ``return``. Il faut noter que l'appel à `pthread_join(3)`_ ne se termine que lorsque le thread spécifié comme premier argument se termine. Si ce thread ne se termine pas pour n'importe quelle raison, l'appel à `pthread_join(3)`_ ne se terminera pas non plus. - - -.. rubric:: Footnotes - -.. [#ftransistors] Source : http://en.wikipedia.org/wiki/File:Transistor_Count_and_Moore%27s_Law_-_2011.svg - -.. [#fperf] Plusieurs sites web recensent cette information, notamment http://www.intel.com/pressroom/kits/quickreffam.htm, http://en.wikipedia.org/wiki/List_of_Intel_microprocessors et http://en.wikipedia.org/wiki/Instructions_per_second - diff --git a/Theorie/Threads/threads2.rst b/Theorie/Threads/threads2.rst deleted file mode 100644 index c5538319b49347d91d99124369dd719b47f9a729..0000000000000000000000000000000000000000 --- a/Theorie/Threads/threads2.rst +++ /dev/null @@ -1,321 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -.. _comthreads: - -Communication entre threads -=========================== - -Lorsque un programme a été décomposé en plusieurs threads, ceux-ci ne sont en général pas complètement indépendants et ils doivent communiquer entre eux. Cette communication entre threads est un problème complexe comme nous allons le voir. Avant d'aborder ce problème, il est utile de revenir à l'organisation d'un processus et de ses threads en mémoire. La figure ci-dessous illustre schématiquement l'organisation de la mémoire après la création d'un thread POSIX. - - -.. figure:: /Threads/S6-fig/figures-001-c.png - :align: center - :scale: 80 - - Organisation de la mémoire après la création d'un thread POSIX - - -Le programme principal et le thread qu'il a créé partagent trois zones de la mémoire : le :term:`segment text` qui comprend l'ensemble des instructions qui composent le programme, le :term:`segment de données` qui comprend toutes les données statiques, initialisées ou non et enfin le :term:`heap`. Autant le programme principal que son thread peuvent accéder à n'importe quelle information se trouvant en mémoire dans ces zones. Par contre, le programme principal et le thread qu'il vient de créer ont chacun leur propre contexte et leur propre pile. - -La première façon pour un processus de communiquer avec un thread qu'il a lancé est d'utiliser les arguments de la fonction de démarrage du thread et la valeur retournée par le thread que le processus principal peut récupérer via l'appel à `pthread_join(3posix)`_. C'est un canal de communication très limité qui ne permet pas d'échange d'information pendant l'exécution du thread. - -Il est cependant assez facile pour un processus de partager de l'information avec ses threads ou même de partager de l'information entre plusieurs threads. En effet, tous les threads d'un processus ont accès aux mêmes variables globales et au même :term:`heap`. Il est donc tout à fait possible pour n'importe quel thread de modifier la valeur d'une variable globale. Deux threads qui réalisent un calcul peuvent donc stocker des résultats intermédiaires dans une variable globale ou un tableau global. Il en va de même pour l'utilisation d'une zone de mémoire allouée par `malloc(3)`_. Chaque thread qui dispose d'un pointeur vers cette zone mémoire peut en lire le contenu ou en modifier la valeur. - -Malheureusement, permettre à tous les threads de lire et d'écrire simultanément en mémoire peut être une source de problèmes. C'est une des difficultés majeures de l'utilisation de threads. Pour s'en convaincre, considérons l'exemple ci-dessous [#fexemple]_. - -.. code-block:: c - - long global=0; - int increment(int i) { - return i+1; - } - void *func(void * param) { - for(int j=0;j<1000000;j++) { - global=increment(global); - } - return(NULL); - } - - -Dans cet exemple, la variable ``global`` est incrémentée ``1000000`` de fois par la fonction ``func``. Après l'exécution de cette fonction, la variable ``global`` contient la valeur ``1000000``. Sur une machine multiprocesseurs, un programmeur pourrait vouloir en accélérer les performances en lançant plusieurs threads qui exécutent chacun la fonction ``func``. Cela pourrait se faire en utilisant par exemple la fonction ``main`` ci-dessous. - - -.. code-block:: c - - int main (int argc, char *argv[]) { - pthread_t thread[NTHREADS]; - int err; - for(int i=0;i<NTHREADS;i++) { - err=pthread_create(&(thread[i]),NULL,&func,NULL); - if(err!=0) - error(err,"pthread_create"); - } - /*...*/ - for(int i=NTHREADS-1;i>=0;i--) { - err=pthread_join(thread[i],NULL); - if(err!=0) - error(err,"pthread_join"); - } - printf("global: %ld\n",global); - return(EXIT_SUCCESS); - } - -Ce programme lance alors 4 threads d'exécution qui incrémentent chacun un million de fois la variable ``global``. Celle-ci étant initialisée à ``0``, la valeur affichée par `printf(3)`_ à la fin de l'exécution doit donc être ``4000000``. L'exécution du programme ne confirme malheureusement pas cette attente. - -.. code-block:: console - - $ for i in {1..5}; do ./pthread-test; done - global: 3408577 - global: 3175353 - global: 1994419 - global: 3051040 - global: 2118713 - - -Non seulement la valeur attendue (``4000000``) n'est pas atteinte, mais en plus la valeur change d'une exécution du programme à la suivante. C'est une illustration du problème majeur de la découpe d'un programme en threads. Pour bien comprendre le problème, il est utile d'analyser en détails les opérations effectuées par deux threads qui exécutent la ligne ``global=increment(global);``. - -La variable ``global`` est stockée dans une zone mémoire qui est accessibles aux deux threads. Appelons-les `T1` et `T2`. L'exécution de cette ligne par un thread nécessite l'exécution de plusieurs instructions en assembleur. Tout d'abord, il faut charger la valeur de la variable ``global`` depuis la mémoire vers un registre. Ensuite, il faut placer cette valeur sur la pile du thread puis appeler la fonction ``increment``. Cette fonction récupère son argument sur la pile du thread, la place dans un registre, incrémente le contenu du registre et sauvegarde le résultat dans le registre ``%eax``. Le résultat est retourné dans la fonction ``func`` et la variable globale peut enfin être mise à jour. - -Malheureusement les difficultés surviennent lorsque deux threads exécutent en même temps la ligne ``global=increment(global);``. Supposons qu'à cet instant, la valeur de la variable ``global`` est ``1252``. Le premier thread charge une copie de cette variable sur sa pile. Le second fait de même. Les deux threads ont donc chacun passé la valeur ``1252`` comme argument à la fonction ``increment``. Celle-ci s'exécute et retourne la valeur ``1253`` que chaque thread va récupérer dans ``%eax``. Chaque thread va ensuite transférer cette valeur dans la zone mémoire correspondant à la variable ``global``. Si les deux threads exécutent l'instruction assembleur correspondante exactement au même moment, les deux écritures en mémoire seront sérialisées par les processeurs sans que l'on ne puisse a priori déterminer quelle écriture se fera en premier [McKenney2005]_. Alors que les deux threads ont chacun exécuté un appel à la fonction ``increment``, la valeur de la variable n'a finalement été incrémentée qu'une seule fois même si cette valeur a été transférée deux fois en mémoire. Ce problème se reproduit fréquemment. C'est pour cette raison que la valeur de la variable ``global`` n'est pas modifiée comme attendu. - -.. note:: Contrôler la pile d'un thread POSIX - - La taille de la pile d'un thread POSIX est l'un des attributs qui peuvent être modifiés lors de l'appel à `pthread_create(3)`_ pour créer un nouveau thread. Cet attribut peut être fixé en utilisant la fonction `pthread_attr_setstackaddr(3posix)`_ comme illustré dans l'exemple ci-dessous [#fpthreadc]_ (où ``thread_first`` est la fonction qui sera appelée à la création du thread). En général, la valeur par défaut choisie par le système suffit, sauf lorsque le programmeur sait qu'un thread devra par exemple allouer un grand tableau auquel il sera le seul à avoir accès. Ce tableau sera alors alloué sur la pile qui devra être suffisamment grande pour le contenir. - - .. literalinclude:: /Threads/S6-src/pthread.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - - -Ce problème d'accès concurrent à une zone de mémoire par plusieurs threads est un problème majeur dans le développement de programmes découpés en threads, que ceux-ci s'exécutent sur des ordinateurs mono-processeurs ou multiprocesseurs. Dans la littérature, il est connu sous le nom de problème de la :term:`section critique` ou :term:`exclusion mutuelle`. La :term:`section critique` peut être définie comme étant une séquence d'instructions qui ne peuvent *jamais* être exécutées par plusieurs threads simultanément. Dans l'exemple ci-dessus, il s'agit de la ligne ``global=increment(global);``. Dans d'autres types de programmes, la section critique peut être beaucoup plus grande et comprendre par exemple la mise à jour d'une base de données. En pratique, on retrouvera une section critique chaque fois que deux threads peuvent modifier ou lire la valeur d'une même zone de la mémoire. - -Le fragment de code ci-dessus présente une autre illustration d'une section critique. Dans cet exemple, la fonction ``main`` (non présentée), créée deux threads. Le premier exécute la fonction ``inc`` qui incrémente la variable ``global``. Le second exécute la fonction ``is_even`` qui teste la valeur de cette variable et compte le nombre de fois qu'elle est paire. Après la terminaison des deux threads, le programme affiche le contenu des variables ``global`` et ``even``. - -.. literalinclude:: /Threads/S6-src/pthread-test-if.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - :end-before: ///BBB - -L'exécution de ces deux threads donne, sans surprise des résultats qui varient d'une exécution à l'autre. - -.. code-block:: console - - $ for i in {1..5}; do ./pthread-test-if; done - global: 1000000, even:905140 - global: 1000000, even:919756 - global: 1000000, even:893058 - global: 1000000, even:891266 - global: 1000000, even:895043 - -.. _coordthreads: - -Coordination entre threads -========================== - -L'utilisation de plusieurs threads dans un programme fonctionnant sur un seul ou plusieurs processeurs nécessite l'utilisation de mécanismes de coordination entre ces threads. Ces mécanismes ont comme objectif d'éviter que deux threads ne puissent modifier ou tester de façon non coordonnée la même zone de la mémoire. - - -.. spelling:: - - Dijkstra - -Exclusion mutuelle ------------------- - -Le premier problème important à résoudre lorsque l'on veut coordonner plusieurs threads d'exécution d'un même processus est celui de l':term:`exclusion mutuelle`. Ce problème a été initialement proposé par Dijkstra en 1965 [Dijkstra1965]_. Il peut être reformulé de la façon suivante pour un programme décomposé en threads. - -Considérons un programme décomposé en `N` threads d'exécution. Supposons également que chaque thread d'exécution est cyclique, c'est-à -dire qu'il exécute régulièrement le même ensemble d'instructions, sans que la durée de ce cycle ne soit fixée ni identique pour les `N` threads. Chacun de ces threads peut être décomposé en deux parties distinctes. La première est la partie non-critique. C'est un ensemble d'instructions qui peuvent être exécutées par le thread sans nécessiter la moindre coordination avec un autre thread. Plus précisément, tous les threads peuvent exécuter simultanément leur partie non-critique. La seconde partie du thread est appelée sa :term:`section critique`. Il s'agit d'un ensemble d'instructions qui ne peuvent être exécutées que par un seul et unique thread. Le problème de l':term:`exclusion mutuelle` est de trouver un algorithme qui permet de garantir qu'il n'y aura jamais deux threads qui simultanément exécuteront les instructions de leur section critique. - -Cela revient à dire qu'il n'y aura pas de violation de la section critique. Une telle violation pourrait avoir des conséquences catastrophiques sur l'exécution du programme. Cette propriété est une propriété de :term:`sûreté` (:term:`safety` en anglais). Dans un programme découpé en threads, une propriété de :term:`sûreté` est une propriété qui doit être vérifiée à tout instant de l'exécution du programme. - -En outre, une solution au problème de l':term:`exclusion mutuelle` doit satisfaire les contraintes suivantes [Dijkstra1965]_ : - - a. La solution doit considérer tous les threads de la même façon et ne peut faire aucune hypothèse sur la priorité relative des différents threads. - b. La solution ne peut faire aucune hypothèse sur la vitesse relative ou absolue d'exécution des différents threads. Elle doit rester valide quelle que soit la vitesse d'exécution non nulle de chaque thread. - c. La solution doit permettre à un thread de s'arrêter en dehors de sa section critique sans que cela n'invalide la contrainte d'exclusion mutuelle - d. Si un ou plusieurs threads souhaitent entamer leur section critique, aucun de ces threads ne doit pouvoir être empêché indéfiniment d'accéder à sa section critique. - -La troisième contrainte implique que la terminaison ou le crash d'un des threads ne doit pas avoir d'impact sur le fonctionnement du programme complet et le respect de la contrainte d'exclusion mutuelle pour la section critique. - -La quatrième contrainte est un peu plus subtile mais tout aussi importante. Toute solution au problème de l'exclusion mutuelle contient nécessairement un mécanisme qui permet de bloquer l'exécution d'un thread pendant qu'un autre exécute sa section critique. Il est important qu'un thread puisse accéder à sa section critique si il le souhaite. C'est un exemple de propriété de :term:`vivacité` (:term:`liveness` en anglais). Une propriété de :term:`vivacité` est une propriété qui ne peut pas être éternellement invalidée. Dans notre exemple, un thread ne pourra jamais être empêché d'accéder à sa section critique. - -.. spelling:: - - monoprocesseur - monoprocesseurs - - -Exclusion mutuelle sur monoprocesseurs -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Même si les threads sont très utiles dans des ordinateurs multiprocesseurs, ils ont été inventés et utilisés d'abord sur des processeurs capables d'exécuter un seul thread d'exécution à la fois. Sur un tel processeur, les threads d'exécution sont entrelacés plutôt que d'être exécutés réellement simultanément. Cet entrelacement est réalisé par le système d'exploitation. - -Les systèmes d'exploitation de la famille Unix permettent d'exécuter plusieurs programmes `en même temps` sur un ordinateur, même si il est équipé d'un processeur qui n'est capable que d'exécuter un thread à la fois. Cette fonctionnalité est souvent appelée le :term:`multitâche` (ou :term:`multitasking` en anglais). Cette exécution simultanée de plusieurs programmes n'est en pratique qu'une illusion puisque le processeur ne peut qu'exécuter qu'une séquence d'instructions à la fois. - -Pour donner cette illusion, un système d'exploitation multitâche tel que Unix exécute régulièrement des changements de contexte entre threads. Le :term:`contexte` d'un thread est composé de l'ensemble des contenus des registres qui sont nécessaires à son exécution (y compris le contenu des registres spéciaux tels que ``%esp``, ``%eip`` ou ``%eflags``). Ces registres définissent l'état du thread du point de vue du processeur. Pour passer de l'exécution du thread `T1` à l'exécution du thread `T2`, le système d'exploitation doit initier un :term:`changement de contexte`. Pour réaliser ce changement de contexte, le système d'exploitation initie le transfert du contenu des registres utilisés par le thread `T1` vers une zone mémoire lui appartenant. Il transfère ensuite depuis une autre zone mémoire lui appartenant le contexte du thread `T2`. Si ce changement de contexte est effectué fréquemment, il peut donner l'illusion à l'utilisateur que plusieurs threads ou programmes s'exécutent simultanément. - -Sur un système Unix, il y a deux types d'événements qui peuvent provoquer un changement de contexte. - - 1. Le hardware génère une :term:`interruption` - 2. Un thread exécute un :term:`appel système bloquant` - -Ces deux types d'événements sont fréquents et il est important de bien comprendre comment ils sont traités par le système d'exploitation. - -Une :term:`interruption` est un signal électronique qui est généré par un dispositif connecté au microprocesseur. De nombreux dispositifs d'entrées-sorties comme les cartes réseau ou les contrôleurs de disque peuvent générer une interruption lorsqu'une information a été lue ou reçue et doit être traitée par le processeur. En outre, chaque ordinateur dispose d'une horloge temps réel qui génère des interruptions à une fréquence déterminée par le système d'exploitation mais qui est généralement comprise entre quelques dizaines et quelques milliers de `Hz`. Ces interruptions nécessitent un traitement rapide de la part du système d'exploitation. Pour cela, le processeur vérifie, à la fin de l'exécution de `chaque` instruction si un signal d'interruption [#finterrupts]_ est présent. Si c'est le cas, le processeur sauvegarde en mémoire le contexte du thread en cours d'exécution et lance une routine de traitement d'interruption faisant partie du système d'exploitation. Cette routine analyse l'interruption présente et lance les fonctions du système d'exploitation nécessaires à son traitement. Dans le cas d'une lecture sur disque, par exemple, la routine de traitement d'interruption permettra d'aller chercher la donnée lue sur le contrôleur de disques. - -Le deuxième type d'événement est l'exécution d'un appel système bloquant. Un thread exécute un :term:`appel système` chaque fois qu'il doit interagir avec le système d'exploitation. Ces appels peuvent être exécutés directement ou via une fonction de la librairie [#fman2]_. Il existe deux types d'appels systèmes : les appels bloquants et les appels non-bloquants. Un appel système non-bloquant est un appel système que le système d'exploitation peut exécuter immédiatement. Cet appel retourne généralement une valeur qui fait partie du système d'exploitation lui-même. L'appel `gettimeofday(2)`_ qui permet de récupérer l'heure actuelle est un exemple d'appel non-bloquant. Un appel système bloquant est un appel système dont le résultat ne peut pas toujours être fourni immédiatement. Les lectures d'information en provenance de l'entrée standard (et donc généralement du clavier) sont un bon exemple simple d'appel système bloquant. Considérons un thread qui exécute la fonction de la librairie `getchar(3)`_ qui retourne un caractère lu sur :term:`stdin`. Cette fonction utilise l'appel système `read(2)`_ pour lire un caractère sur :term:`stdin`. Bien entendu, le système d'exploitation est obligé d'attendre que l'utilisateur presse une touche sur le clavier pour pouvoir fournir le résultat de cet appel système à l'utilisateur. Pendant tout le temps qui s'écoule entre l'exécution de `getchar(3)`_ et la pression d'une touche sur le clavier, le thread est bloqué par le système d'exploitation. Plus aucune instruction du thread n'est exécutée tant que la fonction `getchar(3)`_ ne s'est pas terminée et le contexte du thread est mis en attente dans une zone mémoire gérée par le système d'exploitation. Il sera redémarré automatiquement par le système d'exploitation lorsque la donnée attendue sera disponible. - -Ces interactions entre les threads et le système d'exploitation sont importantes. Pour bien les comprendre, il est utile de noter qu'un thread peut se trouver dans trois états différents du point de vue de son interaction avec le système d'exploitation. Ces trois états sont illustrés dans la figure ci-dessous. - -.. figure:: /Threads/S6-fig/figures-003-c.png - :align: center - :scale: 80 - - Etats d'un thread d'exécution - -Lorsqu'un thread est créé avec la fonction `pthread_create(3)`_, il est placé dans l'état `Ready`. Dans cet état, les instructions du thread ne s'exécutent sur aucun processeur mais il est prêt à être exécuté dès qu'un processeur se libérera. Le deuxième état pour un thread est l'état `Running`. Dans cet état, le thread est exécuté sur un des processeurs du système. Le dernier état est l'état `Blocked`. Un thread est dans l'état `Blocked` lorsqu'il a exécuté un appel système bloquant et que le système d'exploitation attend l'information permettant de retourner le résultat de l'appel système. Pendant ce temps, les instructions du thread ne s'exécutent sur aucun processeur. - -.. spelling:: - - ordonnanceur - scheduler - schedulers - l'ordonnanceur - l'implémentation - -Les transitions entre les différents états d'un thread sont gérées par le système d'exploitation. Lorsque plusieurs threads d'exécution sont simultanément actifs, le système d'exploitation doit arbitrer les demandes d'utilisation du CPU de chaque thread. Cet arbitrage est réalisé par l'ordonnanceur (ou :term:`scheduler` en anglais). Le :term:`scheduler` est un ensemble d'algorithmes qui sont utilisés par le système d'exploitation pour sélectionner le ou les threads qui peuvent utiliser un processeur à un moment donné. Il y a souvent plus de threads qui sont dans l'état `Ready` que de processeurs disponibles et le scheduler doit déterminer quels sont les threads à exécuter. - -Une description détaillée du fonctionnement d'un scheduler relève plutôt d'un cours sur les systèmes d'exploitation que d'un premier cours sur le langage C, mais il est important de connaître les principes de base de fonctionnement de quelques schedulers. - -Un premier scheduler simple est le :term:`round-robin`. Ce scheduler maintient en permanence une liste circulaire de l'ensemble des threads qui se trouvent dans l'état `Ready` et un pointeur vers l'élément courant de cette liste. Lorsqu'un processeur devient disponible, le scheduler sélectionne le thread référencé par ce pointeur. Ce thread passe dans l'état `Running`, est retiré de la liste et le pointeur est déplacé vers l'élément suivant dans la liste. Pour éviter qu'un thread ne puisse monopoliser éternellement un processeur, un scheduler :term:`round-robin` limite généralement le temps qu'un thread peut passer dans l'état `Running`. Lorsqu'un thread a utilisé un processeur pendant ce temps, le scheduler vérifie si il y a un thread en attente dans l'état `Ready`. Si c'est le cas, le scheduler force un changement de contexte, place le thread courant dans l'état `Ready` et le remet dans la liste circulaire tout en permettant à un nouveau thread de passer dans l'état `Running` pour s'exécuter. Lorsqu'un thread revient dans l'état `Ready`, soit parce qu'il vient d'être créé ou parce qu'il vient de quitter l'état `Blocked`, il est placé dans la liste afin de pouvoir être sélectionné par le scheduler. Un scheduler :term:`round-robin` est équitable. Avec un tel scheduler, si `N` threads sont actifs en permanence, chacun recevra :math:`\frac{1}{N}` de temps CPU disponible. - -Un second type de scheduler simple est le scheduler à priorités. Une priorité est associée à chaque thread. Lorsque le scheduler doit sélectionner un thread à exécuter, il commence d'abord par parcourir les threads ayant une haute priorité. En pratique, un scheduler à priorité maintiendra une liste circulaire pour chaque niveau de priorité. Lorsque le scheduler est appelé, il sélectionnera toujours le thread ayant la plus haute priorité et se trouvant dans l'état `Ready`. Si plusieurs threads ont le même niveau de priorité, un scheduler de type :term:`round-robin` peut être utilisé dans chaque niveau de priorité. Sous Unix, le scheduler utilise un scheduler à priorité avec un round-robin à chaque niveau de priorité, mais la priorité varie dynamiquement en fonction du temps de façon à favoriser les threads interactifs. - -Connaissant ces bases du fonctionnement des schedulers, il est utile d'analyser en détails quels sont les événements qui peuvent provoquer des transitions entre les états d'un thread. Certains de ces événements sont provoqués par le thread lui-même. C'est le cas de la transition entre l'état `Running` et l'état `Blocked`. Elle se produit lorsque le thread exécute un :term:`appel système bloquant`. Dans ce cas, un processeur redevient disponible et le scheduler peut sélectionner un autre thread pour s'exécuter sur ce processeur. La transition entre l'état `Blocked` et l'état `Running` dépend elle du système d'exploitation, directement lorsque le thread a été bloqué par le système d'exploitation ou indirectement lorsque le système d'exploitation attend une information venant d'un dispositif d'entrées-sorties. Les transitions entre les états `Running` et `Ready` dépendent elles entièrement du système d'exploitation. Elles se produisent lors de l'exécution du scheduler. Celui-ci est exécuté lorsque certaines interruptions surviennent. Il est exécuté à chaque interruption d'horloge. Cela permet de garantir l'exécution régulière du scheduler même si les seuls threads actifs exécutent une boucle infinie telle que ``while(true);``. A l'occasion de cette interruption, le scheduler mesure le temps d'exécution de chaque thread et si un thread a consommé beaucoup de temps CPU alors que d'autres threads sont dans l'état `Ready`, le scheduler forcera un changement de contexte pour permettre à un autre thread de s'exécuter. De la même façon, une interruption relative à un dispositif d'entrées-sorties peut faire transiter un thread de l'état `Blocked` à l'état `Ready`. Cette modification du nombre de threads dans l'état `Ready` peut forcer le scheduler à devoir effectuer un changement de contexte pour permettre à ce thread de poursuivre son exécution. Sous Unix, le scheduler utilise des niveaux de priorité qui varient en fonction des opérations d'entrées sorties effectuées. Cela a comme conséquence de favoriser les threads qui effectuent des opérations d'entrées sorties par rapport aux threads qui effectuent uniquement du calcul. - - -.. note:: Un thread peut demander de passer la main. - - Dans la plupart de nos exemples, les threads cherchent en permanence à exécuter des instructions. Ce n'est pas nécessairement le cas de tous les threads d'un programme. Par exemple, une application de calcul scientifique pourrait être découpée en `N+1` threads. Les `N` premiers threads réalisent le calcul tandis que le dernier calcule des statistiques. Ce dernier thread ne doit pas consommer de ressources et être en compétition pour le processeur avec les autres threads. La librairie thread POSIX contient la fonction `pthread_yield(3)`_ qui peut être utilisée par un thread pour indiquer explicitement qu'il peut être remplacé par un autre thread. Si un thread ne doit s'exécuter qu'à intervalles réguliers, il est préférable d'utiliser des appels à `sleep(3)`_ ou `usleep(3)`_. Ces fonctions de la librairie permettent de demander au système d'exploitation de bloquer le thread pendant un temps au moins égal à l'argument de la fonction. - -Sur une machine monoprocesseur, tous les threads s'exécutent sur le même processeur. Une violation de section critique peut se produire lorsque le scheduler décide de réaliser un changement de contexte alors qu'un thread se trouve dans sa section critique. Si la section critique d'un thread ne contient ni d'appel système bloquant ni d'appel à `pthread_yield(3)`_, ce changement de contexte ne pourra se produire que si une interruption survient. Une solution pour résoudre le problème de l'exclusion mutuelle sur un ordinateur monoprocesseur pourrait donc être la suivante : - -.. code-block:: c - - disable_interrupts(); - // début section critique - // ... - // fin section critique - enable_interrupts(); - -Cette solution est possible, mais elle souffre de plusieurs inconvénients majeurs. Tout d'abord, une désactivation des interruptions perturbe le fonctionnement du système puisque sans interruptions, la plupart des opérations d'entrées-sorties et l'horloge sont inutilisables. Une telle désactivation ne peut être que très courte, par exemple pour modifier une ou quelques variables en mémoire. Ensuite, la désactivation des interruptions, comme d'autres opérations relatives au fonctionnement du matériel, est une opération privilégiée sur un microprocesseur. Elle ne peut être réalisée que par le système d'exploitation. Il faudrait donc imaginer un appel système qui permettrait à un thread de demander au système d'exploitation de désactiver les interruptions. Si un tel appel système existait, le premier programme qui exécuterait ``disable_interrupts();`` sans le faire suivre de ``enable_interrupts();`` quelques instants après pourrait rendre la machine complètement inutilisable puisque sans interruption plus aucune opération d'entrée-sortie n'est possible et qu'en plus le scheduler ne peut plus être activé par l'interruption d'horloge. Pour toutes ces raisons, la désactivation des interruptions n'est pas un mécanisme utilisable par les threads pour résoudre le problème de l'exclusion mutuelle [#fdisable]_. - - -Coordination par Mutex -^^^^^^^^^^^^^^^^^^^^^^ - -Le premier mécanisme de coordination entre threads dans la librairie POSIX sont les :term:`mutex`. Un :term:`mutex` (abréviation de `mutual exclusion`) est une structure de données qui permet de contrôler l'accès à une ressource. Un :term:`mutex` qui contrôle une ressource peut se trouver dans deux états : - - - `libre` (ou `unlocked` en anglais). Cet état indique que la ressource est libre et peut être utilisée sans risquer de provoquer une violation d'exclusion mutuelle. - - `réservée` (ou `locked` en anglais). Cet état indique que la ressource associée est actuellement utilisée et qu'elle ne peut pas être utilisée par un autre thread. - -Un :term:`mutex` est toujours associé à une ressource. Cette ressource peut être une variable globale comme dans les exemples précédents, mais cela peut aussi être une structure de données plus complexe, une base de données, un fichier, ... Un mutex s'utilise par l'intermédiaire de deux fonctions de base. La fonction `lock` permet à un thread d'acquérir l'usage exclusif d'une ressource. Si la ressource est libre, elle est marquée comme réservée et le thread y accède directement. Si la ressource est occupée, le thread est bloqué par le système d'exploitation jusqu'à ce qu'elle ne devienne libre. A ce moment, le thread pourra poursuivre son exécution et utilisera la ressource avec la certitude qu'aucun autre thread ne pourra faire de même. Lorsque le thread a terminé d'utiliser la ressource associée au mutex, il appelle la fonction `unlock`. Cette fonction vérifie d'abord si un ou plusieurs autres threads sont en attente pour cette ressource (c'est-à -dire qu'ils ont appelé la fonction `lock` mais celle-ci n'a pas encore réussi). Si c'est le cas, un (et un seul) thread est choisi parmi les threads en attente et celui-ci accède à la ressource. Il est important de noter qu'un programme ne peut faire aucune hypothèse sur l'ordre dans lequel les threads qui sont en attente sur un :term:`mutex` pourront accéder à la ressource partagée. Le programme doit être conçu en faisant l'hypothèse que si plusieurs threads sont bloqués sur un appel à `lock` pour un mutex, le thread qui sera libéré est choisi aléatoirement. - -Sans entrer dans des détails qui relèvent du fonctionnement internes des systèmes d'exploitation, on peut schématiquement représenter un :term:`mutex` comme étant une structure de données qui contient deux informations : - - - la valeur actuelle du :term:`mutex` ( `locked` ou `unlocked`) - - une queue contenant l'ensemble des threads qui sont bloqués en attente du mutex - -Schématiquement, l'implémentation des fonctions ``lock`` et ``unlock`` peut être représentée par le code ci-dessous. - -.. code-block:: c - - lock(mutex m) { - if(m.val==unlocked) - { - m.val=locked; - } - else - { - // Place this thread in m.queue; - // This thread is blocked; - } - } - -Le fonction ``lock`` vérifie si le :term:`mutex` est libre. Dans ce cas, le :term:`mutex` est marqué comme réservé et la fonction ``lock`` réussi. Sinon, le thread qui a appelé la fonction ``lock`` est placé dans la queue associée au :term:`mutex` et passe dans l'état `Blocked` jusqu'à ce qu'un autre thread ne libère le mutex. - - -.. code-block:: c - - unlock(mutex m) { - if(m.queue is empty) - { - m.val=unlocked; - } - else - { - // Remove one thread(T) from m.queue; - // Mark Thread(T) as ready to run; - } - } - -La fonction ``unlock`` vérifie d'abord l'état de la queue associée au :term:`mutex`. Si la queue est vide, cela indique qu'aucun thread n'est en attente. Dans ce cas, la valeur du :term:`mutex` est mise à `unlocked` et la fonction se termine. Sinon, un des threads en attente dans la queue associée au :term:`mutex` est choisi et marqué comme prêt à s'exécuter. Cela indique implicitement que l'appel à ``lock`` fait par ce thread réussi et qu'il peut accéder à la ressource. - -Le code présenté ci-dessous n'est qu'une illustration du fonctionnement des opérations ``lock`` et ``unlock``. Pour que ces opérations fonctionnent correctement, il faut bien entendu que les modifications aux valeurs du :term:`mutex` et à la queue qui y est associée se fassent en garantissant qu'un seul thread exécute l'une de ces opérations sur un :term:`mutex` à un instant donné. En pratique, les implémentations de ``lock`` et ``unlock`` utilisent des instructions atomiques telles que celles qui ont été présentées dans la section précédente pour garantir cette propriété. - -Les :term:`mutex` sont fréquemment utilisés pour protéger l'accès à une zone de mémoire partagée. Ainsi, si la variable globale `g` est utilisée en écriture et en lecture par deux threads, celle-ci devra être protégée par un :term:`mutex`. Toute modification de cette variable devra être entourée par des appels à `lock` et `unlock`. - -En C, cela se fait en utilisant les fonctions `pthread_mutex_lock(3posix)`_ et `pthread_mutex_unlock(3posix)`_. Un :term:`mutex` POSIX est représenté par une structure de données de type `pthread_mutex_t` qui est définie dans le fichier `pthread.h`_. Avant d'être utilisé, un :term:`mutex` doit être initialisé via la fonction `pthread_mutex_init(3posix)`_ et lorsqu'il n'est plus nécessaire, les ressources qui lui sont associées doivent être libérées avec la fonction `pthread_mutex_destroy(3posix)`_. - -L'exemple ci-dessous reprend le programme dans lequel une variable globale est incrémentée par plusieurs threads. - -.. literalinclude:: /Threads/S6-src/pthread-mutex.c - :encoding: utf-8 - :language: c - :start-after: ///AAA - -Il est utile de regarder un peu plus en détails les différentes fonctions utilisées par ce programme. Tout d'abord, la ressource partagée est ici la variable ``global``. Dans l'ensemble du programme, l'accès à cette variable est protégé par le :term:`mutex` ``mutex_global``. Celui-ci est représenté par une structure de données de type ``pthread_mutex_t``. - -Avant de pouvoir utiliser un :term:`mutex`, il est nécessaire de l'initialiser. Cette initialisation est effectuée par la fonction `pthread_mutex_init(3posix)`_ qui prend deux arguments [#fstaticinit]_. Le premier est un pointeur vers une structure ``pthread_mutex_t`` et le second un pointeur vers une structure ``pthread_mutexattr_t`` contenant les attributs de ce :term:`mutex`. Tout comme lors de la création d'un thread, ces attributs permettent de spécifier des paramètres à la création du :term:`mutex`. Ces attributs peuvent être manipulés en utilisant les fonctions `pthread_mutexattr_gettype(3posix)`_ et `pthread_mutexattr_settype(3posix)`_. Dans le cadre de ces notes, nous utiliserons exclusivement les attributs par défaut et créerons toujours un :term:`mutex` en passant ``NULL`` comme second argument à la fonction `pthread_mutex_init(3posix)`_. - -Lorsqu'un :term:`mutex` POSIX est initialisé, la ressource qui lui est associée est considérée comme libre. L'accès à la ressource doit se faire en précédant tout accès à la ressource par un appel à la fonction `pthread_mutex_lock(3posix)`_. En fonction des attributs spécifiés à la création du :term:`mutex`, il peut y avoir de très rares cas où la fonction retourne une valeur non nulle. Dans ce cas, le type d'erreur est indiqué via :term:`errno`. Lorsque le thread n'a plus besoin de la ressource protégée par le mutex, il doit appeler la fonction `pthread_mutex_unlock(3posix)`_ pour libérer la ressource protégée. - -`pthread_mutex_lock(3posix)`_ et `pthread_mutex_unlock(3posix)`_ sont toujours utilisés en couple. `pthread_mutex_lock(3posix)`_ doit toujours précéder l'accès à la ressource partagée et `pthread_mutex_unlock(3posix)`_ doit être appelé dès que l'accès exclusif à la ressource partagée n'est plus nécessaire. - - -L'utilisation des mutex permet de résoudre correctement le problème de l'exclusion mutuelle. Pour s'en convaincre, considérons le programme ci-dessus et les threads qui exécutent la fonction ``func``. Celle-ci peut être résumée par les trois lignes suivantes : - -.. code-block:: c - - pthread_mutex_lock(&mutex_global); - global=increment(global); - pthread_mutex_unlock(&mutex_global); - -Pour montrer que cette solution répond bien au problème de l'exclusion mutuelle, il faut montrer qu'elle respecte la propriété de sûreté et la propriété de vivacité. Pour la propriété de sûreté, c'est par construction des :term:`mutex` et parce que chaque thread exécute `pthread_mutex_lock(3posix)`_ avant d'entrer en section critique et `pthread_mutex_unlock(3posix)`_ dès qu'il en sort. Considérons le cas de deux threads qui sont en concurrence pour accéder à cette section critique. Le premier exécute `pthread_mutex_lock(3posix)`_. Il accède à sa section critique. A partir de cet instant, le second thread sera bloqué dès qu'il exécute l'appel à `pthread_mutex_lock(3posix)`_. Il restera bloqué dans l'exécution de cette fonction jusqu'à ce que le premier thread sorte de sa section critique et exécute `pthread_mutex_unlock(3posix)`_. A ce moment, le premier thread n'est plus dans sa section critique et le système peut laisser le second y entrer en terminant l'exécution de l'appel à `pthread_mutex_lock(3posix)`_. Si un troisième thread essaye à ce moment d'entrer dans la section critique, il sera bloqué sur son appel à `pthread_mutex_lock(3posix)`_. - -Pour montrer que la propriété de vivacité est bien respectée, il faut montrer qu'un thread ne sera pas empêché éternellement d'entrer dans sa section critique. Un thread peut être empêché d'entrer dans sa section critique en étant bloqué sur l'appel à `pthread_mutex_lock(3posix)`_. Comme chaque thread exécute `pthread_mutex_unlock(3posix)`_ dès qu'il sort de sa section critique, le thread en attente finira par être exécuté. Pour qu'un thread utilisant le code ci-dessus ne puisse jamais entrer en section critique, il faudrait qu'il y aie en permanence plusieurs threads en attente sur `pthread_mutex_unlock(3posix)`_ et que notre thread ne soit jamais sélectionné par le système lorsque le thread précédent termine sa section critique. - - -.. rubric:: Footnotes - -.. [#fexemple] Le programme complet est accessible via :download:`/Threads/S5-src/pthread-test.c` - -.. [#fpthreadc] Le programme complet est accessible via :download:`/Threads/S6-src/pthread.c` - -.. .. [#fframes] Il existe différents standards pour le nombre d'images par seconde en cinéma et en télévision. Les plus courants sont 24, 25 et 30 images par seconde. Voir http://en.wikipedia.org/wiki/Frame_rate - -.. [#finterrupts] De nombreux processeurs supportent plusieurs signaux d'interruption différents. Dans le cadre de ce cours, nous nous limiterons à l'utilisation d'un seul signal de ce type. - -.. [#fman2] Les appels systèmes sont décrits dans la section ``2`` des pages de manuel tandis que la section ``3`` décrit les fonctions de la librairie. - -.. [#fdisable] Certains systèmes d'exploitation utilisent une désactivation parfois partielle des interruptions pour résoudre des problèmes d'exclusion mutuelle qui portent sur quelques instructions à l'intérieur du système d'exploitation lui-même. Il faut cependant noter qu'une désactivation des interruptions peut être particulièrement coûteuse en termes de performances dans un environnement multiprocesseurs. - -.. [#fstaticinit] Linux supporte également la macro ``PTHREAD_MUTEX_INITIALIZER`` qui permet d'initialiser directement un ``pthread_mutex_t`` déclaré comme variable globale. Dans cet exemple, la déclaration aurait été : ``pthread_mutex_t global_mutex=PTHREAD_MUTEX_INITIALIZER;`` et l'appel à `pthread_mutex_init(3posix)`_ aurait été inutile. Comme il s'agit d'une extension spécifique à Linux, il est préférable de ne pas l'utiliser pour garantir la portabilité du code. - -.. [#fphilo] Le programme complet est :download:`/Threads/S6-src/pthread-philo.c` - diff --git a/Theorie/_static b/Theorie/_static deleted file mode 120000 index 7a2b653646f86d98f976df94c66c017b5d24ecbe..0000000000000000000000000000000000000000 --- a/Theorie/_static +++ /dev/null @@ -1 +0,0 @@ -../_static \ No newline at end of file diff --git a/Theorie/_templates/layout.html b/Theorie/_templates/layout.html deleted file mode 100644 index 289d380b194cd2d21db58b2ded4f2d65a369985c..0000000000000000000000000000000000000000 --- a/Theorie/_templates/layout.html +++ /dev/null @@ -1,4 +0,0 @@ -{% extends "!layout.html" %} -{% block extrahead %} -{% endblock %} - diff --git a/Theorie/bib.rst b/Theorie/bib.rst deleted file mode 100644 index 6514dbd33e53c5a0f7dae2cdd754ea242d242d62..0000000000000000000000000000000000000000 --- a/Theorie/bib.rst +++ /dev/null @@ -1,175 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -************* -Bibliographie -************* - -.. [ABS] Cooper, M., `Advanced Bash-Scripting Guide`, 2011, http://tldp.org/LDP/abs/html/ - -.. [AdelsteinLubanovic2007] Adelstein, T., Lubanovic, B., `Linux System Administration`, OReilly, 2007, http://books.google.be/books?id=-jYe2k1p5tIC - -.. .. [Alagarsamy2003] Alagarsamy, K., `Some myths about famous mutual exclusion algorithms`. SIGACT News 34, 3 (September 2003), 94-103. http://doi.acm.org/10.1145/945526.945527 - -.. [Amdahl1967] Amdahl, G., `Validity of the Single-Processor Approach to Achieving Large-Scale Computing Capabilities`, Proc. Am. Federation of Information Processing Societies Conf., AFIPS Press, 1967, pp. 483-485, http://dx.doi.org/10.1145/1465482.1465560 - -.. [Bashar1997] Bashar, N., `Ariane 5: Who Dunnit?`, IEEE Software 14(3): 15–16. May 1997. https://doi.ieeecomputersociety.org/10.1109/MS.1997.589224 - - -.. .. [BryantOHallaron2011] Bryant, R. and O'Hallaron, D., `Computer Systems : A programmer's perspective`, Second Edition, Pearson, 2011, http://www.amazon.com/Computer-Systems-Programmers-Perspective-2nd/dp/0136108040/ref=sr_1_1?s=books&ie=UTF8&qid=1329058781&sr=1-1 - - -.. [C99] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf - -.. .. [Card+1994] Card, R., Ts’o, T., Tweedie, S, `Design and implementation of the second extended filesystem`. Proceedings of the First Dutch International Symposium on Linux. ISBN 90-367-0385-9. http://web.mit.edu/tytso/www/linux/ext2intro.html - -.. [Cooper2011] Cooper, M., `Advanced Bash-Scripting Guide`, http://tldp.org/LDP/abs/html/, 2011 - -.. .. [Courtois+1971] Courtois, P., Heymans, F. and Parnas, D., `Concurrent control with “readers†and “writersâ€`. Commun. ACM 14, 10 (October 1971), 667-668. http://doi.acm.org/10.1145/362759.362813 - - -.. [CPP] C preprocessor manual, http://gcc.gnu.org/onlinedocs/cpp/ - -.. [Dijkstra1965b] Dijkstra, E., `Cooperating sequential processes`, 1965, http://www.cs.utexas.edu/users/EWD/transcriptions/EWD01xx/EWD123.html - -.. [Dijkstra1965] Dijkstra, E., `Solution of a problem in concurrent programming control`. Commun. ACM 8, 9 (September 1965), 569 http://doi.acm.org/10.1145/365559.365617 - -.. .. [Dijkstra1968] Dijkstra, E., `Go To Statement Considered Harmful`, Communications of the ACM, 11, March 1968, http://www.cs.utexas.edu/~EWD/transcriptions/EWD02xx/EWD215.html Voir aussi [Tribble2005]_ - -.. [Downey2008] Downey, A., `The Little Book of Semaphores`, Second Edition, Green Tea Press, 2008, https://greenteapress.com/wp/semaphores/ - -.. .. [Drepper2007] Drepper, U., `What every programmer should know about memory`, 2007, http://www.akkadia.org/drepper/cpumemory.pdf - -.. [DrepperMolnar2005] Drepper, U., Molnar, I., `The Native POSIX Thread Library for Linux`, http://www.akkadia.org/drepper/nptl-design.pdf - -.. [Goldberg1991] Goldberg, D., `What every computer scientist should know about floating-point arithmetic`. ACM Comput. Surv. 23, 1 (March 1991), 5-48. http://doi.acm.org/10.1145/103162.103163 ou http://www.validlab.com/goldberg/paper.pdf - - -.. [Gove2011] Gove, D., `Multicore Application Programming for Windows, Linux and Oracle Solaris`, Addison-Wesley, 2011, http://books.google.be/books?id=NF-C2ZQZXekC - -.. .. [GNUMake] http://www.gnu.org/software/make/manual/make.html - -.. [GNUPTH] Engelschall, R., `GNU Portable Threads`, http://www.gnu.org/software/pth/ - -.. [Graham+1982] Graham, S., Kessler, P. and Mckusick, M., `Gprof: A call graph execution profiler`. SIGPLAN Not. 17, 6 (June 1982), 120-126. http://doi.acm.org/10.1145/872726.806987 - -.. .. [HennessyPatterson] Hennessy, J. and Patterson, D., `Computer Architecture: A Quantitative Approach`, Morgan Kauffmann, http://books.google.be/books?id=gQ-fSqbLfFoC - -.. .. [HP] HP, `Memory technology evolution: an overview of system memory technologies`, http://h20000.www2.hp.com/bc/docs/support/SupportManual/c00256987/c00256987.pdf - -.. .. [Hyde2010] Hyde, R., `The Art of Assembly Language`, 2nd edition, No Starch Press, http://webster.cs.ucr.edu/AoA/Linux/HTML/AoATOC.html - -.. [IA32] intel, `Intel® 64 and IA-32 Architectures : Software Developer’s Manual`, Combined Volumes: 1, 2A, 2B, 2C, 3A, 3B and 3C, December 2011, http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf - -.. [Kamp2011] Kamp, P., `The Most Expensive One-byte Mistake`, ACM Queue, July 2011, http://queue.acm.org/detail.cfm?id=2010365 - -.. [Kerrisk2010] Kerrisk, M., `The Linux Programming Interface`, No Starch Press, 2010, http://my.safaribooksonline.com/book/programming/linux/9781593272203 - -.. [Kernighan] Kernighan, B., `Programming in C - A Tutorial`, http://cm.bell-labs.com/cm/cs/who/dmr/ctut.pdf - -.. [KernighanRitchie1998] Kernighan, B., and Ritchie, D., `The C programming language, second edition`, Addison Wesley, 1998, http://cm.bell-labs.com/cm/cs/cbook/ - -.. [King2008] King, K., `C programming : a modern approach`, W. W. Norton & company, 2008 - -.. [Krakowiak2011] Krakowiak, S., `Le modele d'architecture de von Neumann`, http://interstices.info/le-modele-darchitecture-de-von-neumann - -.. [Leroy] Leroy, X., `The LinuxThreads library`, http://pauillac.inria.fr/~xleroy/linuxthreads/ - -.. [McKenney2005] McKenney, P., `Memory Ordering in Modern Microprocessors, Part I`, Linux Journal, August 2005, http://www.linuxjournal.com/article/8211 - -.. .. [Mecklenburg+2004] Mechklenburg, R., Mecklenburg, R. W., Oram, A., `Managing projects with GNU make`, O'Reilly, 2004, http://books.google.be/books?id=rL4GthWj9kcC - -.. [Mitchell+2001] Mitchell, M., Oldham, J. and Samuel, A., `Advanced Linux Programming`, New Riders Publishing, ISBN 0-7357-1043-0, June 2001, http://www.advancedlinuxprogramming.com/ - - -.. [Nemeth+2010] Nemeth, E., Hein, T., Snyder, G., Whaley, B., `Unix and Linux System Administration Handbook`, Prentice Hall, 2010, http://books.google.be/books?id=rgFIAnLjb1wC - -.. .. [Peterson1981] Peterson, G., `Myths about the mutual exclusion problem`, Inform. Process. Lett. 12 (3) (1981) 115-116 - -.. [Stallings2011] Stallings, W., `Operating Systems : Internals and Design Principles`, Prentice Hall, 2011, http://williamstallings.com/OperatingSystems/index.html - -.. [StevensRago2008] Stevens, R., and Rago, S., `Advanced Programming in the UNIX Environment`, Addison-Wesley, 2008, http://books.google.be/books?id=wHI8PgAACAAJ - -.. [Stokes2008] Stokes, J., `Classic.Ars: Understanding Moore's Law`, http://arstechnica.com/hardware/news/2008/09/moore.ars - -.. [Tanenbaum+2009] Tanenbaum, A., Woodhull, A., `Operating systems: design and implementation`, Prentice Hall, 2009, https://www.pearson.com/us/higher-education/program/Tanenbaum-Operating-Systems-Design-and-Implementation-3rd-Edition/PGM228096.html - - -.. .. [Tribble2005] Tribble, D., `Go To Statement Considered Harmful: A Retrospective`, 2005, http://david.tribble.com/text/goto.html - -.. [Walls2006] Walls, D., `How to Use the restrict Qualifier in C`. Sun Microsystems, 2006, http://developers.sun.com/solaris/articles/cc_restrict.html - -.. spelling:: - - Cooper - Adelstein - Lubanovic - OReilly - Amdahl - Proc - Am - Federation - of - Processing - Societies - Press - pp - Bashar - May - doi - Cooper - preprocessor - manual - Dijkstra - September - Downey - Edition - Tea - Drepper - Molnar - Goldberg - Surv - March - Gove - Engelschall - Graham - Kessler - Mckusick - Not - intel - Combined - December - Kamp - July - Kerrisk - Starch - Press - Kernighan - Ritchie - Norton - company - Krakowiak - Leroy - August - Mitchell - Oldham - Samuel - New - Riders - Publishing - June - Nemeth - Snyder - Whaley - Stallings - Stevens - Rago - Addison - Wesley - Stokes - Tanenbaum - Woodhull - Prentice - Walls - Microsystems diff --git a/Theorie/conf.py b/Theorie/conf.py deleted file mode 100644 index ddd3ce4384a51d841c87886b0176ddb94e791af6..0000000000000000000000000000000000000000 --- a/Theorie/conf.py +++ /dev/null @@ -1,323 +0,0 @@ -# -*- coding: utf-8 -*- -# -# SINF1252 documentation build configuration file, created by -# sphinx-quickstart on Tue Jan 3 16:17:09 2012. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.todo', 'sphinx.ext.ifconfig', 'sphinx.ext.mathjax', 'sphinx.ext.intersphinx', 'sphinxcontrib.spelling' ] - - -#spelling -spelling_lang='fr' -spelling_word_list_filename='../dict.txt' - -# ucomment -#sys.path.append(os.path.abspath(os.getcwd())) -#extensions.append('ucomment-extension') -#html_translator_class = 'ucomment-extension.ucomment_html_translator' - -# Point to your Django application, which contains all -# the other settings required. -#ucomment = {} -#ucomment['django_application_path'] = '/home/cpaasch/sinf1252/ucommentsite/ucommentapp' - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -source_encoding = 'utf-8' -#source_encoding = 'latin1' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'LEPL1503 : Introduction au langage C' -copyright = u'2013, 2019, O. Bonaventure, G. Detal, C. Paasch' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '2019' -# The full version, including alpha/beta/rc tags. -release = '2019' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -language = 'fr' - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['_build/**', '.#*', '**/.#**', 'Exercices/QCM/**', "**.BASE.**", "**.REMOTE.**", "**.LOCAL.**", "**.BACKUP.**", "MemoireVirtuelle/**", "Assembleur/**", "Fichiers/fichiers-signaux.rst", "Threads/processus.rst" ] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -rst_epilog = """ -.. include:: /links.rst -.. include:: /man_links.rst -.. include:: /incl_links.rst -""" - -# Intersphinx -intersphinx_mapping = {'theorie': ('https://sites.uclouvain.be/SystInfo/notes/Theorie/html/', None), 'outils': ('https://sites.uclouvain.be/SystInfo/notes/Outils/html/', None), 'exercices': ('https://sites.uclouvain.be/SystInfo/notes/Exercices/html/', None)} - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'haiku' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -html_title = u'Langage C' - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'SINF1252doc' - - -# -- Options for LaTeX output -------------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -'papersize': 'a4paper', - -# The font size ('10pt', '11pt' or '12pt'). -'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', - 'preamble': ''' - \\hypersetup{unicode=true} - ''' -# See https://tex.stackexchange.com/questions/120002/how-to-modify-the-default-latex-package-parameters-of-sphinx -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'LEPL1503.tex', u'LEPL1503 : Introduction au langage C', - u'O. Bonaventure, G. Detal, C. Paasch', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'sinf1252', u'SINF1252', - [u'O. Bonaventure, G. Detal, C. Paasch'], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------------ - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'SINF1252', u'SINF1252 : Systèmes informatiques', - u'O. Bonaventure, G. Detal, C. Paasch', 'SINF1252', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - - -# -- Options for Epub output --------------------------------------------------- - -# Bibliographic Dublin Core info. -epub_title = u'LEPL1503 : Introduction au langage C' -epub_author = u'O. Bonaventure, G. Detal, C. Paasch' -epub_publisher = u'O. Bonaventure, G. Detal, C. Paasch' -epub_copyright = u'2013, 2019, O. Bonaventure, G. Detal, C. Paasch' - -# The language of the text. It defaults to the language option -# or en if the language is not set. -#epub_language = '' - -# The scheme of the identifier. Typical schemes are ISBN or URL. -#epub_scheme = '' - -# The unique identifier of the text. This can be a ISBN number -# or the project homepage. -#epub_identifier = '' - -# A unique identification for the text. -#epub_uid = '' - -# A tuple containing the cover image and cover page html template filenames. -#epub_cover = () - -# HTML files that should be inserted before the pages created by sphinx. -# The format is a list of tuples containing the path and title. -#epub_pre_files = [] - -# HTML files shat should be inserted after the pages created by sphinx. -# The format is a list of tuples containing the path and title. -#epub_post_files = [] - -# A list of files that should not be packed into the epub file. -#epub_exclude_files = [] - -# The depth of the table of contents in toc.ncx. -#epub_tocdepth = 3 - -# Allow duplicate toc entries. -#epub_tocdup = True - -#try: -# open('.staff','r') -# tags.add('staff') -# print "Build as staff member" -#except: -# print "Build as student" - -mathjax_path="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML" diff --git a/Theorie/glossaire.rst b/Theorie/glossaire.rst deleted file mode 100644 index 084fe246acbba37ca09acbd0a876f82efb9c80dc..0000000000000000000000000000000000000000 --- a/Theorie/glossaire.rst +++ /dev/null @@ -1,408 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012, 2019 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -********* -Glossaire -********* - -.. glossary:: - :sorted: - - CPU - Central Processing Unit - - C - Langage de programmation permettant d'interagir facilement avec le matériel. - - RISC - Reduced Instruction Set Computer - - CISC - Complex Instruction Set Computer - - x86 - Famille de microprocesseurs développée par intel_. Le 8086 est le premier processeur de cette famille. Ses successeurs (286, 386, Pentium, Centrino, Xeon, ...) sont restés compatibles avec lui tout en introduisant chacun de nouvelles instructions et de nouvelles fonctionnalités. Aujourd'hui, plusieurs fabricants développent des processeurs qui supportent le même langage machine que les processeurs de cette famille. - - Unix - Système d'exploitation développé initialement par AT&T Bell Labs. - - gcc - Compilateur pour la langage C développé par un groupe de volontaires qui est diffusé depuis http://gcc.gnu.org gcc est utilisé dans plusieurs systèmes d'exploitation de type Unix, comme MacOS, Linux ou FreeBSD. Il existe d'autres compilateurs C. Une liste non-exhaustive est maintenue sur http://en.wikipedia.org/wiki/List_of_compilers#C_compilers - - llvm - Ensemble de compilateurs pour différents langages de programmation et différents processeurs développé par un groupe de volontaire. llvm est distrubé depuis http://llvm.org/ - - cpp - préprocesseur - Le préprocesseur C est un programme de manipulation de texte sur base de macros qui est utilisé avec le compilateur. Le préprocesseur de :term:`gcc` est http://gcc.gnu.org/onlinedocs/cpp/ - - microprocesseur - processeur - Unité centrale de l'ordinateur qui exécute les instructions en langage machine et interagit avec la mémoire. - - CPU - Central Processing Unit. Voir :term:`microprocesseur` - - stdin - Entrée standard sur un système Unix (par défaut le clavier) - - stdout - Sortie standard sur un système Unix (par défaut l'écran) - - stderr - Sortie d'erreur standard sur un système Unix (par défaut l'écran) - - X11 - Interface graphique développée au MIT pour Unix. Voir https://en.wikipedia.org/wiki/X_Window_System - - Gnome - Environnement graphique utilisé par de nombreuses distributions Linux. Voir https://en.wikipedia.org/wiki/GNOME - - shell - Interpréteur de commandes sur un système Unix. `bash(1)`_ est l'interpréteur de commandes le plus utilisé de nos jours. - - bit - Plus petite unité d'information. Par convention, un bit peut prendre les valeurs ``0`` et ``1``. - - nibble - Un bloc de quatre bits consécutifs. - - byte - octet - Un bloc de huit bits consécutifs. - - BSD Unix - Variante de Unix développée à l'Université de Californie à Berkeley. - - FreeBSD - Variante de BSD Unix disponible depuis http://www.freebsd.org - - OpenBSD - Variante de BSD Unix disponible depuis http://www.openbsd.org - - MacOS - Système d'exploitation développé par Apple Inc. comprenant de nombreux composantes provenant de :term:`FreeBSD`. - - Minix - Famille de noyaux de systèmes d'exploitation inspiré de :term:`Unix` développée notamment par :term:`Andrew Tanenbaum`. Voir http://www.minix3.org pour la dernière version de Minix. - - Linux - Noyau de système d'exploitation compatible Unix développé initialement par Linus Torvalds. - - Solaris - Système d'exploitation compatible Unix développé par Sun Microsystems et repris par Oracle. La version open-source, OpenSolaris, est disponible depuis http://www.opensolaris.org - - Application Programming Interface - API - Un API est généralement un ensemble de fonctions et de structures de données qui constitue l'interface entre deux composants logiciels qui doivent collaborer. Par exemple, l'API du noyau d'un système Unix est composée de ses appels systèmes. Ceux-ci sont décrits dans la section 2 des pages de manuel (voir `intro(2)`_). - - GNU is not Unix - GNU - GNU est un projet open-source de la Free Software Foundation qui a permis le développement d'un grand nombre d'utilitaires utilisés par les systèmes d'exploitation de la famille Unix actuellement. - - GNU/Linux - Nom générique donné à un système d'exploitation utilisant les utilitaires :term:`GNU` notamment et le noyau :term:`Linux` . - - Andrew Tanenbaum - Andrew Tanenbaum est professeur à la VU d'Amsterdam. - - Linus Torvalds - Linus Torvalds est le créateur et le mainteneur principal du noyau :term:`Linux`. - - Aqua - Aqua est une interface graphique spécifique à :term:`MacOS`. Voir https://en.wikipedia.org/wiki/Aqua_(user_interface) - - pipe - Mécanisme de redirection des entrées-sorties permettant de relier la sortie standard d'un programme à l'entrée standard d'un autre pour créer des pipelines de traitement. - - assembleur - Programme permettant de convertir un programme écrit en langage d'assemblage dans le langage machine correspondant à un processeur donné. - - warning - Message d'avertissement émis par un compilateur C. Un :term:`warning` n'empêche pas la compilation et la génération du code objet. Cependant, la plupart des warnings indiquent un problème dans le programme compilé et il est nettement préférable de les supprimer du code. - - bit de poids fort - Par convention, le bit le plus à gauche d'une séquence de n bits. - - bit de poids faible - Par convention, bit le plus à droite d'une séquence de n bits. - - simple précision - Représentation de nombre réels en virgule flottante (type ``float`` en C). La norme `IEEE754 <http://ieeexplore.ieee.org/xpl/mostRecentIssue.jsp?punumber=4610933>`_ définit le format de ces nombres sur 32 bits. - - double précision - Représentation de nombre réels en virgule flottante (type ``double`` en C). La norme `IEEE754 <http://ieeexplore.ieee.org/xpl/mostRecentIssue.jsp?punumber=4610933>`_ définit le format de ces nombres sur 64 bits. - - buffer overflow - Erreur dans laquelle un programme informatique cherche à stocker plus de données en mémoire que la capacité de la zone réservée en mémoire. Donne généralement lieu à des problèmes, parfois graves, de sécurité. https://en.wikipedia.org/wiki/Buffer_overflow - - garbage collector - Algorithme permettant de libérer la mémoire qui n'est plus utilisée notamment dans des langages tels que Java - - pointeur - Adresse d'une variable ou fonction en mémoire. - - adresse - Position d'un donnée en mémoire. - - C99 - Standard international définissant le langage C [C99]_ - - fichier header - Fichier contenant des signatures de fonctions, des déclarations de types de données, des variables globales, permettant d'utiliser une librairie ou un API. - - segmentation fault - Erreur à l'exécution à compléter - - NOT - négation - Opération binaire logique. - - AND - conjonction logique - Opération binaire logique. - - OR - disjonction logique - Opération binaire logique. - - XOR - ou exclusif - Opération binaire logique. - - libc - Librairie C standard. Contient de nombreuses fonctions utilisables par les programmes écrits en langage C et décrites dans la troisième section des pages de manuel. Linux utilise la librairie GNU `glibc <http://www.gnu.org/software/libc/manual/>`_ qui contient de nombreuses extensions par rapport à la libraire standard. - - FSF - Free Software Foundation, http://www.fsf.org - - portée - Zone d'un programme dans laquelle une variable est déclarée. - - portée locale - Une variable ayant une portée locale est accessible uniquement dans le bloc dans lequelle elle est définie. - - portée globale - Une variable ayant une portée globale est accessible dans tout le programme. - - debugger - Logiciel - - text - segment text - Partie de la mémoire d'un programme contenant les instructions en langage machine à exécuter. - - segment des données initialisées - Partie de la mémoire d'un programme contenant les données initialisées dans le code source du programme ainsi que les chaînes de caractères. - - segment des données non-initialisées - Partie de la mémoire d'un programme contenant les données (tableaux notamment) qui sont déclarés mais pas explicitement initialisés dans le code source du programme. - - heap - tas - Partie de la mémoire d'un programme gérée par `malloc(3)`_ et `free(3)`_. - - stack - pile - Partie de la mémoire d'un programme contenant les variables locales et adresses de retour des fonctions durant leur exécution. - - memory leak - Fuite de mémoire. Erreur concernant un programme qui a alloué de la mémoire avec `malloc(3)`_ et ne l'utilise plus sans avoir fait appel à `free(3)`_ - - processus - Ensemble cohérent d'instructions utilisant une partie de la mémoire, initié par le système d'exploitation et exécuté sur un des processeurs du système. Le système d'exploitation libère les ressources qui lui sont allouées à la fin de son exécution. - - pid - process identifier - identifiant de processus. Sous Unix, chaque processus est identifié par un entier unique. Cet identifiant sert de clé d'accès à la :term:`table des processus`. Voir `getpid(2)`_ pour récupérer l'identifiant du processus courant. - - table des processus - Table contenant les identifiants (:term:`pid`) de tous les processus qui s'exécutent à ce moment sur un système Unix. Outre les identifiants, cette table contient de nombreuses informations relatives à chaque :term:`processus`. Voir également :term:`/proc` - - /proc - Sous Linux, représentation de l'information stockée dans la :term:`table des processus` sous la forme d'une arborescence directement accessible via les commandes du :term:`shell`. Voir `proc(5)`_ - - signal - mécanisme permettant la communication entre processus. Utilisé notamment pour arrêter un processus via la commande `kill(1)`_ - - von Neumann - Un des inventaires des premiers ordinateurs. A défini l'architecture de base des premiers ordinateurs qui est maintenant connue comme le modèle de von Neumann [Krakowiak2011]_ - - mémoire - Dispositif électronique permettant de stocker - - SRAM - static RAM - Un des deux principaux types de mémoire. Dans une SRAM, l'information est mémorisée comme la présence ou l'absence d'un courant électrique. Les mémoires SRAM sont généralement assez rapides mais de faible capacité. Elles sont souvent utilisées pour construire des mémoires caches. - - DRAM - dynamic RAM - Un des deux principaux types de mémoire. Dans une DRAM, l'information est mémorisée comme la présence ou l'absence de charge dans un minuscule condensateur. Les mémoires DRAM sont plus lentes que les :term:`SRAM` mais ont une plus grande capacité. - - RAM - Random Access Memory - Mémoire à accès aléatoire. Mémoire permettant au processeur d'accéder à n'importe quelle donnée en connaissant son adresse. Voir :term:`DRAM` et :term:`SRAM`. - - - registre - Unité de mémoire intégrée au processeur. Les registres sont utilisés comme source ou destination pour la plupart des opérations effectuées par un processeur. - - hiérarchie de mémoire - Ensemble des mémoires utilisées sur un ordinateur. Depuis les registres jusqu'à la mémoire virtuelle en passant par la mémoire centrale et les mémoires caches. - - mémoire cache - Mémoire rapide de faible capacité. La mémoire cache peut stocker des données provenant de mémoires de plus grande capacité mais qui sont plus lentes, et exploite le :term:`principe de localité` en stockant de manière transparente les instructions et les données les plus récemment utilisées. Elle fait office d'interface entre le processeur et la mémoire principale et toutes les demandes d'accès à la mémoire principale passent par la mémoire cache, ce qui permet d'améliorer les performances de nombreux systèmes informatiques. - - eip - pc - compteur de programme - instruction pointer - Registre spécial du processeur qui contient en permanence l'adresse de l'instruction en cours d'exécution. Le contenu de ce registre est incrémenté après chaque instruction et modifié par les instructions de saut. - - makefile - à compléter - - fichier - à compléter - - fichier objet - à compléter - - linker - à compléter - - errno - à compléter - - loi de Moore - à compléter - - kHz - à compléter - - MHz - à compléter - - GHz - à compléter - - MIPS - Million d'instructions par seconde - - benchmark - à compléter - - multi-coeurs - à compléter - - multithreadé - Programme utilisant plusieurs threads. - - section critique - Partie de programme ne pouvant pas être exécutée simultanément par deux threads différents. - - exclusion mutuelle - à compléter - - sûreté - safety - à compléter - - liveness - vivacité - à compléter - - multitâche - multitasking - à compléter - - contexte - à compléter - - changement de contexte - à compléter - - interruption - à compléter - - scheduler - à compléter - - round-robin - à compléter - - livelock - à compléter - - opération atomique - à compléter - - deadlock - à compléter - - mutex - à compléter - - appel système - à compléter - - appel système bloquant - à compléter - - sémaphore - à compléter - - thread-safe - à compléter - - loi de Amdahl - à compléter - - static library - librairie statique - à compléter - - shared library - librairie dynamique - librairie partagée - à compléter - - descripteur de fichier - à compléter - - répertoire - à compléter - - répertoire courant - à compléter - - offset pointer - à compléter - - little endian - à compléter - - big endian - à compléter - - lien symbolique - à compléter - - appel système lent - à compléter - - - SSD - Solid State Drive - Système de stockage de données s'appuyant uniquement sur de la mémoire flash. - - root - à compléter - - userid - à compléter - - Unicode - Norme d'encodage de caractères supportant l'ensemble des langues écrites, voir notamment https://en.wikipedia.org/wiki/Unicode diff --git a/Theorie/incl_links.rst b/Theorie/incl_links.rst deleted file mode 100644 index 87441f3ee9b4f291d43fe0de72b96a7f873d8baf..0000000000000000000000000000000000000000 --- a/Theorie/incl_links.rst +++ /dev/null @@ -1,918 +0,0 @@ -.. _`mntent.h` : http://sites.uclouvain.be/SystInfo/usr/include/mntent.h.html -.. _`stdint.h` : http://sites.uclouvain.be/SystInfo/usr/include/stdint.h.html -.. _`getopt.h` : http://sites.uclouvain.be/SystInfo/usr/include/getopt.h.html -.. _`bmmintrin.h` : http://sites.uclouvain.be/SystInfo/usr/include/bmmintrin.h.html -.. _`pmmintrin.h` : http://sites.uclouvain.be/SystInfo/usr/include/pmmintrin.h.html -.. _`pthread.h` : http://sites.uclouvain.be/SystInfo/usr/include/pthread.h.html -.. _`aliases.h` : http://sites.uclouvain.be/SystInfo/usr/include/aliases.h.html -.. _`gshadow.h` : http://sites.uclouvain.be/SystInfo/usr/include/gshadow.h.html -.. _`mm_malloc.h` : http://sites.uclouvain.be/SystInfo/usr/include/mm_malloc.h.html -.. _`link.h` : http://sites.uclouvain.be/SystInfo/usr/include/link.h.html -.. _`immintrin.h` : http://sites.uclouvain.be/SystInfo/usr/include/immintrin.h.html -.. _`grp.h` : http://sites.uclouvain.be/SystInfo/usr/include/grp.h.html -.. _`libio.h` : http://sites.uclouvain.be/SystInfo/usr/include/libio.h.html -.. _`cpio.h` : http://sites.uclouvain.be/SystInfo/usr/include/cpio.h.html -.. _`xmmintrin.h` : http://sites.uclouvain.be/SystInfo/usr/include/xmmintrin.h.html -.. _`memory.h` : http://sites.uclouvain.be/SystInfo/usr/include/memory.h.html -.. _`nmmintrin.h` : http://sites.uclouvain.be/SystInfo/usr/include/nmmintrin.h.html -.. _`locale.h` : http://sites.uclouvain.be/SystInfo/usr/include/locale.h.html -.. _`aio.h` : http://sites.uclouvain.be/SystInfo/usr/include/aio.h.html -.. _`alloca.h` : http://sites.uclouvain.be/SystInfo/usr/include/alloca.h.html -.. _`ctype.h` : http://sites.uclouvain.be/SystInfo/usr/include/ctype.h.html -.. _`tar.h` : http://sites.uclouvain.be/SystInfo/usr/include/tar.h.html -.. _`inttypes.h` : http://sites.uclouvain.be/SystInfo/usr/include/inttypes.h.html -.. _`err.h` : http://sites.uclouvain.be/SystInfo/usr/include/err.h.html -.. _`x86intrin.h` : http://sites.uclouvain.be/SystInfo/usr/include/x86intrin.h.html -.. _`paths.h` : http://sites.uclouvain.be/SystInfo/usr/include/paths.h.html -.. _`malloc.h` : http://sites.uclouvain.be/SystInfo/usr/include/malloc.h.html -.. _`syscall.h` : http://sites.uclouvain.be/SystInfo/usr/include/syscall.h.html -.. _`dirent.h` : http://sites.uclouvain.be/SystInfo/usr/include/dirent.h.html -.. _`float.h` : http://sites.uclouvain.be/SystInfo/usr/include/float.h.html -.. _`wmmintrin.h` : http://sites.uclouvain.be/SystInfo/usr/include/wmmintrin.h.html -.. _`_G_config.h` : http://sites.uclouvain.be/SystInfo/usr/include/_G_config.h.html -.. _`ftw.h` : http://sites.uclouvain.be/SystInfo/usr/include/ftw.h.html -.. _`fnmatch.h` : http://sites.uclouvain.be/SystInfo/usr/include/fnmatch.h.html -.. _`libgen.h` : http://sites.uclouvain.be/SystInfo/usr/include/libgen.h.html -.. _`byteswap.h` : http://sites.uclouvain.be/SystInfo/usr/include/byteswap.h.html -.. _`time.h` : http://sites.uclouvain.be/SystInfo/usr/include/time.h.html -.. _`crypt.h` : http://sites.uclouvain.be/SystInfo/usr/include/crypt.h.html -.. _`cpuid.h` : http://sites.uclouvain.be/SystInfo/usr/include/cpuid.h.html -.. _`regexp.h` : http://sites.uclouvain.be/SystInfo/usr/include/regexp.h.html -.. _`stdio_ext.h` : http://sites.uclouvain.be/SystInfo/usr/include/stdio_ext.h.html -.. _`wchar.h` : http://sites.uclouvain.be/SystInfo/usr/include/wchar.h.html -.. _`netdb.h` : http://sites.uclouvain.be/SystInfo/usr/include/netdb.h.html -.. _`fmtmsg.h` : http://sites.uclouvain.be/SystInfo/usr/include/fmtmsg.h.html -.. _`monetary.h` : http://sites.uclouvain.be/SystInfo/usr/include/monetary.h.html -.. _`ttyent.h` : http://sites.uclouvain.be/SystInfo/usr/include/ttyent.h.html -.. _`nss.h` : http://sites.uclouvain.be/SystInfo/usr/include/nss.h.html -.. _`sgtty.h` : http://sites.uclouvain.be/SystInfo/usr/include/sgtty.h.html -.. _`values.h` : http://sites.uclouvain.be/SystInfo/usr/include/values.h.html -.. _`semaphore.h` : http://sites.uclouvain.be/SystInfo/usr/include/semaphore.h.html -.. _`ar.h` : http://sites.uclouvain.be/SystInfo/usr/include/ar.h.html -.. _`termios.h` : http://sites.uclouvain.be/SystInfo/usr/include/termios.h.html -.. _`shadow.h` : http://sites.uclouvain.be/SystInfo/usr/include/shadow.h.html -.. _`nl_types.h` : http://sites.uclouvain.be/SystInfo/usr/include/nl_types.h.html -.. _`stdio.h` : http://sites.uclouvain.be/SystInfo/usr/include/stdio.h.html -.. _`strings.h` : http://sites.uclouvain.be/SystInfo/usr/include/strings.h.html -.. _`iso646.h` : http://sites.uclouvain.be/SystInfo/usr/include/iso646.h.html -.. _`tgmath.h` : http://sites.uclouvain.be/SystInfo/usr/include/tgmath.h.html -.. _`elf.h` : http://sites.uclouvain.be/SystInfo/usr/include/elf.h.html -.. _`error.h` : http://sites.uclouvain.be/SystInfo/usr/include/error.h.html -.. _`search.h` : http://sites.uclouvain.be/SystInfo/usr/include/search.h.html -.. _`pwd.h` : http://sites.uclouvain.be/SystInfo/usr/include/pwd.h.html -.. _`dlfcn.h` : http://sites.uclouvain.be/SystInfo/usr/include/dlfcn.h.html -.. _`stdarg.h` : http://sites.uclouvain.be/SystInfo/usr/include/stdarg.h.html -.. _`setjmp.h` : http://sites.uclouvain.be/SystInfo/usr/include/setjmp.h.html -.. _`lastlog.h` : http://sites.uclouvain.be/SystInfo/usr/include/lastlog.h.html -.. _`execinfo.h` : http://sites.uclouvain.be/SystInfo/usr/include/execinfo.h.html -.. _`termio.h` : http://sites.uclouvain.be/SystInfo/usr/include/termio.h.html -.. _`argp.h` : http://sites.uclouvain.be/SystInfo/usr/include/argp.h.html -.. _`stab.h` : http://sites.uclouvain.be/SystInfo/usr/include/stab.h.html -.. _`assert.h` : http://sites.uclouvain.be/SystInfo/usr/include/assert.h.html -.. _`ammintrin.h` : http://sites.uclouvain.be/SystInfo/usr/include/ammintrin.h.html -.. _`obstack.h` : http://sites.uclouvain.be/SystInfo/usr/include/obstack.h.html -.. _`ucontext.h` : http://sites.uclouvain.be/SystInfo/usr/include/ucontext.h.html -.. _`avxintrin.h` : http://sites.uclouvain.be/SystInfo/usr/include/avxintrin.h.html -.. _`emmintrin.h` : http://sites.uclouvain.be/SystInfo/usr/include/emmintrin.h.html -.. _`fpu_control.h` : http://sites.uclouvain.be/SystInfo/usr/include/fpu_control.h.html -.. _`mmintrin-common.h` : http://sites.uclouvain.be/SystInfo/usr/include/mmintrin-common.h.html -.. _`argz.h` : http://sites.uclouvain.be/SystInfo/usr/include/argz.h.html -.. _`stdlib.h` : http://sites.uclouvain.be/SystInfo/usr/include/stdlib.h.html -.. _`signal.h` : http://sites.uclouvain.be/SystInfo/usr/include/signal.h.html -.. _`varargs.h` : http://sites.uclouvain.be/SystInfo/usr/include/varargs.h.html -.. _`mcheck.h` : http://sites.uclouvain.be/SystInfo/usr/include/mcheck.h.html -.. _`syslog.h` : http://sites.uclouvain.be/SystInfo/usr/include/syslog.h.html -.. _`mm3dnow.h` : http://sites.uclouvain.be/SystInfo/usr/include/mm3dnow.h.html -.. _`unwind.h` : http://sites.uclouvain.be/SystInfo/usr/include/unwind.h.html -.. _`wait.h` : http://sites.uclouvain.be/SystInfo/usr/include/wait.h.html -.. _`tmmintrin.h` : http://sites.uclouvain.be/SystInfo/usr/include/tmmintrin.h.html -.. _`gnu-versions.h` : http://sites.uclouvain.be/SystInfo/usr/include/gnu-versions.h.html -.. _`math.h` : http://sites.uclouvain.be/SystInfo/usr/include/math.h.html -.. _`poll.h` : http://sites.uclouvain.be/SystInfo/usr/include/poll.h.html -.. _`ustat.h` : http://sites.uclouvain.be/SystInfo/usr/include/ustat.h.html -.. _`complex.h` : http://sites.uclouvain.be/SystInfo/usr/include/complex.h.html -.. _`utime.h` : http://sites.uclouvain.be/SystInfo/usr/include/utime.h.html -.. _`clif.h` : http://sites.uclouvain.be/SystInfo/usr/include/clif.h.html -.. _`ulimit.h` : http://sites.uclouvain.be/SystInfo/usr/include/ulimit.h.html -.. _`fstab.h` : http://sites.uclouvain.be/SystInfo/usr/include/fstab.h.html -.. _`stdbool.h` : http://sites.uclouvain.be/SystInfo/usr/include/stdbool.h.html -.. _`fcntl.h` : http://sites.uclouvain.be/SystInfo/usr/include/fcntl.h.html -.. _`sysexits.h` : http://sites.uclouvain.be/SystInfo/usr/include/sysexits.h.html -.. _`glob.h` : http://sites.uclouvain.be/SystInfo/usr/include/glob.h.html -.. _`spawn.h` : http://sites.uclouvain.be/SystInfo/usr/include/spawn.h.html -.. _`wctype.h` : http://sites.uclouvain.be/SystInfo/usr/include/wctype.h.html -.. _`utmp.h` : http://sites.uclouvain.be/SystInfo/usr/include/utmp.h.html -.. _`unistd.h` : http://sites.uclouvain.be/SystInfo/usr/include/unistd.h.html -.. _`fenv.h` : http://sites.uclouvain.be/SystInfo/usr/include/fenv.h.html -.. _`wordexp.h` : http://sites.uclouvain.be/SystInfo/usr/include/wordexp.h.html -.. _`errno.h` : http://sites.uclouvain.be/SystInfo/usr/include/errno.h.html -.. _`stddef.h` : http://sites.uclouvain.be/SystInfo/usr/include/stddef.h.html -.. _`xlocale.h` : http://sites.uclouvain.be/SystInfo/usr/include/xlocale.h.html -.. _`a.out.h` : http://sites.uclouvain.be/SystInfo/usr/include/a.out.h.html -.. _`langinfo.h` : http://sites.uclouvain.be/SystInfo/usr/include/langinfo.h.html -.. _`pty.h` : http://sites.uclouvain.be/SystInfo/usr/include/pty.h.html -.. _`envz.h` : http://sites.uclouvain.be/SystInfo/usr/include/envz.h.html -.. _`utmpx.h` : http://sites.uclouvain.be/SystInfo/usr/include/utmpx.h.html -.. _`omp.h` : http://sites.uclouvain.be/SystInfo/usr/include/omp.h.html -.. _`libintl.h` : http://sites.uclouvain.be/SystInfo/usr/include/libintl.h.html -.. _`ifaddrs.h` : http://sites.uclouvain.be/SystInfo/usr/include/ifaddrs.h.html -.. _`mqueue.h` : http://sites.uclouvain.be/SystInfo/usr/include/mqueue.h.html -.. _`fts.h` : http://sites.uclouvain.be/SystInfo/usr/include/fts.h.html -.. _`mmintrin.h` : http://sites.uclouvain.be/SystInfo/usr/include/mmintrin.h.html -.. _`smmintrin.h` : http://sites.uclouvain.be/SystInfo/usr/include/smmintrin.h.html -.. _`endian.h` : http://sites.uclouvain.be/SystInfo/usr/include/endian.h.html -.. _`resolv.h` : http://sites.uclouvain.be/SystInfo/usr/include/resolv.h.html -.. _`cross-stdarg.h` : http://sites.uclouvain.be/SystInfo/usr/include/cross-stdarg.h.html -.. _`stdfix.h` : http://sites.uclouvain.be/SystInfo/usr/include/stdfix.h.html -.. _`regex.h` : http://sites.uclouvain.be/SystInfo/usr/include/regex.h.html -.. _`features.h` : http://sites.uclouvain.be/SystInfo/usr/include/features.h.html -.. _`re_comp.h` : http://sites.uclouvain.be/SystInfo/usr/include/re_comp.h.html -.. _`iconv.h` : http://sites.uclouvain.be/SystInfo/usr/include/iconv.h.html -.. _`sched.h` : http://sites.uclouvain.be/SystInfo/usr/include/sched.h.html -.. _`string.h` : http://sites.uclouvain.be/SystInfo/usr/include/string.h.html -.. _`ieee754.h` : http://sites.uclouvain.be/SystInfo/usr/include/ieee754.h.html -.. _`limits.h` : http://sites.uclouvain.be/SystInfo/usr/include/limits.h.html -.. _`gconv.h` : http://sites.uclouvain.be/SystInfo/usr/include/gconv.h.html -.. _`printf.h` : http://sites.uclouvain.be/SystInfo/usr/include/printf.h.html -.. _`thread_db.h` : http://sites.uclouvain.be/SystInfo/usr/include/thread_db.h.html -.. _`stropts.h` : http://sites.uclouvain.be/SystInfo/usr/include/stropts.h.html -.. _`initreq.h` : http://sites.uclouvain.be/SystInfo/usr/include/initreq.h.html -.. _`python2.6/pyconfig.h` : http://sites.uclouvain.be/SystInfo/usr/include/python2.6/pyconfig.h.html -.. _`xen/evtchn.h` : http://sites.uclouvain.be/SystInfo/usr/include/xen/evtchn.h.html -.. _`linux/atm_he.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atm_he.h.html -.. _`linux/atm_zatm.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atm_zatm.h.html -.. _`linux/if_pppol2tp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_pppol2tp.h.html -.. _`linux/baycom.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/baycom.h.html -.. _`linux/sem.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/sem.h.html -.. _`linux/if_arcnet.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_arcnet.h.html -.. _`linux/bfs_fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/bfs_fs.h.html -.. _`linux/mtio.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/mtio.h.html -.. _`linux/can.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/can.h.html -.. _`linux/nfs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/nfs.h.html -.. _`linux/if_tun.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_tun.h.html -.. _`linux/atm_eni.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atm_eni.h.html -.. _`linux/spi` : http://sites.uclouvain.be/SystInfo/usr/include/linux/spi.html -.. _`linux/dcbnl.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/dcbnl.h.html -.. _`linux/ncp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ncp.h.html -.. _`linux/dlm.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/dlm.h.html -.. _`linux/qnxtypes.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/qnxtypes.h.html -.. _`linux/can` : http://sites.uclouvain.be/SystInfo/usr/include/linux/can.html -.. _`linux/netfilter_arp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/netfilter_arp.h.html -.. _`linux/veth.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/veth.h.html -.. _`linux/kdev_t.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/kdev_t.h.html -.. _`linux/tc_ematch` : http://sites.uclouvain.be/SystInfo/usr/include/linux/tc_ematch.html -.. _`linux/elf-em.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/elf-em.h.html -.. _`linux/hid.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/hid.h.html -.. _`linux/icmp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/icmp.h.html -.. _`linux/sunrpc` : http://sites.uclouvain.be/SystInfo/usr/include/linux/sunrpc.html -.. _`linux/cyclades.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/cyclades.h.html -.. _`linux/hdlc` : http://sites.uclouvain.be/SystInfo/usr/include/linux/hdlc.html -.. _`linux/net_dropmon.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/net_dropmon.h.html -.. _`linux/mroute.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/mroute.h.html -.. _`linux/in.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/in.h.html -.. _`linux/capi.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/capi.h.html -.. _`linux/pg.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/pg.h.html -.. _`linux/atmmpc.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atmmpc.h.html -.. _`linux/if_arp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_arp.h.html -.. _`linux/netfilter_decnet.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/netfilter_decnet.h.html -.. _`linux/vt.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/vt.h.html -.. _`linux/futex.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/futex.h.html -.. _`linux/sysctl.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/sysctl.h.html -.. _`linux/atmclip.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atmclip.h.html -.. _`linux/ivtv.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ivtv.h.html -.. _`linux/wimax` : http://sites.uclouvain.be/SystInfo/usr/include/linux/wimax.html -.. _`linux/usb` : http://sites.uclouvain.be/SystInfo/usr/include/linux/usb.html -.. _`linux/ipsec.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ipsec.h.html -.. _`linux/msg.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/msg.h.html -.. _`linux/coda_psdev.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/coda_psdev.h.html -.. _`linux/dn.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/dn.h.html -.. _`linux/sound.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/sound.h.html -.. _`linux/tc_act` : http://sites.uclouvain.be/SystInfo/usr/include/linux/tc_act.html -.. _`linux/wimax.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/wimax.h.html -.. _`linux/ip6_tunnel.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ip6_tunnel.h.html -.. _`linux/if_pppox.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_pppox.h.html -.. _`linux/map_to_7segment.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/map_to_7segment.h.html -.. _`linux/kvm_para.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/kvm_para.h.html -.. _`linux/if_ec.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_ec.h.html -.. _`linux/ivtvfb.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ivtvfb.h.html -.. _`linux/atmppp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atmppp.h.html -.. _`linux/hdlc.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/hdlc.h.html -.. _`linux/nfs_mount.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/nfs_mount.h.html -.. _`linux/blkpg.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/blkpg.h.html -.. _`linux/cramfs_fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/cramfs_fs.h.html -.. _`linux/if_tunnel.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_tunnel.h.html -.. _`linux/nfs2.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/nfs2.h.html -.. _`linux/minix_fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/minix_fs.h.html -.. _`linux/ip.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ip.h.html -.. _`linux/inet_diag.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/inet_diag.h.html -.. _`linux/socket.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/socket.h.html -.. _`linux/jffs2.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/jffs2.h.html -.. _`linux/virtio_config.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/virtio_config.h.html -.. _`linux/i2c.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/i2c.h.html -.. _`linux/apm_bios.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/apm_bios.h.html -.. _`linux/blktrace_api.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/blktrace_api.h.html -.. _`linux/phonet.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/phonet.h.html -.. _`linux/ptrace.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ptrace.h.html -.. _`linux/mempolicy.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/mempolicy.h.html -.. _`linux/quota.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/quota.h.html -.. _`linux/i2o-dev.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/i2o-dev.h.html -.. _`linux/xfrm.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/xfrm.h.html -.. _`linux/tipc.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/tipc.h.html -.. _`linux/swab.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/swab.h.html -.. _`linux/nbd.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/nbd.h.html -.. _`linux/comstats.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/comstats.h.html -.. _`linux/wireless.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/wireless.h.html -.. _`linux/parport.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/parport.h.html -.. _`linux/nfs3.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/nfs3.h.html -.. _`linux/tcp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/tcp.h.html -.. _`linux/ppdev.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ppdev.h.html -.. _`linux/types.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/types.h.html -.. _`linux/rtnetlink.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/rtnetlink.h.html -.. _`linux/smbno.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/smbno.h.html -.. _`linux/time.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/time.h.html -.. _`linux/virtio_ids.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/virtio_ids.h.html -.. _`linux/resource.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/resource.h.html -.. _`linux/nfs_fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/nfs_fs.h.html -.. _`linux/soundcard.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/soundcard.h.html -.. _`linux/aufs_type.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/aufs_type.h.html -.. _`linux/param.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/param.h.html -.. _`linux/joystick.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/joystick.h.html -.. _`linux/dm-ioctl.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/dm-ioctl.h.html -.. _`linux/kernel.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/kernel.h.html -.. _`linux/elf-fdpic.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/elf-fdpic.h.html -.. _`linux/filter.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/filter.h.html -.. _`linux/if_ltalk.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_ltalk.h.html -.. _`linux/eventpoll.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/eventpoll.h.html -.. _`linux/if.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if.h.html -.. _`linux/tipc_config.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/tipc_config.h.html -.. _`linux/fd.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/fd.h.html -.. _`linux/phantom.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/phantom.h.html -.. _`linux/fib_rules.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/fib_rules.h.html -.. _`linux/ipmi_msgdefs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ipmi_msgdefs.h.html -.. _`linux/pfkeyv2.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/pfkeyv2.h.html -.. _`linux/auxvec.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/auxvec.h.html -.. _`linux/audit.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/audit.h.html -.. _`linux/fuse.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/fuse.h.html -.. _`linux/ext2_fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ext2_fs.h.html -.. _`linux/ax25.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ax25.h.html -.. _`linux/ncp_fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ncp_fs.h.html -.. _`linux/if_hippi.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_hippi.h.html -.. _`linux/nfsacl.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/nfsacl.h.html -.. _`linux/if_link.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_link.h.html -.. _`linux/un.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/un.h.html -.. _`linux/sonet.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/sonet.h.html -.. _`linux/serial_reg.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/serial_reg.h.html -.. _`linux/videotext.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/videotext.h.html -.. _`linux/cdrom.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/cdrom.h.html -.. _`linux/watchdog.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/watchdog.h.html -.. _`linux/hdlcdrv.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/hdlcdrv.h.html -.. _`linux/mroute6.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/mroute6.h.html -.. _`linux/keyctl.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/keyctl.h.html -.. _`linux/cdk.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/cdk.h.html -.. _`linux/capability.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/capability.h.html -.. _`linux/dlm_netlink.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/dlm_netlink.h.html -.. _`linux/ioctl.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ioctl.h.html -.. _`linux/raid` : http://sites.uclouvain.be/SystInfo/usr/include/linux/raid.html -.. _`linux/hpet.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/hpet.h.html -.. _`linux/cm4000_cs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/cm4000_cs.h.html -.. _`linux/kd.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/kd.h.html -.. _`linux/isdnif.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/isdnif.h.html -.. _`linux/rtc.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/rtc.h.html -.. _`linux/telephony.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/telephony.h.html -.. _`linux/if_packet.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_packet.h.html -.. _`linux/netfilter_ipv4` : http://sites.uclouvain.be/SystInfo/usr/include/linux/netfilter_ipv4.html -.. _`linux/tiocl.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/tiocl.h.html -.. _`linux/utsname.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/utsname.h.html -.. _`linux/snmp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/snmp.h.html -.. _`linux/oom.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/oom.h.html -.. _`linux/atmlec.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atmlec.h.html -.. _`linux/agpgart.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/agpgart.h.html -.. _`linux/som.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/som.h.html -.. _`linux/netfilter_ipv6` : http://sites.uclouvain.be/SystInfo/usr/include/linux/netfilter_ipv6.html -.. _`linux/atmarp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atmarp.h.html -.. _`linux/atm.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atm.h.html -.. _`linux/termios.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/termios.h.html -.. _`linux/udf_fs_i.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/udf_fs_i.h.html -.. _`linux/if_bridge.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_bridge.h.html -.. _`linux/input.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/input.h.html -.. _`linux/nl80211.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/nl80211.h.html -.. _`linux/n_r3964.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/n_r3964.h.html -.. _`linux/smb_mount.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/smb_mount.h.html -.. _`linux/matroxfb.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/matroxfb.h.html -.. _`linux/ipv6.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ipv6.h.html -.. _`linux/ppp_defs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ppp_defs.h.html -.. _`linux/keyboard.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/keyboard.h.html -.. _`linux/hysdn_if.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/hysdn_if.h.html -.. _`linux/elf.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/elf.h.html -.. _`linux/patchkey.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/patchkey.h.html -.. _`linux/if_strip.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_strip.h.html -.. _`linux/virtio_blk.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/virtio_blk.h.html -.. _`linux/netfilter` : http://sites.uclouvain.be/SystInfo/usr/include/linux/netfilter.html -.. _`linux/posix_types.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/posix_types.h.html -.. _`linux/b1lli.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/b1lli.h.html -.. _`linux/bsg.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/bsg.h.html -.. _`linux/netfilter.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/netfilter.h.html -.. _`linux/const.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/const.h.html -.. _`linux/if_plip.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_plip.h.html -.. _`linux/raw.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/raw.h.html -.. _`linux/tty.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/tty.h.html -.. _`linux/virtio_net.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/virtio_net.h.html -.. _`linux/mman.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/mman.h.html -.. _`linux/atm_tcp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atm_tcp.h.html -.. _`linux/videodev2.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/videodev2.h.html -.. _`linux/iso_fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/iso_fs.h.html -.. _`linux/atmbr2684.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atmbr2684.h.html -.. _`linux/arcfb.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/arcfb.h.html -.. _`linux/cn_proc.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/cn_proc.h.html -.. _`linux/gigaset_dev.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/gigaset_dev.h.html -.. _`linux/loop.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/loop.h.html -.. _`linux/virtio_balloon.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/virtio_balloon.h.html -.. _`linux/reiserfs_fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/reiserfs_fs.h.html -.. _`linux/gfs2_ondisk.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/gfs2_ondisk.h.html -.. _`linux/cciss_ioctl.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/cciss_ioctl.h.html -.. _`linux/atmapi.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atmapi.h.html -.. _`linux/sonypi.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/sonypi.h.html -.. _`linux/major.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/major.h.html -.. _`linux/ncp_mount.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ncp_mount.h.html -.. _`linux/atmdev.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atmdev.h.html -.. _`linux/if_phonet.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_phonet.h.html -.. _`linux/if_ether.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_ether.h.html -.. _`linux/ppp-comp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ppp-comp.h.html -.. _`linux/magic.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/magic.h.html -.. _`linux/if_eql.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_eql.h.html -.. _`linux/virtio_console.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/virtio_console.h.html -.. _`linux/virtio_9p.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/virtio_9p.h.html -.. _`linux/sockios.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/sockios.h.html -.. _`linux/kvm.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/kvm.h.html -.. _`linux/dlm_device.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/dlm_device.h.html -.. _`linux/edd.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/edd.h.html -.. _`linux/serial.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/serial.h.html -.. _`linux/times.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/times.h.html -.. _`linux/lp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/lp.h.html -.. _`linux/kernelcapi.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/kernelcapi.h.html -.. _`linux/if_ppp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_ppp.h.html -.. _`linux/pci.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/pci.h.html -.. _`linux/shm.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/shm.h.html -.. _`linux/atm_nicstar.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atm_nicstar.h.html -.. _`linux/x25.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/x25.h.html -.. _`linux/screen_info.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/screen_info.h.html -.. _`linux/rfkill.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/rfkill.h.html -.. _`linux/radeonfb.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/radeonfb.h.html -.. _`linux/ipc.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ipc.h.html -.. _`linux/adfs_fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/adfs_fs.h.html -.. _`linux/signal.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/signal.h.html -.. _`linux/dvb` : http://sites.uclouvain.be/SystInfo/usr/include/linux/dvb.html -.. _`linux/reboot.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/reboot.h.html -.. _`linux/version.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/version.h.html -.. _`linux/hiddev.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/hiddev.h.html -.. _`linux/ixjuser.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ixjuser.h.html -.. _`linux/auto_fs4.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/auto_fs4.h.html -.. _`linux/if_addr.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_addr.h.html -.. _`linux/if_fddi.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_fddi.h.html -.. _`linux/genetlink.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/genetlink.h.html -.. _`linux/mmtimer.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/mmtimer.h.html -.. _`linux/atmsap.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atmsap.h.html -.. _`linux/isdn_divertif.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/isdn_divertif.h.html -.. _`linux/generic_serial.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/generic_serial.h.html -.. _`linux/wait.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/wait.h.html -.. _`linux/errqueue.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/errqueue.h.html -.. _`linux/netfilter_ipv6.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/netfilter_ipv6.h.html -.. _`linux/scc.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/scc.h.html -.. _`linux/if_tr.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_tr.h.html -.. _`linux/isdn.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/isdn.h.html -.. _`linux/mii.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/mii.h.html -.. _`linux/pktcdvd.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/pktcdvd.h.html -.. _`linux/nfs4_mount.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/nfs4_mount.h.html -.. _`linux/poll.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/poll.h.html -.. _`linux/synclink.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/synclink.h.html -.. _`linux/personality.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/personality.h.html -.. _`linux/i8k.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/i8k.h.html -.. _`linux/hdreg.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/hdreg.h.html -.. _`linux/atm_idt77105.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atm_idt77105.h.html -.. _`linux/netfilter_bridge` : http://sites.uclouvain.be/SystInfo/usr/include/linux/netfilter_bridge.html -.. _`linux/utime.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/utime.h.html -.. _`linux/selinux_netlink.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/selinux_netlink.h.html -.. _`linux/i2c-dev.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/i2c-dev.h.html -.. _`linux/dlm_plock.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/dlm_plock.h.html -.. _`linux/fdreg.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/fdreg.h.html -.. _`linux/affs_hardblocks.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/affs_hardblocks.h.html -.. _`linux/stat.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/stat.h.html -.. _`linux/binfmts.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/binfmts.h.html -.. _`linux/neighbour.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/neighbour.h.html -.. _`linux/if_slip.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_slip.h.html -.. _`linux/pci_regs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/pci_regs.h.html -.. _`linux/isdn_ppp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/isdn_ppp.h.html -.. _`linux/fiemap.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/fiemap.h.html -.. _`linux/virtio_rng.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/virtio_rng.h.html -.. _`linux/nfs4.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/nfs4.h.html -.. _`linux/acct.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/acct.h.html -.. _`linux/elfcore.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/elfcore.h.html -.. _`linux/perf_event.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/perf_event.h.html -.. _`linux/virtio_ring.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/virtio_ring.h.html -.. _`linux/nubus.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/nubus.h.html -.. _`linux/fcntl.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/fcntl.h.html -.. _`linux/net.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/net.h.html -.. _`linux/adb.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/adb.h.html -.. _`linux/msdos_fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/msdos_fs.h.html -.. _`linux/prctl.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/prctl.h.html -.. _`linux/aio_abi.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/aio_abi.h.html -.. _`linux/random.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/random.h.html -.. _`linux/auto_fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/auto_fs.h.html -.. _`linux/firewire-cdev.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/firewire-cdev.h.html -.. _`linux/chio.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/chio.h.html -.. _`linux/if_bonding.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_bonding.h.html -.. _`linux/unistd.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/unistd.h.html -.. _`linux/irda.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/irda.h.html -.. _`linux/pmu.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/pmu.h.html -.. _`linux/suspend_ioctls.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/suspend_ioctls.h.html -.. _`linux/firewire-constants.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/firewire-constants.h.html -.. _`linux/pkt_cls.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/pkt_cls.h.html -.. _`linux/xattr.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/xattr.h.html -.. _`linux/dqblk_xfs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/dqblk_xfs.h.html -.. _`linux/igmp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/igmp.h.html -.. _`linux/if_vlan.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_vlan.h.html -.. _`linux/gen_stats.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/gen_stats.h.html -.. _`linux/errno.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/errno.h.html -.. _`linux/taskstats.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/taskstats.h.html -.. _`linux/stddef.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/stddef.h.html -.. _`linux/in_route.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/in_route.h.html -.. _`linux/signalfd.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/signalfd.h.html -.. _`linux/coda.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/coda.h.html -.. _`linux/pkt_sched.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/pkt_sched.h.html -.. _`linux/ipmi.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ipmi.h.html -.. _`linux/meye.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/meye.h.html -.. _`linux/efs_fs_sb.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/efs_fs_sb.h.html -.. _`linux/fadvise.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/fadvise.h.html -.. _`linux/a.out.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/a.out.h.html -.. _`linux/nfs_idmap.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/nfs_idmap.h.html -.. _`linux/dccp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/dccp.h.html -.. _`linux/dm-log-userspace.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/dm-log-userspace.h.html -.. _`linux/hidraw.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/hidraw.h.html -.. _`linux/ethtool.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ethtool.h.html -.. _`linux/uinput.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/uinput.h.html -.. _`linux/romfs_fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/romfs_fs.h.html -.. _`linux/timex.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/timex.h.html -.. _`linux/bpqether.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/bpqether.h.html -.. _`linux/cycx_cfm.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/cycx_cfm.h.html -.. _`linux/dlmconstants.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/dlmconstants.h.html -.. _`linux/mqueue.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/mqueue.h.html -.. _`linux/netdevice.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/netdevice.h.html -.. _`linux/llc.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/llc.h.html -.. _`linux/rose.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/rose.h.html -.. _`linux/coff.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/coff.h.html -.. _`linux/hayesesp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/hayesesp.h.html -.. _`linux/ip_vs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ip_vs.h.html -.. _`linux/cgroupstats.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/cgroupstats.h.html -.. _`linux/netlink.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/netlink.h.html -.. _`linux/netfilter_arp` : http://sites.uclouvain.be/SystInfo/usr/include/linux/netfilter_arp.html -.. _`linux/qnx4_fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/qnx4_fs.h.html -.. _`linux/ipx.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ipx.h.html -.. _`linux/connector.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/connector.h.html -.. _`linux/if_addrlabel.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_addrlabel.h.html -.. _`linux/inotify.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/inotify.h.html -.. _`linux/ncp_no.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ncp_no.h.html -.. _`linux/atmsvc.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atmsvc.h.html -.. _`linux/irqnr.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/irqnr.h.html -.. _`linux/sdla.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/sdla.h.html -.. _`linux/nvram.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/nvram.h.html -.. _`linux/videodev.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/videodev.h.html -.. _`linux/isdn` : http://sites.uclouvain.be/SystInfo/usr/include/linux/isdn.html -.. _`linux/icmpv6.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/icmpv6.h.html -.. _`linux/if_fc.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_fc.h.html -.. _`linux/if_infiniband.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_infiniband.h.html -.. _`linux/route.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/route.h.html -.. _`linux/ipv6_route.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ipv6_route.h.html -.. _`linux/toshiba.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/toshiba.h.html -.. _`linux/nfsd` : http://sites.uclouvain.be/SystInfo/usr/include/linux/nfsd.html -.. _`linux/usbdevice_fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/usbdevice_fs.h.html -.. _`linux/wanrouter.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/wanrouter.h.html -.. _`linux/reiserfs_xattr.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/reiserfs_xattr.h.html -.. _`linux/atmioc.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atmioc.h.html -.. _`linux/serio.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/serio.h.html -.. _`linux/falloc.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/falloc.h.html -.. _`linux/smb_fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/smb_fs.h.html -.. _`linux/fb.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/fb.h.html -.. _`linux/sched.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/sched.h.html -.. _`linux/string.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/string.h.html -.. _`linux/netrom.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/netrom.h.html -.. _`linux/uio.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/uio.h.html -.. _`linux/netfilter_bridge.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/netfilter_bridge.h.html -.. _`linux/serial_core.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/serial_core.h.html -.. _`linux/limits.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/limits.h.html -.. _`linux/if_frad.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_frad.h.html -.. _`linux/byteorder` : http://sites.uclouvain.be/SystInfo/usr/include/linux/byteorder.html -.. _`linux/virtio_pci.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/virtio_pci.h.html -.. _`linux/in6.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/in6.h.html -.. _`linux/pps.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/pps.h.html -.. _`linux/cuda.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/cuda.h.html -.. _`linux/ultrasound.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/ultrasound.h.html -.. _`linux/gameport.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/gameport.h.html -.. _`linux/if_cablemodem.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/if_cablemodem.h.html -.. _`linux/netfilter_ipv4.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/netfilter_ipv4.h.html -.. _`linux/flat.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/flat.h.html -.. _`linux/smb.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/smb.h.html -.. _`linux/fs.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/fs.h.html -.. _`linux/atalk.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/atalk.h.html -.. _`linux/udp.h` : http://sites.uclouvain.be/SystInfo/usr/include/linux/udp.h.html -.. _`netipx/ipx.h` : http://sites.uclouvain.be/SystInfo/usr/include/netipx/ipx.h.html -.. _`nfs/nfs.h` : http://sites.uclouvain.be/SystInfo/usr/include/nfs/nfs.h.html -.. _`netatalk/at.h` : http://sites.uclouvain.be/SystInfo/usr/include/netatalk/at.h.html -.. _`mtd/ubi-user.h` : http://sites.uclouvain.be/SystInfo/usr/include/mtd/ubi-user.h.html -.. _`mtd/inftl-user.h` : http://sites.uclouvain.be/SystInfo/usr/include/mtd/inftl-user.h.html -.. _`mtd/nftl-user.h` : http://sites.uclouvain.be/SystInfo/usr/include/mtd/nftl-user.h.html -.. _`mtd/mtd-user.h` : http://sites.uclouvain.be/SystInfo/usr/include/mtd/mtd-user.h.html -.. _`mtd/mtd-abi.h` : http://sites.uclouvain.be/SystInfo/usr/include/mtd/mtd-abi.h.html -.. _`arpa/ftp.h` : http://sites.uclouvain.be/SystInfo/usr/include/arpa/ftp.h.html -.. _`arpa/inet.h` : http://sites.uclouvain.be/SystInfo/usr/include/arpa/inet.h.html -.. _`arpa/nameser.h` : http://sites.uclouvain.be/SystInfo/usr/include/arpa/nameser.h.html -.. _`arpa/tftp.h` : http://sites.uclouvain.be/SystInfo/usr/include/arpa/tftp.h.html -.. _`arpa/telnet.h` : http://sites.uclouvain.be/SystInfo/usr/include/arpa/telnet.h.html -.. _`arpa/nameser_compat.h` : http://sites.uclouvain.be/SystInfo/usr/include/arpa/nameser_compat.h.html -.. _`c++/4.4` : http://sites.uclouvain.be/SystInfo/usr/include/c++/4.4.html -.. _`c++/4.4.5` : http://sites.uclouvain.be/SystInfo/usr/include/c++/4.4.5.html -.. _`netax25/ax25.h` : http://sites.uclouvain.be/SystInfo/usr/include/netax25/ax25.h.html -.. _`sys/vtimes.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/vtimes.h.html -.. _`sys/sem.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/sem.h.html -.. _`sys/mtio.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/mtio.h.html -.. _`sys/vm86.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/vm86.h.html -.. _`sys/user.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/user.h.html -.. _`sys/epoll.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/epoll.h.html -.. _`sys/reg.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/reg.h.html -.. _`sys/vt.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/vt.h.html -.. _`sys/sysctl.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/sysctl.h.html -.. _`sys/msg.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/msg.h.html -.. _`sys/gmon_out.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/gmon_out.h.html -.. _`sys/syscall.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/syscall.h.html -.. _`sys/socket.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/socket.h.html -.. _`sys/timerfd.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/timerfd.h.html -.. _`sys/ptrace.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/ptrace.h.html -.. _`sys/quota.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/quota.h.html -.. _`sys/sysmacros.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/sysmacros.h.html -.. _`sys/io.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/io.h.html -.. _`sys/cdefs.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/cdefs.h.html -.. _`sys/types.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/types.h.html -.. _`sys/time.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/time.h.html -.. _`sys/ttychars.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/ttychars.h.html -.. _`sys/resource.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/resource.h.html -.. _`sys/soundcard.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/soundcard.h.html -.. _`sys/param.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/param.h.html -.. _`sys/timeb.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/timeb.h.html -.. _`sys/debugreg.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/debugreg.h.html -.. _`sys/socketvar.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/socketvar.h.html -.. _`sys/un.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/un.h.html -.. _`sys/sysinfo.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/sysinfo.h.html -.. _`sys/statfs.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/statfs.h.html -.. _`sys/ioctl.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/ioctl.h.html -.. _`sys/kd.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/kd.h.html -.. _`sys/ttydefaults.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/ttydefaults.h.html -.. _`sys/utsname.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/utsname.h.html -.. _`sys/bitypes.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/bitypes.h.html -.. _`sys/termios.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/termios.h.html -.. _`sys/kdaemon.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/kdaemon.h.html -.. _`sys/elf.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/elf.h.html -.. _`sys/klog.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/klog.h.html -.. _`sys/mount.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/mount.h.html -.. _`sys/raw.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/raw.h.html -.. _`sys/mman.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/mman.h.html -.. _`sys/sendfile.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/sendfile.h.html -.. _`sys/procfs.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/procfs.h.html -.. _`sys/ucontext.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/ucontext.h.html -.. _`sys/times.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/times.h.html -.. _`sys/swap.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/swap.h.html -.. _`sys/pci.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/pci.h.html -.. _`sys/shm.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/shm.h.html -.. _`sys/ipc.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/ipc.h.html -.. _`sys/fsuid.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/fsuid.h.html -.. _`sys/profil.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/profil.h.html -.. _`sys/signal.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/signal.h.html -.. _`sys/reboot.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/reboot.h.html -.. _`sys/perm.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/perm.h.html -.. _`sys/queue.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/queue.h.html -.. _`sys/syslog.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/syslog.h.html -.. _`sys/wait.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/wait.h.html -.. _`sys/dir.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/dir.h.html -.. _`sys/vlimit.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/vlimit.h.html -.. _`sys/poll.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/poll.h.html -.. _`sys/personality.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/personality.h.html -.. _`sys/ustat.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/ustat.h.html -.. _`sys/statvfs.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/statvfs.h.html -.. _`sys/gmon.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/gmon.h.html -.. _`sys/stat.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/stat.h.html -.. _`sys/vfs.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/vfs.h.html -.. _`sys/acct.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/acct.h.html -.. _`sys/fcntl.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/fcntl.h.html -.. _`sys/prctl.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/prctl.h.html -.. _`sys/unistd.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/unistd.h.html -.. _`sys/xattr.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/xattr.h.html -.. _`sys/errno.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/errno.h.html -.. _`sys/eventfd.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/eventfd.h.html -.. _`sys/signalfd.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/signalfd.h.html -.. _`sys/select.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/select.h.html -.. _`sys/timex.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/timex.h.html -.. _`sys/inotify.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/inotify.h.html -.. _`sys/file.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/file.h.html -.. _`sys/uio.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/uio.h.html -.. _`sys/ultrasound.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/ultrasound.h.html -.. _`sys/stropts.h` : http://sites.uclouvain.be/SystInfo/usr/include/sys/stropts.h.html -.. _`asm-generic/setup.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/setup.h.html -.. _`asm-generic/mman-common.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/mman-common.h.html -.. _`asm-generic/shmparam.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/shmparam.h.html -.. _`asm-generic/ioctls.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/ioctls.h.html -.. _`asm-generic/socket.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/socket.h.html -.. _`asm-generic/swab.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/swab.h.html -.. _`asm-generic/types.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/types.h.html -.. _`asm-generic/resource.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/resource.h.html -.. _`asm-generic/param.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/param.h.html -.. _`asm-generic/signal-defs.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/signal-defs.h.html -.. _`asm-generic/auxvec.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/auxvec.h.html -.. _`asm-generic/statfs.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/statfs.h.html -.. _`asm-generic/ioctl.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/ioctl.h.html -.. _`asm-generic/siginfo.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/siginfo.h.html -.. _`asm-generic/termios.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/termios.h.html -.. _`asm-generic/posix_types.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/posix_types.h.html -.. _`asm-generic/int-ll64.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/int-ll64.h.html -.. _`asm-generic/mman.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/mman.h.html -.. _`asm-generic/ucontext.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/ucontext.h.html -.. _`asm-generic/bitsperlong.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/bitsperlong.h.html -.. _`asm-generic/sockios.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/sockios.h.html -.. _`asm-generic/int-l64.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/int-l64.h.html -.. _`asm-generic/signal.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/signal.h.html -.. _`asm-generic/ipcbuf.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/ipcbuf.h.html -.. _`asm-generic/poll.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/poll.h.html -.. _`asm-generic/sembuf.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/sembuf.h.html -.. _`asm-generic/msgbuf.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/msgbuf.h.html -.. _`asm-generic/stat.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/stat.h.html -.. _`asm-generic/fcntl.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/fcntl.h.html -.. _`asm-generic/unistd.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/unistd.h.html -.. _`asm-generic/errno.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/errno.h.html -.. _`asm-generic/errno-base.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/errno-base.h.html -.. _`asm-generic/shmbuf.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/shmbuf.h.html -.. _`asm-generic/termbits.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm-generic/termbits.h.html -.. _`gnu/stubs-32.h` : http://sites.uclouvain.be/SystInfo/usr/include/gnu/stubs-32.h.html -.. _`gnu/option-groups.h` : http://sites.uclouvain.be/SystInfo/usr/include/gnu/option-groups.h.html -.. _`gnu/lib-names.h` : http://sites.uclouvain.be/SystInfo/usr/include/gnu/lib-names.h.html -.. _`gnu/libc-version.h` : http://sites.uclouvain.be/SystInfo/usr/include/gnu/libc-version.h.html -.. _`gnu/stubs-64.h` : http://sites.uclouvain.be/SystInfo/usr/include/gnu/stubs-64.h.html -.. _`gnu/stubs.h` : http://sites.uclouvain.be/SystInfo/usr/include/gnu/stubs.h.html -.. _`netrom/netrom.h` : http://sites.uclouvain.be/SystInfo/usr/include/netrom/netrom.h.html -.. _`video/edid.h` : http://sites.uclouvain.be/SystInfo/usr/include/video/edid.h.html -.. _`video/uvesafb.h` : http://sites.uclouvain.be/SystInfo/usr/include/video/uvesafb.h.html -.. _`video/sisfb.h` : http://sites.uclouvain.be/SystInfo/usr/include/video/sisfb.h.html -.. _`net/ethernet.h` : http://sites.uclouvain.be/SystInfo/usr/include/net/ethernet.h.html -.. _`net/if_arp.h` : http://sites.uclouvain.be/SystInfo/usr/include/net/if_arp.h.html -.. _`net/if.h` : http://sites.uclouvain.be/SystInfo/usr/include/net/if.h.html -.. _`net/if_packet.h` : http://sites.uclouvain.be/SystInfo/usr/include/net/if_packet.h.html -.. _`net/ppp_defs.h` : http://sites.uclouvain.be/SystInfo/usr/include/net/ppp_defs.h.html -.. _`net/ppp-comp.h` : http://sites.uclouvain.be/SystInfo/usr/include/net/ppp-comp.h.html -.. _`net/if_ppp.h` : http://sites.uclouvain.be/SystInfo/usr/include/net/if_ppp.h.html -.. _`net/if_slip.h` : http://sites.uclouvain.be/SystInfo/usr/include/net/if_slip.h.html -.. _`net/if_shaper.h` : http://sites.uclouvain.be/SystInfo/usr/include/net/if_shaper.h.html -.. _`net/route.h` : http://sites.uclouvain.be/SystInfo/usr/include/net/route.h.html -.. _`netash/ash.h` : http://sites.uclouvain.be/SystInfo/usr/include/netash/ash.h.html -.. _`asm/setup.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/setup.h.html -.. _`asm/vm86.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/vm86.h.html -.. _`asm/unistd_64.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/unistd_64.h.html -.. _`asm/vsyscall.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/vsyscall.h.html -.. _`asm/kvm_para.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/kvm_para.h.html -.. _`asm/ioctls.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/ioctls.h.html -.. _`asm/bootparam.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/bootparam.h.html -.. _`asm/socket.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/socket.h.html -.. _`asm/ptrace.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/ptrace.h.html -.. _`asm/mtrr.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/mtrr.h.html -.. _`asm/swab.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/swab.h.html -.. _`asm/types.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/types.h.html -.. _`asm/ptrace-abi.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/ptrace-abi.h.html -.. _`asm/resource.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/resource.h.html -.. _`asm/param.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/param.h.html -.. _`asm/debugreg.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/debugreg.h.html -.. _`asm/auxvec.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/auxvec.h.html -.. _`asm/statfs.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/statfs.h.html -.. _`asm/byteorder.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/byteorder.h.html -.. _`asm/ioctl.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/ioctl.h.html -.. _`asm/siginfo.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/siginfo.h.html -.. _`asm/termios.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/termios.h.html -.. _`asm/ist.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/ist.h.html -.. _`asm/posix_types.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/posix_types.h.html -.. _`asm/mce.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/mce.h.html -.. _`asm/mman.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/mman.h.html -.. _`asm/ucontext.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/ucontext.h.html -.. _`asm/bitsperlong.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/bitsperlong.h.html -.. _`asm/sockios.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/sockios.h.html -.. _`asm/kvm.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/kvm.h.html -.. _`asm/unistd_32.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/unistd_32.h.html -.. _`asm/posix_types_64.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/posix_types_64.h.html -.. _`asm/signal.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/signal.h.html -.. _`asm/sigcontext.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/sigcontext.h.html -.. _`asm/ipcbuf.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/ipcbuf.h.html -.. _`asm/msr.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/msr.h.html -.. _`asm/poll.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/poll.h.html -.. _`asm/sembuf.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/sembuf.h.html -.. _`asm/msgbuf.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/msgbuf.h.html -.. _`asm/stat.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/stat.h.html -.. _`asm/fcntl.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/fcntl.h.html -.. _`asm/e820.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/e820.h.html -.. _`asm/prctl.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/prctl.h.html -.. _`asm/unistd.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/unistd.h.html -.. _`asm/processor-flags.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/processor-flags.h.html -.. _`asm/errno.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/errno.h.html -.. _`asm/a.out.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/a.out.h.html -.. _`asm/shmbuf.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/shmbuf.h.html -.. _`asm/boot.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/boot.h.html -.. _`asm/termbits.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/termbits.h.html -.. _`asm/sigcontext32.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/sigcontext32.h.html -.. _`asm/ldt.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/ldt.h.html -.. _`asm/posix_types_32.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/posix_types_32.h.html -.. _`asm/msr-index.h` : http://sites.uclouvain.be/SystInfo/usr/include/asm/msr-index.h.html -.. _`scsi/sg.h` : http://sites.uclouvain.be/SystInfo/usr/include/scsi/sg.h.html -.. _`scsi/scsi_ioctl.h` : http://sites.uclouvain.be/SystInfo/usr/include/scsi/scsi_ioctl.h.html -.. _`scsi/scsi.h` : http://sites.uclouvain.be/SystInfo/usr/include/scsi/scsi.h.html -.. _`protocols/timed.h` : http://sites.uclouvain.be/SystInfo/usr/include/protocols/timed.h.html -.. _`protocols/rwhod.h` : http://sites.uclouvain.be/SystInfo/usr/include/protocols/rwhod.h.html -.. _`protocols/talkd.h` : http://sites.uclouvain.be/SystInfo/usr/include/protocols/talkd.h.html -.. _`protocols/routed.h` : http://sites.uclouvain.be/SystInfo/usr/include/protocols/routed.h.html -.. _`neteconet/ec.h` : http://sites.uclouvain.be/SystInfo/usr/include/neteconet/ec.h.html -.. _`netinet/in.h` : http://sites.uclouvain.be/SystInfo/usr/include/netinet/in.h.html -.. _`netinet/ip.h` : http://sites.uclouvain.be/SystInfo/usr/include/netinet/ip.h.html -.. _`netinet/ip_icmp.h` : http://sites.uclouvain.be/SystInfo/usr/include/netinet/ip_icmp.h.html -.. _`netinet/tcp.h` : http://sites.uclouvain.be/SystInfo/usr/include/netinet/tcp.h.html -.. _`netinet/ether.h` : http://sites.uclouvain.be/SystInfo/usr/include/netinet/ether.h.html -.. _`netinet/ip6.h` : http://sites.uclouvain.be/SystInfo/usr/include/netinet/ip6.h.html -.. _`netinet/in_systm.h` : http://sites.uclouvain.be/SystInfo/usr/include/netinet/in_systm.h.html -.. _`netinet/if_ether.h` : http://sites.uclouvain.be/SystInfo/usr/include/netinet/if_ether.h.html -.. _`netinet/icmp6.h` : http://sites.uclouvain.be/SystInfo/usr/include/netinet/icmp6.h.html -.. _`netinet/if_fddi.h` : http://sites.uclouvain.be/SystInfo/usr/include/netinet/if_fddi.h.html -.. _`netinet/if_tr.h` : http://sites.uclouvain.be/SystInfo/usr/include/netinet/if_tr.h.html -.. _`netinet/igmp.h` : http://sites.uclouvain.be/SystInfo/usr/include/netinet/igmp.h.html -.. _`netinet/udp.h` : http://sites.uclouvain.be/SystInfo/usr/include/netinet/udp.h.html -.. _`netiucv/iucv.h` : http://sites.uclouvain.be/SystInfo/usr/include/netiucv/iucv.h.html -.. _`rpcsvc/ypclnt.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/ypclnt.h.html -.. _`rpcsvc/key_prot.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/key_prot.h.html -.. _`rpcsvc/bootparam.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/bootparam.h.html -.. _`rpcsvc/nlm_prot.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/nlm_prot.h.html -.. _`rpcsvc/spray.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/spray.x.html -.. _`rpcsvc/nis_object.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/nis_object.x.html -.. _`rpcsvc/nfs_prot.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/nfs_prot.x.html -.. _`rpcsvc/bootparam_prot.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/bootparam_prot.x.html -.. _`rpcsvc/yp.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/yp.h.html -.. _`rpcsvc/rstat.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/rstat.x.html -.. _`rpcsvc/klm_prot.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/klm_prot.x.html -.. _`rpcsvc/nfs_prot.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/nfs_prot.h.html -.. _`rpcsvc/nlm_prot.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/nlm_prot.x.html -.. _`rpcsvc/klm_prot.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/klm_prot.h.html -.. _`rpcsvc/rstat.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/rstat.h.html -.. _`rpcsvc/mount.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/mount.h.html -.. _`rpcsvc/yppasswd.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/yppasswd.h.html -.. _`rpcsvc/spray.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/spray.h.html -.. _`rpcsvc/bootparam_prot.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/bootparam_prot.h.html -.. _`rpcsvc/rex.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/rex.x.html -.. _`rpcsvc/key_prot.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/key_prot.x.html -.. _`rpcsvc/nis_callback.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/nis_callback.h.html -.. _`rpcsvc/mount.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/mount.x.html -.. _`rpcsvc/yppasswd.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/yppasswd.x.html -.. _`rpcsvc/nislib.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/nislib.h.html -.. _`rpcsvc/sm_inter.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/sm_inter.x.html -.. _`rpcsvc/nis_tags.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/nis_tags.h.html -.. _`rpcsvc/nis_callback.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/nis_callback.x.html -.. _`rpcsvc/rex.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/rex.h.html -.. _`rpcsvc/rquota.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/rquota.x.html -.. _`rpcsvc/rusers.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/rusers.x.html -.. _`rpcsvc/yp.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/yp.x.html -.. _`rpcsvc/nis.x` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/nis.x.html -.. _`rpcsvc/rusers.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/rusers.h.html -.. _`rpcsvc/sm_inter.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/sm_inter.h.html -.. _`rpcsvc/yp_prot.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/yp_prot.h.html -.. _`rpcsvc/ypupd.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/ypupd.h.html -.. _`rpcsvc/rquota.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/rquota.h.html -.. _`rpcsvc/nis.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpcsvc/nis.h.html -.. _`netpacket/packet.h` : http://sites.uclouvain.be/SystInfo/usr/include/netpacket/packet.h.html -.. _`netrose/rose.h` : http://sites.uclouvain.be/SystInfo/usr/include/netrose/rose.h.html -.. _`bits/initspin.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/initspin.h.html -.. _`bits/sem.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/sem.h.html -.. _`bits/syslog-ldbl.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/syslog-ldbl.h.html -.. _`bits/stdio2.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/stdio2.h.html -.. _`bits/wchar2.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/wchar2.h.html -.. _`bits/mathinline.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/mathinline.h.html -.. _`bits/link.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/link.h.html -.. _`bits/in.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/in.h.html -.. _`bits/sigstack.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/sigstack.h.html -.. _`bits/inf.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/inf.h.html -.. _`bits/waitstatus.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/waitstatus.h.html -.. _`bits/locale.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/locale.h.html -.. _`bits/ioctls.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/ioctls.h.html -.. _`bits/syscall.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/syscall.h.html -.. _`bits/socket.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/socket.h.html -.. _`bits/dirent.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/dirent.h.html -.. _`bits/sigthread.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/sigthread.h.html -.. _`bits/elfclass.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/elfclass.h.html -.. _`bits/types.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/types.h.html -.. _`bits/byteswap.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/byteswap.h.html -.. _`bits/time.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/time.h.html -.. _`bits/resource.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/resource.h.html -.. _`bits/libc-lock.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/libc-lock.h.html -.. _`bits/stdio-ldbl.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/stdio-ldbl.h.html -.. _`bits/mathcalls.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/mathcalls.h.html -.. _`bits/wordsize.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/wordsize.h.html -.. _`bits/predefs.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/predefs.h.html -.. _`bits/sockaddr.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/sockaddr.h.html -.. _`bits/mqueue2.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/mqueue2.h.html -.. _`bits/wchar.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/wchar.h.html -.. _`bits/local_lim.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/local_lim.h.html -.. _`bits/netdb.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/netdb.h.html -.. _`bits/fenvinline.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/fenvinline.h.html -.. _`bits/statfs.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/statfs.h.html -.. _`bits/posix1_lim.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/posix1_lim.h.html -.. _`bits/monetary-ldbl.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/monetary-ldbl.h.html -.. _`bits/semaphore.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/semaphore.h.html -.. _`bits/xtitypes.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/xtitypes.h.html -.. _`bits/ipctypes.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/ipctypes.h.html -.. _`bits/waitflags.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/waitflags.h.html -.. _`bits/utsname.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/utsname.h.html -.. _`bits/siginfo.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/siginfo.h.html -.. _`bits/cmathcalls.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/cmathcalls.h.html -.. _`bits/termios.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/termios.h.html -.. _`bits/stdio.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/stdio.h.html -.. _`bits/error.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/error.h.html -.. _`bits/ioctl-types.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/ioctl-types.h.html -.. _`bits/posix2_lim.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/posix2_lim.h.html -.. _`bits/huge_valf.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/huge_valf.h.html -.. _`bits/mman.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/mman.h.html -.. _`bits/dlfcn.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/dlfcn.h.html -.. _`bits/setjmp.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/setjmp.h.html -.. _`bits/fcntl2.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/fcntl2.h.html -.. _`bits/sys_errlist.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/sys_errlist.h.html -.. _`bits/stdlib-ldbl.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/stdlib-ldbl.h.html -.. _`bits/xopen_lim.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/xopen_lim.h.html -.. _`bits/shm.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/shm.h.html -.. _`bits/ipc.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/ipc.h.html -.. _`bits/printf-ldbl.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/printf-ldbl.h.html -.. _`bits/stdlib.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/stdlib.h.html -.. _`bits/huge_vall.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/huge_vall.h.html -.. _`bits/sigcontext.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/sigcontext.h.html -.. _`bits/syslog.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/syslog.h.html -.. _`bits/huge_val.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/huge_val.h.html -.. _`bits/pthreadtypes.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/pthreadtypes.h.html -.. _`bits/mathdef.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/mathdef.h.html -.. _`bits/typesizes.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/typesizes.h.html -.. _`bits/poll.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/poll.h.html -.. _`bits/ustat.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/ustat.h.html -.. _`bits/posix_opt.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/posix_opt.h.html -.. _`bits/setjmp2.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/setjmp2.h.html -.. _`bits/statvfs.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/statvfs.h.html -.. _`bits/string3.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/string3.h.html -.. _`bits/stat.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/stat.h.html -.. _`bits/confname.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/confname.h.html -.. _`bits/string2.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/string2.h.html -.. _`bits/fcntl.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/fcntl.h.html -.. _`bits/syslog-path.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/syslog-path.h.html -.. _`bits/libio-ldbl.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/libio-ldbl.h.html -.. _`bits/utmp.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/utmp.h.html -.. _`bits/unistd.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/unistd.h.html -.. _`bits/sigaction.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/sigaction.h.html -.. _`bits/fenv.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/fenv.h.html -.. _`bits/sigset.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/sigset.h.html -.. _`bits/msq.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/msq.h.html -.. _`bits/nan.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/nan.h.html -.. _`bits/errno.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/errno.h.html -.. _`bits/a.out.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/a.out.h.html -.. _`bits/select.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/select.h.html -.. _`bits/stdio_lim.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/stdio_lim.h.html -.. _`bits/utmpx.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/utmpx.h.html -.. _`bits/socket2.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/socket2.h.html -.. _`bits/mqueue.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/mqueue.h.html -.. _`bits/environments.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/environments.h.html -.. _`bits/endian.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/endian.h.html -.. _`bits/stdio-lock.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/stdio-lock.h.html -.. _`bits/wchar-ldbl.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/wchar-ldbl.h.html -.. _`bits/stab.def` : http://sites.uclouvain.be/SystInfo/usr/include/bits/stab.def.html -.. _`bits/signum.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/signum.h.html -.. _`bits/sched.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/sched.h.html -.. _`bits/string.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/string.h.html -.. _`bits/uio.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/uio.h.html -.. _`bits/stropts.h` : http://sites.uclouvain.be/SystInfo/usr/include/bits/stropts.h.html -.. _`rpc/rpc_des.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/rpc_des.h.html -.. _`rpc/xdr.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/xdr.h.html -.. _`rpc/key_prot.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/key_prot.h.html -.. _`rpc/pmap_prot.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/pmap_prot.h.html -.. _`rpc/types.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/types.h.html -.. _`rpc/pmap_clnt.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/pmap_clnt.h.html -.. _`rpc/auth.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/auth.h.html -.. _`rpc/netdb.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/netdb.h.html -.. _`rpc/pmap_rmt.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/pmap_rmt.h.html -.. _`rpc/svc_auth.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/svc_auth.h.html -.. _`rpc/svc.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/svc.h.html -.. _`rpc/rpc.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/rpc.h.html -.. _`rpc/auth_unix.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/auth_unix.h.html -.. _`rpc/des_crypt.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/des_crypt.h.html -.. _`rpc/clnt.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/clnt.h.html -.. _`rpc/rpc_msg.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/rpc_msg.h.html -.. _`rpc/auth_des.h` : http://sites.uclouvain.be/SystInfo/usr/include/rpc/auth_des.h.html -.. _`sound/sb16_csp.h` : http://sites.uclouvain.be/SystInfo/usr/include/sound/sb16_csp.h.html -.. _`sound/emu10k1.h` : http://sites.uclouvain.be/SystInfo/usr/include/sound/emu10k1.h.html -.. _`sound/asound_fm.h` : http://sites.uclouvain.be/SystInfo/usr/include/sound/asound_fm.h.html -.. _`sound/asequencer.h` : http://sites.uclouvain.be/SystInfo/usr/include/sound/asequencer.h.html -.. _`sound/sfnt_info.h` : http://sites.uclouvain.be/SystInfo/usr/include/sound/sfnt_info.h.html -.. _`sound/asound.h` : http://sites.uclouvain.be/SystInfo/usr/include/sound/asound.h.html -.. _`sound/sscape_ioctl.h` : http://sites.uclouvain.be/SystInfo/usr/include/sound/sscape_ioctl.h.html -.. _`sound/hdspm.h` : http://sites.uclouvain.be/SystInfo/usr/include/sound/hdspm.h.html -.. _`sound/hdsp.h` : http://sites.uclouvain.be/SystInfo/usr/include/sound/hdsp.h.html -.. _`rdma/ib_user_mad.h` : http://sites.uclouvain.be/SystInfo/usr/include/rdma/ib_user_mad.h.html diff --git a/Theorie/index.rst b/Theorie/index.rst deleted file mode 100644 index 96b2f00c9d89ef5caa334c72e6f5b8f7237d4b1d..0000000000000000000000000000000000000000 --- a/Theorie/index.rst +++ /dev/null @@ -1,73 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012-2014 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -###################### -Systèmes informatiques -###################### - - -.. only:: html - - Ce site web contient la partie théorique du support du cours `Projet P3 - LEPL1503 <https://uclouvain.be/cours-2019-lepl1503>`_ donné aux `étudiants ingénieurs et informaticiens <http://www.uclouvain.be/info.html>`_ à l'`Université catholique de Louvain <https://www.uclouvain.be>`_ (UCL). Les étudiants sont invités à ajouter leur commentaires en soumettant des patches via https://github.com/UCL-INGI/SyllabusC . - - La version HTML est la préférable car elle contient des liens hypertextes vers les pages de manuel Linux qui font partie de la matière. D'autres formats sont possibles pour ceux qui veulent lire le document hors ligne : - - - `format epub <http://sites.uclouvain.be/SystInfo/distrib/SINF1252-Theorie.epub>`_ lisible sur tablettes style iPad ou Galaxy Tab - - `format pdf <http://sites.uclouvain.be/SystInfo/distrib/SINF1252-Theorie.pdf>`_ pour lecture via les logiciels Adobe ou pour impression - - - - -Introduction -************* -.. toctree:: - :maxdepth: 2 - - intro - -Langage C -********* - -.. toctree:: - :maxdepth: 2 - - C/intro-C - C/datatypes - C/malloc - C/linker - - - - - -Systèmes Multiprocesseurs -************************* -.. toctree:: - :maxdepth: 2 - - Threads/threads - Threads/threads2 - Threads/coordination -.. Threads/processus - - -Gestion des fichiers -******************** - -.. toctree:: - :maxdepth: 2 - - Fichiers/fichiers - -******* -Annexes -******* - -.. toctree:: - :maxdepth: 2 - - bib - glossaire - diff --git a/Theorie/intro.rst b/Theorie/intro.rst deleted file mode 100644 index 35447f806416385630297c75099f0e1639b6b6eb..0000000000000000000000000000000000000000 --- a/Theorie/intro.rst +++ /dev/null @@ -1,248 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012, 2019 by `Olivier Bonaventure <http://perso.uclouvain.be/olivier.bonaventure>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - -Introduction -============ - - -Les systèmes informatiques jouent un rôle de plus en plus important dans notre société. Depuis les premiers calculateurs à la fin de la seconde guerre mondiale, les ordinateurs se sont rapidement améliorés et démocratisés. Aujourd'hui, notre société est de plus en plus dépendante des systèmes informatiques. - -.. spelling:: - - Von Neumann - binary - digit - word - -Composition d'un système informatique -------------------------------------- - -Le système informatique le plus simple est composé d'un :term:`processeur` (:term:`CPU` en anglais) ou unité de calcul et d'une mémoire. Le processeur est un circuit électronique qui est capable d'effectuer de nombreuses tâches : - - - lire de l'information en mémoire - - écrire de l'information en mémoire - - réaliser des calculs - -L'architecture des ordinateurs est basée sur l'architecture dite de Von Neumann. Suivant cette architecture, un ordinateur est composé d'un processeur qui exécute un programme se trouvant en mémoire. La mémoire contient à la fois le programme à exécuter et les données qui sont manipulées par le programme. - -L'élément de base pour stocker et représenter de l'information dans un système informatique est le :term:`bit`. Un bit (`binary digit` en anglais) peut prendre deux valeurs qui par convention sont représentées par : - - - ``1`` - - ``0`` - -Physiquement, un bit est représenté sous la forme d'un signal électrique ou optique lorsqu'il est transmis et d'une charge électrique ou sous forme magnétique lorsqu'il est stocké. Nous n'aborderons pas ces détails technologiques dans le cadre de ce cours. Ils font l'objet de nombreux cours d'électronique. - -Le bit est l'unité de base de stockage et de transfert de l'information. En général, les systèmes informatiques ne traitent pas des bits individuellement [#fbitreseau]_. - -La composition de plusieurs bits donne lieu à des blocs de données qui -peuvent être utiles dans différentes applications -informatiques. Ainsi, un :term:`nibble` est un bloc de 4 bits -consécutifs tandis qu'un :term:`octet` (ou :term:`byte` en anglais) -est un bloc de 8 bits consécutifs. On parlera de mots (`word` en -anglais) pour des groupes comprenant généralement 32 bits et de long -mot pour des groupes de 64 bits. - -Le processeur et la mémoire ne sont pas les deux seuls composants d'un système informatique. Celui-ci doit également pouvoir interagir avec le monde extérieur, ne fut-ce que pour pouvoir charger le programme à exécuter et les données à analyser. Cette interaction se réalise grâce à un grand nombre de dispositifs d'entrées/sorties et de stockage. Parmi ceux-ci, on peut citer : - - - le clavier qui permet à l'utilisateur d'entrer des caractères - - l'écran qui permet à l'utilisateur de visualiser le fonctionnement des programmes et les résultats qu'ils produisent - - l'imprimante qui permet à l'ordinateur d'écrire sur papier les résultats de l'exécution de programmes - - le disque-dur, les clés USB, les CDs et DVDs qui permettent de stocker les données sous la forme de fichiers et de répertoires - - la souris ou la tablette graphique qui permettent à l'utilisateur de fournir à l'ordinateur des indications de positionnement - - le scanner qui permet à l'ordinateur de transformer un document en une image numérique - - le haut-parleur avec lequel l'ordinateur peut diffuser différentes sortes de son - - le microphone et la caméra qui permettent à l'ordinateur de capturer des informations sonores et visuelles pour les stocker ou les traiter - -.. spelling:: - - API - l'API - Bell - Laboratories - AT&T - Berkeley - Labs - Amsterdam - d'Amsterdam - -Unix ----- - -Unix est aujourd'hui un nom générique [#funix]_ correspondant à une famille de systèmes d'exploitation. La première version de Unix a été développée pour faciliter le traitement de documents sur mini-ordinateur. - -.. topic:: Quelques variantes de Unix - - De nombreuses variantes de Unix ont été produites durant les quarante dernières années. Il est impossible de les décrire toutes, mais en voici quelques unes. - - - :term:`Unix`. Initialement développé aux AT&T Bell Laboratories, Unix a été ensuite développé par d'autres entreprises. C'est aujourd'hui une marque déposée par ``The Open group``, voir http://www.unix.org/ - - :term:`BSD Unix`. Les premières versions de Unix étaient librement distribuées par Bell Labs. Avec le temps, des variantes de Unix sont apparues. La variante développée par l'université de Berkeley en Californie a été historiquement importante car c'est dans cette variante que de nombreuses innovations ont été introduites dont notamment les piles de protocoles TCP/IP utilisés sur Internet. Aujourd'hui, :term:`FreeBSD` et :term:`OpenBSD` sont deux descendants de :term:`BSD Unix`. Ils sont largement utilisés dans de nombreux serveurs et systèmes embarqués. :term:`MacOS`, développé par Apple, s'appuie fortement sur un noyau et des utilitaires provenant de :term:`FreeBSD`. - - :term:`Minix` est un système d'exploitation développé initialement par :term:`Andrew Tanenbaum` à l'université d'Amsterdam. :term:`Minix` est fréquemment utilisé pour l'apprentissage du fonctionnement des systèmes d'exploitation. - - :term:`Linux` est un noyau de système d'exploitation largement inspiré de :term:`Unix` et `Minix`. Développé par :term:`Linus Torvalds` durant ses études d'informatique, il est devenu la variante de Unix la plus utilisée à travers le monde. Il est maintenant développé par des centaines de développeurs qui collaborent via Internet. - - :term:`Solaris` est le nom commercial de la variante Unix de Oracle. - - Dans le cadre de ce cours, nous nous focaliserons sur le système :term:`GNU/Linux`, c'est-à -dire un système qui intègre le noyau :term:`Linux` et les librairies et utilitaires développés par le projet :term:`GNU` de la :term:`FSF`. - -Un système Unix est composé de trois grands types de logiciels : - - - Le noyau du système d'exploitation qui est chargé automatiquement au démarrage de la machine et qui prend en charge toutes les interactions entre les logiciels et le matériel. - - De nombreuses librairies qui facilitent l'écriture et le développement d'applications - - De nombreux programmes utilitaires simples qui permettent de résoudre un grand nombre de problèmes courants. Certains de ces utilitaires sont chargés automatiquement lors du démarrage de la machine. La plupart sont exécutés uniquement à la demande des utilisateurs. - -.. spelling:: - - API - programmatiques - Application - Programming - Interface - -Le rôle principal du noyau du système d'exploitation est de gérer les ressources matérielles (processeur, mémoire, dispositifs d'entrées/sorties et de stockage) de façon à ce qu'elles soient accessibles à toutes les applications qui s'exécutent sur le système. Gérer les ressources matérielles nécessite d'inclure dans le systèmes d'exploitation des interfaces programmatiques (`Application Programming Interfaces` en anglais - :term:`API`) qui facilitent leur utilisation par les applications. Les dispositifs de stockage sont une belle illustration de ce principe. Il existe de nombreux dispositifs de stockage (disque dur, clé USB, CD, DVD, mémoire flash, ...). Chacun de ces dispositifs a des caractéristiques électriques et mécaniques propres. Ils permettent en général la lecture et/ou l'écriture de blocs de données de quelques centaines d'octets. Nous reviendrons sur leur fonctionnement ultérieurement. Peu d'applications sont capables de piloter directement de tels dispositifs pour y lire ou y écrire de tels blocs de données. Par contre, la majorité des applications sont capables de les utiliser par l'intermédiaire du système de fichiers. Le système de fichiers (arborescence des fichiers) et l'API associée (`open(2)`_, `close(2)`_, `read(2)`_ `write(2)`_ ) sont un exemple des services fournis par le système d'exploitation aux applications. Le système de fichiers regroupe l'ensemble des fichiers qui sont accessibles depuis un système sous une arborescence unique, quel que soit le nombre de dispositifs de stockage utilisé. La racine de cette arborescence est le répertoire ``/`` par convention. Ce répertoire contient généralement une dizaine de sous répertoires dont les noms varient d'une variante de Unix à l'autre. Généralement, on retrouve dans la racine les sous-répertoires suivants : - - - ``/usr`` : sous-répertoire contenant la plupart des utilitaires et librairies installées sur le système - - ``/bin`` et ``/sbin`` : sous-répertoire contenant quelques utilitaires de base nécessaires à l'administrateur du système - - ``/tmp`` : sous-répertoire contenant des fichiers temporaires. Son contenu est généralement effacé au redémarrage du système. - - ``/etc`` : sous-répertoire contenant les fichiers de configuration du système - - ``/home`` : sous-répertoire contenant les répertoires personnels des utilisateurs du système - - ``/dev`` : sous-répertoire contenant des fichiers spéciaux - - ``/root``: sous-répertoire contenant des fichiers propres à l'administrateur système. Dans certains variantes de Unix, ces fichiers sont stockés dans le répertoire racine. - -Un autre service est le partage de la mémoire et du processus. La plupart des systèmes d'exploitation supportent l'exécution simultanée de plusieurs applications. Pour ce faire, le système d'exploitation partage la mémoire disponible entre les différentes applications en cours d'exécution. Il est également responsable du partage du temps d'exécution sur le ou les processeurs de façon à ce que toutes les applications en cours puissent s'exécuter. - -Unix s'appuie sur la notion de processus. Une application est composée de un ou plusieurs processus. Un processus peut être défini comme un ensemble cohérent d'instructions qui utilisent une partie de la mémoire et sont exécutées sur un des processeurs du système. L'exécution d'un processus est initiée par le système d'exploitation (généralement suite à une requête faite par un autre processus). Un processus peut s'exécuter pendant une fraction de secondes, quelques secondes ou des journées entières. Pendant son exécution, le processus peut potentiellement accéder aux différentes ressources (processeurs, mémoire, dispositifs d'entrées/sorties et de stockage) du système. A la fin de son exécution, le processus se termine [#ftermine]_ et libère les ressources qui lui ont été allouées par le système d'exploitation. Sous Unix, tout processus retourne au processus qui l'avait initié le résultat de son exécution qui est résumée en un nombre entier. Cette valeur de retour est utilisée en général pour déterminer si l'exécution d'un processus s'est déroulée correctement (zéro comme valeur de retour) ou non (valeur de retour différente de zéro). - -Dans le cadre de ce cours, nous aurons l'occasion de voir en détails de nombreuses librairies d'un système Unix et verrons le fonctionnement d'appels systèmes qui permettent aux logiciels d'interagir directement avec le noyau. Le système Unix étant majoritairement écrit en langage C, ce langage est le langage de choix pour de nombreuses applications. Nous le verrons donc en détails. - - -Utilitaires -^^^^^^^^^^^ - -Unix a été conçu à l'époque des mini-ordinateurs. Un mini-ordinateur servait plusieurs utilisateurs en même temps. Ceux-ci y étaient connectés par l'intermédiaire d'un terminal équipé d'un écran et d'un clavier. Les programmes traitaient les données entrées par l'utilisateur via le clavier ou stockées sur le disque. Les résultats de l'exécution des ces programmes étaient affichés à l'écran, sauvegardés sur disque ou parfois imprimés sur papier. Le fonctionnement de nombreux utilitaires Unix a été influencé par cet environnement. A tout processus Unix, on associe : - - - une entrée standard (:term:`stdin` en anglais) qui est un flux d'informations par lequel le processus reçoit les données à traiter. Par défaut, l'entrée standard est associée au clavier. - - une sortie standard (:term:`stdout` en anglais) qui est un flux d'informations sur lequel le processus écrit le résultat de son traitement. Par défaut, la sortie standard est associée au terminal. - - une sortie d'erreur standard (:term:`stderr` en anglais) qui est un flux de données sur lequel le processus écrira les messages d'erreur éventuels. Par défaut, la sortie d'erreur standard est associée à l'écran. - -Unix ayant été initialement développé pour manipuler des documents contenant du texte, il comprend de nombreux utilitaires facilitant ces traitements. Une description détaillée de l'ensemble de ces utilitaires sort du cadre de ce cours. De nombreux livres et ressources Internet fournissent une description détaillée. Voici cependant une brève présentation de quelques utilitaires de manipulation de texte qui peuvent s'avérer très utiles en pratique. - - - `cat(1)`_ : utilitaire permettant notamment d'afficher le contenu d'un fichier sur la sortie standard - - `echo(1)`_ : utilitaire permettant d'afficher sur la sortie standard une chaîne de caractères passée en argument - - `head(1)`_ et `tail(1)`_ : utilitaires permettant respectivement d'extraire le début ou la fin d'un fichier - - `wc(1)`_ : utilitaire permettant de compter le nombre de caractères et de lignes d'un fichier - - `grep(1)`_ : utilitaire permettant notamment d'extraire d'un fichier texte les lignes qui contiennent ou ne contiennent pas une chaîne de caractères passée en argument - - `sort(1)`_ : utilitaire permettant de trier les lignes d'un fichier texte - - `uniq(1)`_ : utilitaire permettant de filtrer le contenu d'un fichier texte afin d'en extraire les lignes qui sont uniques ou dupliquées (requiert que le fichier d'entrée soit trié, car ne compare que les lignes consécutives) - - `more(1)`_ : utilitaire permettant d'afficher page par page un fichier texte sur la sortie standard (`less(1)`_ est une variante courante de `more(1)`_) - - `gzip(1)`_ et `gunzip(1)`_ : utilitaires permettant respectivement de compresser et de décompresser des fichiers. Les fichiers compressés prennent moins de place sur le disque que les fichiers standard et ont par convention un nom qui se termine par ``.gz``. - - `tar(1)`_ : utilitaire permettant de regrouper plusieurs fichiers dans une archive. Souvent utilisé en combinaison avec `gzip(1)`_ pour réaliser des backups ou distribuer des logiciels. - - `sed(1)`_ : utilitaire permettant d'éditer, c'est-à -dire de modifier les caractères présents dans un flux de données. - - `awk(1)`_ : utilitaire incluant un petit langage de programmation et qui permet d'écrire rapidement de nombreux programmes de manipulation de fichiers textes - -La plupart des utilitaires fournis avec un système Unix ont été conçus pour être utilisés en combinaison avec d'autres. Cette combinaison efficace de plusieurs petits utilitaires est un des points forts des systèmes Unix par rapport à d'autres systèmes d'exploitation. - - -Shell -^^^^^ - -Avant le développement des interfaces graphiques telles que :term:`X11`, :term:`Gnome` ou :term:`Aqua`, l'utilisateur interagissait exclusivement avec l'ordinateur par l'intermédiaire d'un interpréteur de commandes. Dans le monde Unix, le terme anglais :term:`shell` est le plus souvent utilisé pour désigner cet interpréteur et nous ferons de même. Avec les interfaces graphiques actuelles, le shell est accessible par l'intermédiaire d'une application qui est généralement appelée ``terminal`` ou ``console``. - -Un :term:`shell` est un programme qui a été spécialement conçu pour faciliter l'utilisation d'un système Unix via le clavier. De nombreux shells Unix existent. Les plus simples permettent à l'utilisateur de taper une série de commandes à exécuter en les combinant. Les plus avancés sont des interpréteurs de commandes qui supportent un langage complet permettant le développement de scripts plus ou moins ambitieux. Dans le cadre de ce cours, nous utiliserons `bash(1)`_ qui est un des shells les plus populaires et les plus complets. La plupart des commandes `bash(1)`_ que nous utiliserons sont cependant compatibles avec de nombreux autres shells tels que `zsh <http://www.zsh.org>`_ ou `csh <http://www.tcsh.org/Home>`_. - -Lorsqu'un utilisateur se connecte à un système Unix, en direct ou à travers une connexion réseau, le système vérifie son mot de passe puis exécute automatiquement le shell qui est associé à cet utilisateur depuis son répertoire par défaut. Ce shell permet à l'utilisateur d'exécuter et de combiner des commandes. Un shell supporte deux types de commande : les commandes internes qu'il implémente directement et les commandes externes qui font appel à un utilitaire stocké sur disque. Les utilitaires présentés dans la section précédente sont des exemples de commandes externes. Voici quelques exemples d'utilisation de commandes externes. - -.. literalinclude:: src/exemple.out - :language: console - -.. spelling:: - - -La puissance du :term:`shell` ne vient pas de sa capacité d'exécuter des commandes individuelles telles que ci-dessus. Elle vient de la possibilité de combiner ces commandes en redirigeant les entrées et sorties standards. Les shells Unix supportent différentes formes de redirection. Tout d'abord, il est possible de forcer un programme à lire son entrée standard depuis un fichier plutôt que depuis le clavier. Cela se fait en ajoutant à la fin de la ligne de commande le caractère ``<`` suivi du nom du fichier à lire. Ensuite, il est possible de rediriger la sortie standard vers un fichier. Cela se fait en utilisant ``>`` ou ``>>``. Lorsqu'une commande est suivie de ``> file``, le fichier ``file`` est créé si il n'existait pas et remis à zéro si il existait et la sortie standard de cette commande est redirigée vers le fichier ``file``. Lorsqu'un commande est suivie de ``>> file``, la sortie standard est sauvegardée à la fin du fichier ``file`` (si ``file`` n'existait pas, il est créé). Des informations plus complètes sur les mécanismes de redirection de `bash(1)`_ peuvent être obtenues dans le `chapitre 20 <http://tldp.org/LDP/abs/html/io-redirection.html>`_ de [ABS]_. - - - -.. literalinclude:: src/exemple2.out - :language: console - -Les shells Unix supportent un second mécanisme qui est encore plus intéressant pour combiner plusieurs programmes. Il s'agit de la redirection de la sortie standard d'un programme vers l'entrée standard d'un autre sans passer par un fichier intermédiaire. Cela se réalise avec le symbole ``|`` (:term:`pipe` en anglais). L'exemple suivant illustre quelques combinaisons d'utilitaires de manipulation de texte. - -.. literalinclude:: src/exemple3.out - :language: console - -Le premier exemple est d'utiliser `echo(1)`_ pour générer du texte et le passer directement à `wc(1)`_ qui compte le nombre de caractères. Le deuxième exemple utilise `cat(1)`_ pour afficher sur la sortie standard le contenu d'un fichier. Cette sortie est reliée à `sort(1)`_ qui trie le texte reçu sur son entrée standard en ordre alphabétique croissant. Cette sortie en ordre alphabétique est reliée à `uniq(1)`_ qui la filtre pour en retirer les lignes dupliquées. - - -Tout shell Unix peut également s'utiliser comme un interpréteur de commande qui permet d'interpréter des scripts. Un système Unix peut exécuter deux types de programmes : - - - des programmes exécutables en langage machine. C'est le cas de la plupart des utilitaires dont nous avons parlé jusqu'ici. - - des programmes écrits dans un langage interprété. C'est le cas des programmes écrits pour le shell, mais également pour d'autres langages interprétés comme python_ ou perl_. - -Lors de l'exécution d'un programme, le système d'exploitation reconnaît [#fexecbit]_ si il s'agit d'un programme directement exécutable ou d'un programme interprété en analysant les premiers octets du fichier. Par convention, sous Unix, les deux premiers caractères d'un programme écrit dans un langage qui doit être interprété sont ``#!``. Ils sont suivis par le nom complet de l'interpréteur qui doit être utilisé pour interpréter le programme. - -Le programme `bash(1)`_ le plus simple est le suivant : - -.. literalinclude:: src/hello.sh - :language: bash - -L'exécution de ce script shell retourne la sortie suivante : - -.. literalinclude:: src/hello.sh.out - :language: console - - -Par convention en `bash(1)`_, le caractère ``#`` marque le début d'un commentaire en début ou en cours de ligne. Comme tout langage, `bash(1)`_ permet à l'utilisateur de définir des variables. Celles-ci peuvent contenir des chaînes de caractères ou des nombres. Le script ci-dessous utilise deux variables, ``PROG`` et ``COURS`` et les utilise pour afficher un texte avec la commande ``echo``. - -.. literalinclude:: src/hellovar.sh - :language: bash - -Un script `bash(1)`_ peut également prendre des arguments passés en ligne de commande. Par convention, ceux-ci ont comme noms ``$1``, ``$2``, ``$3``, ... L'exemple ci-dessous illustre l'utilisation de ces arguments. - -.. literalinclude:: src/args.sh - :language: bash - -L'exécution de ce script produit la sortie suivante : - -.. literalinclude:: src/args.sh.out - :language: console - - -Concernant le traitement des arguments par un script bash, il est utile de noter que lorsque l'on appelle un script en redirigeant son entrée ou sa sortie standard, le script n'est pas informé de cette redirection. Ainsi, si l'on exécute le script précédent en faisant ``args.sh arg1 > args.out``, le fichier ``args.out`` contient les lignes suivantes : - -.. literalinclude:: src/args.out - :language: console - - -`bash(1)`_ supporte la construction ``if [ condition ]; then ... fi`` qui permet notamment de comparer les valeurs de variables. `bash(1)`_ définit de nombreuses conditions différentes, dont notamment : - - - ``$i -eq $j`` est vraie lorsque les deux variables ``$i`` et ``$j`` contiennent le même nombre. - - ``$i -lt $j`` est vraie lorsque la valeur de la variable ``$i`` est numériquement strictement inférieure à celle de la variable ``$j`` - - ``$i -ge $j`` est vraie lorsque la valeur de la variable ``$i`` est numériquement supérieure ou égale à celle de la variable ``$j`` - - ``$s = $t`` est vraie lorsque la chaîne de caractères contenue dans la variable ``$s`` est égale à celle qui est contenue dans la variable ``$t`` - - ``-z $s`` est vraie lorsque la chaîne de caractères contenue dans la variable ``$s`` est vide - -D'autres types de test sont définis dans la page de manuel : `bash(1)`_. Le script ci-dessous fournit un premier exemple d'utilisation de tests avec `bash(1)`_. - -.. literalinclude:: src/eq.sh - :language: bash - -Tout d'abord, ce script vérifie qu'il a bien été appelé avec deux arguments. Vérifier qu'un programme reçoit bien les arguments qu'il attend est une règle de bonne pratique qu'il est bon de respecter dès le début. Si le script n'est pas appelé avec le bon nombre d'arguments, un message d'erreur est affiché sur la sortie d'erreur standard et le script se termine avec un code de retour. Ces codes de retour sont importants car ils permettent à un autre programme, par exemple un autre script `bash(1)`_ de vérifier le bon déroulement d'un programme appelé. Le script :download:`src/eq.sh` utilise des appels explicites à `exit(1posix)`_ même si par défaut, un script `bash(1)`_ qui n'en contient pas retourne un code de retour nul à la fin de son exécution. - -Un autre exemple d'utilisation des codes de retour est le script :download:`src/wordin.sh` repris ci-dessous qui utilise `grep(1)`_ pour déterminer si un mot passé en argument est présent dans un fichier texte. Pour cela, il exploite la variable spéciale ``$?`` dans laquelle `bash(1)`_ sauve le code de retour du dernier programme exécuté par le script. - -.. literalinclude:: src/wordin.sh - :language: bash - -Ce programme utilise le fichier spécial ``/dev/null``. Celui-ci est en pratique l'équivalent d'un trou noir. Il accepte toutes les données en écriture mais celles-ci ne peuvent jamais être relues. ``/dev/null`` est très utile lorsque l'on veut ignorer la sortie d'un programme et éviter qu'elle ne s'affiche sur le terminal. `bash(1)`_ supporte également ``/dev/stdin`` pour représenter l'entrée standard, ``/dev/stdout`` pour la sortie standard et ``/dev/stderr`` pour l'erreur standard. - - - -Une description complète de `bash(1)`_ sort du cadre de ce cours. De nombreuses références à ce sujet sont disponibles [Cooper2011]_. - -.. rubric:: Footnotes - -.. [#fbitreseau] Dans certaines applications, par exemple dans les réseaux informatiques, il peut être utile d'accéder à la valeur d'un bit particulier qui joue par exemple le rôle d'un drapeau. Celui-ci se trouve cependant généralement à l'intérieur d'une structure de données comprenant un ensemble de bits. - -.. [#funix] Formellement, Unix est une marque déposée par l'`Open Group <http://www.opengroup.org>`_, un ensemble d'entreprises qui développent des standards dans le monde de l'informatique. La première version de Unix écrite en C date de 1973, http://www.unix.org/what_is_unix/history_timeline.html - -.. [#ftermine] Certains processus sont lancés automatiquement au démarrage du système et ne se terminent qu'à son arrêt. Ces processus sont souvent appelés des `daemons`. Il peut s'agir de services qui fonctionnent en permanence sur la machine, comme par exemple un serveur web ou un `daemon` d'authentification. - -.. [#fexecbit] Sous Unix et contrairement à d'autres systèmes d'exploitation, le suffixe d'un nom de fichier ne joue pas de rôle particulier pour indiquer si un fichier contient un programme exécutable ou non. Comme nous le verrons ultérieurement, le système de fichiers Unix contient des bits de permission qui indiquent notamment si un fichier est exécutable ou non. diff --git a/Theorie/links.rst b/Theorie/links.rst deleted file mode 100644 index 3699367545745c29ccc466afbeb7c9fa2f8b7244..0000000000000000000000000000000000000000 --- a/Theorie/links.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. Links to be included - - - -.. _intel : http://www.intel.com -.. _python : http://www.python.org -.. _perl : http://www.perl.org -.. _Git : http://git-scm.com/ -.. _subversion : http://subversion.apache.org/ -.. _ISO-8859 : http://en.wikipedia.org/wiki/ISO/IEC_8859 -.. _Unicode: http://en.wikipedia.org/wiki/Unicode -.. _Endianness: http://en.wikipedia.org/wiki/Endianness -.. _llvm: http://llvm.org - - - - - diff --git a/Theorie/man_links.rst b/Theorie/man_links.rst deleted file mode 100644 index cbd46dbc1bec791719f1746e05e332c6e3024fc6..0000000000000000000000000000000000000000 --- a/Theorie/man_links.rst +++ /dev/null @@ -1,5459 +0,0 @@ -.. _`[(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/[.1.html -.. _`a2dismod(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/a2dismod.8.html -.. _`a2dissite(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/a2dissite.8.html -.. _`a2enmod(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/a2enmod.8.html -.. _`a2ensite(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/a2ensite.8.html -.. _`a2p(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/a2p.1.html -.. _`a64l(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/a64l.3.html -.. _`a64l(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/a64l.3posix.html -.. _`ab(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ab.1.html -.. _`abort(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/abort.3.html -.. _`abort(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/abort.3posix.html -.. _`abs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/abs.3.html -.. _`abs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/abs.3posix.html -.. _`accept(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/accept.2.html -.. _`accept(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/accept.3posix.html -.. _`accept4(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/accept4.2.html -.. _`access(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/access.2.html -.. _`access(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/access.3posix.html -.. _`access.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/access.conf.5.html -.. _`accessdb(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/accessdb.8.html -.. _`acct(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/acct.2.html -.. _`acct(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/acct.5.html -.. _`acos(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/acos.3.html -.. _`acos(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/acos.3posix.html -.. _`acosf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/acosf.3.html -.. _`acosf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/acosf.3posix.html -.. _`acosh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/acosh.3.html -.. _`acosh(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/acosh.3posix.html -.. _`acoshf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/acoshf.3.html -.. _`acoshf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/acoshf.3posix.html -.. _`acoshl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/acoshl.3.html -.. _`acoshl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/acoshl.3posix.html -.. _`acosl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/acosl.3.html -.. _`acosl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/acosl.3posix.html -.. _`addch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/addch.3ncurses.html -.. _`addchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/addchnstr.3ncurses.html -.. _`addchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/addchstr.3ncurses.html -.. _`addgroup(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/addgroup.8.html -.. _`add_key(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/add_key.2.html -.. _`addmntent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/addmntent.3.html -.. _`addnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/addnstr.3ncurses.html -.. _`addnwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/addnwstr.3ncurses.html -.. _`addpart(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/addpart.8.html -.. _`addr2line(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/addr2line.1.html -.. _`addseverity(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/addseverity.3.html -.. _`add-shell(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/add-shell.8.html -.. _`addstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/addstr.3ncurses.html -.. _`adduser(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/adduser.8.html -.. _`adduser.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/adduser.conf.5.html -.. _`add_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/add_wch.3ncurses.html -.. _`add_wchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/add_wchnstr.3ncurses.html -.. _`add_wchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/add_wchstr.3ncurses.html -.. _`addwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/addwstr.3ncurses.html -.. _`adjtime(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/adjtime.2.html -.. _`adjtime(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/adjtime.3.html -.. _`adjtimex(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/adjtimex.2.html -.. _`admin(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/admin.1posix.html -.. _`af_local(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/af_local.7.html -.. _`afs_syscall(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/afs_syscall.2.html -.. _`af_unix(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/af_unix.7.html -.. _`agetty(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/agetty.8.html -.. _`aio_cancel(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aio_cancel.3.html -.. _`aio_cancel(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aio_cancel.3posix.html -.. _`aio_error(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aio_error.3.html -.. _`aio_error(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aio_error.3posix.html -.. _`aio_fsync(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aio_fsync.3.html -.. _`aio_fsync(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aio_fsync.3posix.html -.. _`aio.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/aio.h.7posix.html -.. _`aio_read(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aio_read.3.html -.. _`aio_read(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aio_read.3posix.html -.. _`aio_return(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aio_return.3.html -.. _`aio_return(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aio_return.3posix.html -.. _`aio_suspend(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aio_suspend.3.html -.. _`aio_suspend(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aio_suspend.3posix.html -.. _`aio_write(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aio_write.3.html -.. _`aio_write(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aio_write.3posix.html -.. _`alarm(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/alarm.2.html -.. _`alarm(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/alarm.3posix.html -.. _`algorithm::diff(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/algorithm::diff.3pm.html -.. _`algorithm::diffold(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/algorithm::diffold.3pm.html -.. _`algorithm::diff::xs(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/algorithm::diff::xs.3pm.html -.. _`algorithm::merge(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/algorithm::merge.3pm.html -.. _`alias(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/alias.1posix.html -.. _`alloca(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/alloca.3.html -.. _`alloc_hugepages(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/alloc_hugepages.2.html -.. _`alphasort(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/alphasort.3.html -.. _`apache2(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/apache2.8.html -.. _`apache2ctl(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/apache2ctl.8.html -.. _`apachectl(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/apachectl.8.html -.. _`apropos(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/apropos.1.html -.. _`apt(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/apt.8.html -.. _`apt-cache(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/apt-cache.8.html -.. _`apt-cdrom(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/apt-cdrom.8.html -.. _`apt.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/apt.conf.5.html -.. _`apt-config(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/apt-config.8.html -.. _`apt-extracttemplates(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/apt-extracttemplates.1.html -.. _`apt-file(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/apt-file.1.html -.. _`apt-ftparchive(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/apt-ftparchive.1.html -.. _`apt-get(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/apt-get.8.html -.. _`aptitude(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/aptitude.8.html -.. _`aptitude-create-state-bundle(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/aptitude-create-state-bundle.1.html -.. _`aptitude-run-state-bundle(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/aptitude-run-state-bundle.1.html -.. _`apt-key(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/apt-key.8.html -.. _`apt-mark(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/apt-mark.8.html -.. _`aptpkg(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aptpkg.3pm.html -.. _`aptpkg::cache(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aptpkg::cache.3pm.html -.. _`aptpkg::config(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aptpkg::config.3pm.html -.. _`aptpkg::hash(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aptpkg::hash.3pm.html -.. _`aptpkg::pkgrecords(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aptpkg::pkgrecords.3pm.html -.. _`aptpkg::policy(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aptpkg::policy.3pm.html -.. _`aptpkg::source(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aptpkg::source.3pm.html -.. _`aptpkg::system(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aptpkg::system.3pm.html -.. _`aptpkg::version(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/aptpkg::version.3pm.html -.. _`apt_preferences(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/apt_preferences.5.html -.. _`apt-secure(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/apt-secure.8.html -.. _`apt-sortpkgs(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/apt-sortpkgs.1.html -.. _`ar(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ar.1.html -.. _`ar(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ar.1posix.html -.. _`arch(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/arch.1.html -.. _`arch_prctl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/arch_prctl.2.html -.. _`argz(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/argz.3.html -.. _`argz_add(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/argz_add.3.html -.. _`argz_add_sep(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/argz_add_sep.3.html -.. _`argz_append(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/argz_append.3.html -.. _`argz_count(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/argz_count.3.html -.. _`argz_create(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/argz_create.3.html -.. _`argz_create_sep(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/argz_create_sep.3.html -.. _`argz_delete(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/argz_delete.3.html -.. _`argz_extract(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/argz_extract.3.html -.. _`argz_insert(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/argz_insert.3.html -.. _`argz_next(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/argz_next.3.html -.. _`argz_replace(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/argz_replace.3.html -.. _`argz_stringify(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/argz_stringify.3.html -.. _`armscii-8(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/armscii-8.7.html -.. _`arp(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/arp.7.html -.. _`arp(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/arp.8.html -.. _`arpd(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/arpd.8.html -.. _`as(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/as.1.html -.. _`asa(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/asa.1posix.html -.. _`ascii(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/ascii.7.html -.. _`asctime(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asctime.3.html -.. _`asctime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asctime.3posix.html -.. _`asctime_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asctime_r.3.html -.. _`asctime_r(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asctime_r.3posix.html -.. _`asin(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asin.3.html -.. _`asin(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asin.3posix.html -.. _`asinf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asinf.3.html -.. _`asinf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asinf.3posix.html -.. _`asinh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asinh.3.html -.. _`asinh(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asinh.3posix.html -.. _`asinhf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asinhf.3.html -.. _`asinhf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asinhf.3posix.html -.. _`asinhl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asinhl.3.html -.. _`asinhl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asinhl.3posix.html -.. _`asinl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asinl.3.html -.. _`asinl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asinl.3posix.html -.. _`asn1parse(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/asn1parse.1ssl.html -.. _`asprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/asprintf.3.html -.. _`assert(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/assert.3.html -.. _`assert(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/assert.3posix.html -.. _`assert.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/assert.h.7posix.html -.. _`assert_perror(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/assert_perror.3.html -.. _`assume_default_colors(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/assume_default_colors.3ncurses.html -.. _`at(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/at.1posix.html -.. _`atan2(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atan2.3.html -.. _`atan2(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atan2.3posix.html -.. _`atan2f(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atan2f.3.html -.. _`atan2f(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atan2f.3posix.html -.. _`atan2l(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atan2l.3.html -.. _`atan2l(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atan2l.3posix.html -.. _`atan(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atan.3.html -.. _`atan(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atan.3posix.html -.. _`atanf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atanf.3.html -.. _`atanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atanf.3posix.html -.. _`atanh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atanh.3.html -.. _`atanh(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atanh.3posix.html -.. _`atanhf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atanhf.3.html -.. _`atanhf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atanhf.3posix.html -.. _`atanhl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atanhl.3.html -.. _`atanhl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atanhl.3posix.html -.. _`atanl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atanl.3.html -.. _`atanl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atanl.3posix.html -.. _`atexit(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atexit.3.html -.. _`atexit(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atexit.3posix.html -.. _`atof(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atof.3.html -.. _`atof(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atof.3posix.html -.. _`atoi(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atoi.3.html -.. _`atoi(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atoi.3posix.html -.. _`atol(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atol.3.html -.. _`atol(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atol.3posix.html -.. _`atoll(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atoll.3.html -.. _`atoll(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atoll.3posix.html -.. _`atoq(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/atoq.3.html -.. _`attr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/attr.3ncurses.html -.. _`attr_get(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/attr_get.3ncurses.html -.. _`attributes(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/attributes.3menu.html -.. _`attr_off(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/attr_off.3ncurses.html -.. _`attroff(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/attroff.3ncurses.html -.. _`attr_on(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/attr_on.3ncurses.html -.. _`attron(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/attron.3ncurses.html -.. _`attr_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/attr_set.3ncurses.html -.. _`attrset(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/attrset.3ncurses.html -.. _`auth_destroy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/auth_destroy.3.html -.. _`authnone_create(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/authnone_create.3.html -.. _`authorized_keys(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/authorized_keys.5.html -.. _`authunix_create(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/authunix_create.3.html -.. _`authunix_create_default(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/authunix_create_default.3.html -.. _`avr-addr2line(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-addr2line.1.html -.. _`avr-ar(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-ar.1.html -.. _`avr-as(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-as.1.html -.. _`avr-c++filt(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-c++filt.1.html -.. _`avr-dlltool(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-dlltool.1.html -.. _`avr-gasp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-gasp.1.html -.. _`avr-gprof(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-gprof.1.html -.. _`avr-ld(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-ld.1.html -.. _`avr-nlmconv(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-nlmconv.1.html -.. _`avr-nm(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-nm.1.html -.. _`avr-objcopy(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-objcopy.1.html -.. _`avr-objdump(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-objdump.1.html -.. _`avr-ranlib(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-ranlib.1.html -.. _`avr-readelf(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-readelf.1.html -.. _`avr-size(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-size.1.html -.. _`avr-strings(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-strings.1.html -.. _`avr-strip(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-strip.1.html -.. _`avr-windmc(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-windmc.1.html -.. _`avr-windres(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/avr-windres.1.html -.. _`awk(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/awk.1.html -.. _`awk(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/awk.1posix.html -.. _`backtrace(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/backtrace.3.html -.. _`backtrace_symbols(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/backtrace_symbols.3.html -.. _`backtrace_symbols_fd(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/backtrace_symbols_fd.3.html -.. _`badblocks(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/badblocks.8.html -.. _`base64(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/base64.1.html -.. _`basename(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/basename.1.html -.. _`basename(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/basename.1posix.html -.. _`basename(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/basename.3.html -.. _`basename(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/basename.3posix.html -.. _`bash(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bash.1.html -.. _`bashbug(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bashbug.1.html -.. _`bash-builtins(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/bash-builtins.7.html -.. _`batch(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/batch.1posix.html -.. _`baudrate(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/baudrate.3ncurses.html -.. _`bc(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bc.1.html -.. _`bc(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bc.1posix.html -.. _`bcmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bcmp.3.html -.. _`bcmp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bcmp.3posix.html -.. _`bcopy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bcopy.3.html -.. _`bcopy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bcopy.3posix.html -.. _`bdflush(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/bdflush.2.html -.. _`be16toh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/be16toh.3.html -.. _`be32toh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/be32toh.3.html -.. _`be64toh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/be64toh.3.html -.. _`beep(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/beep.3ncurses.html -.. _`bg(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bg.1posix.html -.. _`bind(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/bind.2.html -.. _`bind(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bind.3posix.html -.. _`bindresvport(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bindresvport.3.html -.. _`biosdecode(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/biosdecode.8.html -.. _`bison(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bison.1.html -.. _`bison.yacc(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bison.yacc.1.html -.. _`bkgd(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bkgd.3ncurses.html -.. _`bkgdset(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bkgdset.3ncurses.html -.. _`bkgrnd(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bkgrnd.3ncurses.html -.. _`bkgrndset(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bkgrndset.3ncurses.html -.. _`blkid(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/blkid.8.html -.. _`blockdev(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/blockdev.8.html -.. _`boot(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/boot.7.html -.. _`bootlogd(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/bootlogd.8.html -.. _`bootparam(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/bootparam.7.html -.. _`border(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/border.3ncurses.html -.. _`border_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/border_set.3ncurses.html -.. _`bottom_panel(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bottom_panel.3curses.html -.. _`box(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/box.3ncurses.html -.. _`box_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/box_set.3ncurses.html -.. _`break(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/break.1posix.html -.. _`break(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/break.2.html -.. _`brk(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/brk.2.html -.. _`bsd-from(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bsd-from.1.html -.. _`bsd_signal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bsd_signal.3.html -.. _`bsd_signal(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bsd_signal.3posix.html -.. _`bsd-write(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bsd-write.1.html -.. _`bsearch(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bsearch.3.html -.. _`bsearch(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bsearch.3posix.html -.. _`bstring(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bstring.3.html -.. _`btowc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/btowc.3.html -.. _`btowc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/btowc.3posix.html -.. _`btree(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/btree.3.html -.. _`builtins(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/builtins.7.html -.. _`bunzip2(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bunzip2.1.html -.. _`busybox(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/busybox.1.html -.. _`byteorder(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/byteorder.3.html -.. _`bzcat(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bzcat.1.html -.. _`bzcmp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bzcmp.1.html -.. _`bzdiff(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bzdiff.1.html -.. _`bzegrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bzegrep.1.html -.. _`bzero(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bzero.3.html -.. _`bzero(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/bzero.3posix.html -.. _`bzexe(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bzexe.1.html -.. _`bzfgrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bzfgrep.1.html -.. _`bzgrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bzgrep.1.html -.. _`bzip2(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bzip2.1.html -.. _`bzip2recover(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bzip2recover.1.html -.. _`bzless(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bzless.1.html -.. _`bzmore(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/bzmore.1.html -.. _`c++(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/c++.1.html -.. _`c2html(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/c2html.1.html -.. _`c2ph(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/c2ph.1.html -.. _`c89(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/c89.1.html -.. _`c89-gcc(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/c89-gcc.1.html -.. _`c99(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/c99.1.html -.. _`c99(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/c99.1posix.html -.. _`c99-gcc(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/c99-gcc.1.html -.. _`ca(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ca.1ssl.html -.. _`cabs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cabs.3.html -.. _`cabs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cabs.3posix.html -.. _`cabsf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cabsf.3.html -.. _`cabsf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cabsf.3posix.html -.. _`cabsl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cabsl.3.html -.. _`cabsl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cabsl.3posix.html -.. _`cacheflush(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/cacheflush.2.html -.. _`cacos(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cacos.3.html -.. _`cacos(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cacos.3posix.html -.. _`cacosf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cacosf.3.html -.. _`cacosf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cacosf.3posix.html -.. _`cacosh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cacosh.3.html -.. _`cacosh(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cacosh.3posix.html -.. _`cacoshf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cacoshf.3.html -.. _`cacoshf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cacoshf.3posix.html -.. _`cacoshl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cacoshl.3.html -.. _`cacoshl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cacoshl.3posix.html -.. _`cacosl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cacosl.3.html -.. _`cacosl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cacosl.3posix.html -.. _`cal(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cal.1.html -.. _`cal(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cal.1posix.html -.. _`calendar(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/calendar.1.html -.. _`callgrind_annotate(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/callgrind_annotate.1.html -.. _`callgrind_control(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/callgrind_control.1.html -.. _`calloc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/calloc.3.html -.. _`calloc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/calloc.3posix.html -.. _`callrpc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/callrpc.3.html -.. _`can_change_color(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/can_change_color.3ncurses.html -.. _`canonicalize_file_name(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/canonicalize_file_name.3.html -.. _`capabilities(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/capabilities.7.html -.. _`capget(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/capget.2.html -.. _`ca.pl(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ca.pl.1ssl.html -.. _`capset(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/capset.2.html -.. _`captoinfo(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/captoinfo.1.html -.. _`carg(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/carg.3.html -.. _`carg(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/carg.3posix.html -.. _`cargf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cargf.3.html -.. _`cargf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cargf.3posix.html -.. _`cargl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cargl.3.html -.. _`cargl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cargl.3posix.html -.. _`casin(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/casin.3.html -.. _`casin(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/casin.3posix.html -.. _`casinf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/casinf.3.html -.. _`casinf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/casinf.3posix.html -.. _`casinh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/casinh.3.html -.. _`casinh(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/casinh.3posix.html -.. _`casinhf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/casinhf.3.html -.. _`casinhf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/casinhf.3posix.html -.. _`casinhl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/casinhl.3.html -.. _`casinhl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/casinhl.3posix.html -.. _`casinl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/casinl.3.html -.. _`casinl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/casinl.3posix.html -.. _`cat(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cat.1.html -.. _`cat(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cat.1posix.html -.. _`catan(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catan.3.html -.. _`catan(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catan.3posix.html -.. _`catanf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catanf.3.html -.. _`catanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catanf.3posix.html -.. _`catanh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catanh.3.html -.. _`catanh(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catanh.3posix.html -.. _`catanhf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catanhf.3.html -.. _`catanhf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catanhf.3posix.html -.. _`catanhl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catanhl.3.html -.. _`catanhl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catanhl.3posix.html -.. _`catanl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catanl.3.html -.. _`catanl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catanl.3posix.html -.. _`catchsegv(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/catchsegv.1.html -.. _`catclose(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catclose.3.html -.. _`catclose(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catclose.3posix.html -.. _`catgets(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catgets.3.html -.. _`catgets(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catgets.3posix.html -.. _`catman(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/catman.8.html -.. _`catopen(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catopen.3.html -.. _`catopen(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/catopen.3posix.html -.. _`cbc_crypt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cbc_crypt.3.html -.. _`cbreak(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cbreak.3ncurses.html -.. _`cbrt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cbrt.3.html -.. _`cbrt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cbrt.3posix.html -.. _`cbrtf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cbrtf.3.html -.. _`cbrtf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cbrtf.3posix.html -.. _`cbrtl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cbrtl.3.html -.. _`cbrtl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cbrtl.3posix.html -.. _`cc(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cc.1.html -.. _`ccos(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ccos.3.html -.. _`ccos(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ccos.3posix.html -.. _`ccosf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ccosf.3.html -.. _`ccosf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ccosf.3posix.html -.. _`ccosh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ccosh.3.html -.. _`ccosh(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ccosh.3posix.html -.. _`ccoshf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ccoshf.3.html -.. _`ccoshf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ccoshf.3posix.html -.. _`ccoshl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ccoshl.3.html -.. _`ccoshl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ccoshl.3posix.html -.. _`ccosl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ccosl.3.html -.. _`ccosl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ccosl.3posix.html -.. _`cd(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cd.1posix.html -.. _`ceil(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ceil.3.html -.. _`ceil(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ceil.3posix.html -.. _`ceilf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ceilf.3.html -.. _`ceilf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ceilf.3posix.html -.. _`ceill(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ceill.3.html -.. _`ceill(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ceill.3posix.html -.. _`cerf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cerf.3.html -.. _`cerfc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cerfc.3.html -.. _`cerfcf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cerfcf.3.html -.. _`cerfcl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cerfcl.3.html -.. _`cerff(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cerff.3.html -.. _`cerfl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cerfl.3.html -.. _`cexp2(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cexp2.3.html -.. _`cexp2f(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cexp2f.3.html -.. _`cexp2l(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cexp2l.3.html -.. _`cexp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cexp.3.html -.. _`cexp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cexp.3posix.html -.. _`cexpf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cexpf.3.html -.. _`cexpf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cexpf.3posix.html -.. _`cexpl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cexpl.3.html -.. _`cexpl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cexpl.3posix.html -.. _`cfdisk(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/cfdisk.8.html -.. _`cfgetispeed(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cfgetispeed.3.html -.. _`cfgetispeed(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cfgetispeed.3posix.html -.. _`cfgetospeed(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cfgetospeed.3.html -.. _`cfgetospeed(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cfgetospeed.3posix.html -.. _`c++filt(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/c++filt.1.html -.. _`cflow(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cflow.1posix.html -.. _`cfmakeraw(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cfmakeraw.3.html -.. _`cfree(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cfree.3.html -.. _`cfsetispeed(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cfsetispeed.3.html -.. _`cfsetispeed(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cfsetispeed.3posix.html -.. _`cfsetospeed(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cfsetospeed.3.html -.. _`cfsetospeed(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cfsetospeed.3posix.html -.. _`cfsetspeed(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cfsetspeed.3.html -.. _`cg_annotate(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cg_annotate.1.html -.. _`chage(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/chage.1.html -.. _`charmap(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/charmap.5.html -.. _`charsets(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/charsets.7.html -.. _`chattr(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/chattr.1.html -.. _`chcon(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/chcon.1.html -.. _`chdir(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/chdir.2.html -.. _`chdir(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/chdir.3posix.html -.. _`check_forensic(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/check_forensic.8.html -.. _`checkgid(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/checkgid.8.html -.. _`chfn(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/chfn.1.html -.. _`chgat(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/chgat.3ncurses.html -.. _`chgpasswd(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/chgpasswd.8.html -.. _`chgrp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/chgrp.1.html -.. _`chgrp(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/chgrp.1posix.html -.. _`chkdupexe(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/chkdupexe.1.html -.. _`chmod(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/chmod.1.html -.. _`chmod(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/chmod.1posix.html -.. _`chmod(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/chmod.2.html -.. _`chmod(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/chmod.3posix.html -.. _`chown(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/chown.1.html -.. _`chown(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/chown.1posix.html -.. _`chown(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/chown.2.html -.. _`chown32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/chown32.2.html -.. _`chown(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/chown.3posix.html -.. _`chpasswd(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/chpasswd.8.html -.. _`chroot(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/chroot.2.html -.. _`chroot(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/chroot.8.html -.. _`chrt(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/chrt.1.html -.. _`chsh(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/chsh.1.html -.. _`cimag(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cimag.3.html -.. _`cimag(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cimag.3posix.html -.. _`cimagf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cimagf.3.html -.. _`cimagf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cimagf.3posix.html -.. _`cimagl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cimagl.3.html -.. _`cimagl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cimagl.3posix.html -.. _`ciphers(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ciphers.1ssl.html -.. _`cksum(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cksum.1.html -.. _`cksum(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cksum.1posix.html -.. _`clear(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/clear.1.html -.. _`clear(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clear.3ncurses.html -.. _`clear_console(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/clear_console.1.html -.. _`clearenv(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clearenv.3.html -.. _`clearerr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clearerr.3.html -.. _`clearerr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clearerr.3posix.html -.. _`clearerr_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clearerr_unlocked.3.html -.. _`clearok(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clearok.3ncurses.html -.. _`clnt_broadcast(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clnt_broadcast.3.html -.. _`clnt_call(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clnt_call.3.html -.. _`clnt_control(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clnt_control.3.html -.. _`clnt_create(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clnt_create.3.html -.. _`clnt_destroy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clnt_destroy.3.html -.. _`clnt_freeres(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clnt_freeres.3.html -.. _`clnt_geterr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clnt_geterr.3.html -.. _`clnt_pcreateerror(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clnt_pcreateerror.3.html -.. _`clnt_perrno(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clnt_perrno.3.html -.. _`clnt_perror(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clnt_perror.3.html -.. _`clntraw_create(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clntraw_create.3.html -.. _`clnt_spcreateerror(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clnt_spcreateerror.3.html -.. _`clnt_sperrno(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clnt_sperrno.3.html -.. _`clnt_sperror(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clnt_sperror.3.html -.. _`clnttcp_create(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clnttcp_create.3.html -.. _`clntudp_bufcreate(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clntudp_bufcreate.3.html -.. _`clntudp_create(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clntudp_create.3.html -.. _`clock(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clock.3.html -.. _`clock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clock.3posix.html -.. _`clock(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/clock.8.html -.. _`clock_getcpuclockid(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clock_getcpuclockid.3.html -.. _`clock_getcpuclockid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clock_getcpuclockid.3posix.html -.. _`clock_getres(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/clock_getres.2.html -.. _`clock_getres(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clock_getres.3.html -.. _`clock_getres(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clock_getres.3posix.html -.. _`clock_gettime(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/clock_gettime.2.html -.. _`clock_gettime(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clock_gettime.3.html -.. _`clock_gettime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clock_gettime.3posix.html -.. _`clock_nanosleep(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/clock_nanosleep.2.html -.. _`clock_nanosleep(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clock_nanosleep.3posix.html -.. _`clock_settime(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/clock_settime.2.html -.. _`clock_settime(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clock_settime.3.html -.. _`clock_settime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clock_settime.3posix.html -.. _`clog10(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clog10.3.html -.. _`clog10f(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clog10f.3.html -.. _`clog10l(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clog10l.3.html -.. _`clog2(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clog2.3.html -.. _`clog2f(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clog2f.3.html -.. _`clog2l(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clog2l.3.html -.. _`clog(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clog.3.html -.. _`clog(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clog.3posix.html -.. _`clogf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clogf.3.html -.. _`clogf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clogf.3posix.html -.. _`clogl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clogl.3.html -.. _`clogl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clogl.3posix.html -.. _`__clone2(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/__clone2.2.html -.. _`clone2(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/clone2.2.html -.. _`clone(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/clone.2.html -.. _`close(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/close.2.html -.. _`close(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/close.3posix.html -.. _`closedir(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/closedir.3.html -.. _`closedir(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/closedir.3posix.html -.. _`closelog(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/closelog.3.html -.. _`closelog(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/closelog.3posix.html -.. _`clrtobot(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clrtobot.3ncurses.html -.. _`clrtoeol(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/clrtoeol.3ncurses.html -.. _`cmp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cmp.1.html -.. _`cmp(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cmp.1posix.html -.. _`cmsg(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cmsg.3.html -.. _`cmsg_align(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cmsg_align.3.html -.. _`cmsg_firsthdr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cmsg_firsthdr.3.html -.. _`cmsg_nxthdr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cmsg_nxthdr.3.html -.. _`cmsg_space(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cmsg_space.3.html -.. _`col(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/col.1.html -.. _`colcrt(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/colcrt.1.html -.. _`colon(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/colon.1posix.html -.. _`color(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/color.3ncurses.html -.. _`color_content(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/color_content.3ncurses.html -.. _`color_pair(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/color_pair.3ncurses.html -.. _`color_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/color_set.3ncurses.html -.. _`colrm(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/colrm.1.html -.. _`column(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/column.1.html -.. _`comm(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/comm.1.html -.. _`comm(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/comm.1posix.html -.. _`command(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/command.1posix.html -.. _`complex(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/complex.5.html -.. _`complex(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/complex.7.html -.. _`complex.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/complex.h.7posix.html -.. _`compose(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/compose.1.html -.. _`compose(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/compose.5.html -.. _`compress(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/compress.1posix.html -.. _`config(5ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man5/config.5ssl.html -.. _`config_data(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/config_data.1.html -.. _`config::file(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/config::file.3pm.html -.. _`confstr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/confstr.3.html -.. _`confstr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/confstr.3posix.html -.. _`conj(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/conj.3.html -.. _`conj(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/conj.3posix.html -.. _`conjf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/conjf.3.html -.. _`conjf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/conjf.3posix.html -.. _`conjl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/conjl.3.html -.. _`conjl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/conjl.3posix.html -.. _`connect(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/connect.2.html -.. _`connect(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/connect.3posix.html -.. _`console_codes(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/console_codes.4.html -.. _`console_ioctl(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/console_ioctl.4.html -.. _`continue(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/continue.1posix.html -.. _`copysign(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/copysign.3.html -.. _`copysign(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/copysign.3posix.html -.. _`copysignf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/copysignf.3.html -.. _`copysignf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/copysignf.3posix.html -.. _`copysignl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/copysignl.3.html -.. _`copysignl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/copysignl.3posix.html -.. _`copywin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/copywin.3ncurses.html -.. _`core(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/core.5.html -.. _`corelist(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/corelist.1.html -.. _`cos(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cos.3.html -.. _`cos(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cos.3posix.html -.. _`cosf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cosf.3.html -.. _`cosf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cosf.3posix.html -.. _`cosh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cosh.3.html -.. _`cosh(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cosh.3posix.html -.. _`coshf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/coshf.3.html -.. _`coshf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/coshf.3posix.html -.. _`coshl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/coshl.3.html -.. _`coshl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/coshl.3posix.html -.. _`cosl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cosl.3.html -.. _`cosl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cosl.3posix.html -.. _`cp1251(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/cp1251.7.html -.. _`cp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cp.1.html -.. _`cp(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cp.1posix.html -.. _`cpan(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cpan.1.html -.. _`cpan2dist(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cpan2dist.1.html -.. _`cpanp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cpanp.1.html -.. _`cpgr(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/cpgr.8.html -.. _`cpio(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cpio.1.html -.. _`cpio.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/cpio.h.7posix.html -.. _`cpow(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpow.3.html -.. _`cpow(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpow.3posix.html -.. _`cpowf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpowf.3.html -.. _`cpowf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpowf.3posix.html -.. _`cpowl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpowl.3.html -.. _`cpowl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpowl.3posix.html -.. _`cpp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cpp.1.html -.. _`cpp-4.4(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cpp-4.4.1.html -.. _`cppw(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/cppw.8.html -.. _`cproj(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cproj.3.html -.. _`cproj(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cproj.3posix.html -.. _`cprojf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cprojf.3.html -.. _`cprojf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cprojf.3posix.html -.. _`cprojl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cprojl.3.html -.. _`cprojl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cprojl.3posix.html -.. _`cpu_alloc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_alloc.3.html -.. _`cpu_alloc_size(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_alloc_size.3.html -.. _`cpu_and(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_and.3.html -.. _`cpu_and_s(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_and_s.3.html -.. _`cpu_clr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_clr.3.html -.. _`cpu_clr_s(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_clr_s.3.html -.. _`cpu_count(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_count.3.html -.. _`cpu_count_s(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_count_s.3.html -.. _`cpu_equal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_equal.3.html -.. _`cpu_equal_s(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_equal_s.3.html -.. _`cpu_free(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_free.3.html -.. _`cpuid(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/cpuid.4.html -.. _`cpu_isset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_isset.3.html -.. _`cpu_isset_s(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_isset_s.3.html -.. _`cpu_or(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_or.3.html -.. _`cpu_or_s(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_or_s.3.html -.. _`cpu_set(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_set.3.html -.. _`cpuset(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/cpuset.7.html -.. _`cpu_set_s(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_set_s.3.html -.. _`cpu_xor(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_xor.3.html -.. _`cpu_xor_s(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_xor_s.3.html -.. _`cpu_zero(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_zero.3.html -.. _`cpu_zero_s(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cpu_zero_s.3.html -.. _`creal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/creal.3.html -.. _`creal(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/creal.3posix.html -.. _`crealf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/crealf.3.html -.. _`crealf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/crealf.3posix.html -.. _`creall(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/creall.3.html -.. _`creall(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/creall.3posix.html -.. _`creat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/creat.2.html -.. _`creat(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/creat.3posix.html -.. _`credentials(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/credentials.7.html -.. _`c_rehash(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/c_rehash.1ssl.html -.. _`crl(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/crl.1ssl.html -.. _`crl2pkcs7(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/crl2pkcs7.1ssl.html -.. _`cron(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/cron.8.html -.. _`crontab(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/crontab.1.html -.. _`crontab(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/crontab.1posix.html -.. _`crontab(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/crontab.5.html -.. _`crypt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/crypt.3.html -.. _`crypt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/crypt.3posix.html -.. _`crypt_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/crypt_r.3.html -.. _`csh(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/csh.1.html -.. _`csin(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csin.3.html -.. _`csin(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csin.3posix.html -.. _`csinf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csinf.3.html -.. _`csinf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csinf.3posix.html -.. _`csinh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csinh.3.html -.. _`csinh(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csinh.3posix.html -.. _`csinhf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csinhf.3.html -.. _`csinhf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csinhf.3posix.html -.. _`csinhl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csinhl.3.html -.. _`csinhl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csinhl.3posix.html -.. _`csinl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csinl.3.html -.. _`csinl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csinl.3posix.html -.. _`csplit(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/csplit.1.html -.. _`csplit(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/csplit.1posix.html -.. _`csqrt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csqrt.3.html -.. _`csqrt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csqrt.3posix.html -.. _`csqrtf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csqrtf.3.html -.. _`csqrtf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csqrtf.3posix.html -.. _`csqrtl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csqrtl.3.html -.. _`csqrtl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/csqrtl.3posix.html -.. _`ctags(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ctags.1posix.html -.. _`ctan(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctan.3.html -.. _`ctan(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctan.3posix.html -.. _`ctanf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctanf.3.html -.. _`ctanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctanf.3posix.html -.. _`ctanh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctanh.3.html -.. _`ctanh(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctanh.3posix.html -.. _`ctanhf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctanhf.3.html -.. _`ctanhf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctanhf.3posix.html -.. _`ctanhl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctanhl.3.html -.. _`ctanhl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctanhl.3posix.html -.. _`ctanl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctanl.3.html -.. _`ctanl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctanl.3posix.html -.. _`ctermid(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctermid.3.html -.. _`ctermid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctermid.3posix.html -.. _`ctime(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctime.3.html -.. _`ctime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctime.3posix.html -.. _`ctime_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctime_r.3.html -.. _`ctime_r(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ctime_r.3posix.html -.. _`ctrlaltdel(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ctrlaltdel.8.html -.. _`ctstat(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ctstat.8.html -.. _`ctype.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/ctype.h.7posix.html -.. _`cunit(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cunit.3.html -.. _`curl(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/curl.1.html -.. _`current_field(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/current_field.3form.html -.. _`current_item(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/current_item.3menu.html -.. _`curses_version(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/curses_version.3ncurses.html -.. _`cursor(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cursor.3form.html -.. _`cursor(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cursor.3menu.html -.. _`curs_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/curs_set.3ncurses.html -.. _`cuserid(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/cuserid.3.html -.. _`cut(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cut.1.html -.. _`cut(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cut.1posix.html -.. _`cxref(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/cxref.1posix.html -.. _`cytune(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/cytune.8.html -.. _`daemon(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/daemon.3.html -.. _`dash(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dash.1.html -.. _`data(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/data.3form.html -.. _`data_ahead(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/data_ahead.3form.html -.. _`data_behind(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/data_behind.3form.html -.. _`date(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/date.1.html -.. _`date(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/date.1posix.html -.. _`date::format(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/date::format.3pm.html -.. _`date::language(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/date::language.3pm.html -.. _`date::language::hungarian(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/date::language::hungarian.3pm.html -.. _`date::parse(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/date::parse.3pm.html -.. _`daylight(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/daylight.3.html -.. _`daylight(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/daylight.3posix.html -.. _`db(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/db.3.html -.. _`dbm_clearerr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dbm_clearerr.3posix.html -.. _`dbm_close(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dbm_close.3posix.html -.. _`dbm_delete(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dbm_delete.3posix.html -.. _`dbm_error(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dbm_error.3posix.html -.. _`dbm_fetch(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dbm_fetch.3posix.html -.. _`dbm_firstkey(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dbm_firstkey.3posix.html -.. _`dbmmanage(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dbmmanage.1.html -.. _`dbm_nextkey(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dbm_nextkey.3posix.html -.. _`dbm_open(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dbm_open.3posix.html -.. _`dbm_store(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dbm_store.3posix.html -.. _`dbopen(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dbopen.3.html -.. _`dd(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dd.1.html -.. _`dd(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dd.1posix.html -.. _`ddate(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ddate.1.html -.. _`ddp(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/ddp.7.html -.. _`deb(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/deb.5.html -.. _`debconf(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/debconf.1.html -.. _`debconf-apt-progress(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/debconf-apt-progress.1.html -.. _`debconf-communicate(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/debconf-communicate.1.html -.. _`debconf-copydb(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/debconf-copydb.1.html -.. _`debconf-escape(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/debconf-escape.1.html -.. _`debconf-set-selections(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/debconf-set-selections.1.html -.. _`debconf-show(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/debconf-show.1.html -.. _`deb-control(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/deb-control.5.html -.. _`deb-extra-override(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/deb-extra-override.5.html -.. _`deb-old(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/deb-old.5.html -.. _`deb-override(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/deb-override.5.html -.. _`deb-shlibs(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/deb-shlibs.5.html -.. _`deb-split(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/deb-split.5.html -.. _`deb-substvars(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/deb-substvars.5.html -.. _`deb-symbols(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/deb-symbols.5.html -.. _`deb-triggers(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/deb-triggers.5.html -.. _`debugfs(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/debugfs.8.html -.. _`deb-version(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/deb-version.5.html -.. _`default_colors(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/default_colors.3ncurses.html -.. _`define_key(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/define_key.3ncurses.html -.. _`def_prog_mode(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/def_prog_mode.3ncurses.html -.. _`def_shell_mode(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/def_shell_mode.3ncurses.html -.. _`delay_output(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/delay_output.3ncurses.html -.. _`delch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/delch.3ncurses.html -.. _`del_curterm(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/del_curterm.3ncurses.html -.. _`deleteln(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/deleteln.3ncurses.html -.. _`delgroup(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/delgroup.8.html -.. _`del_panel(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/del_panel.3curses.html -.. _`delpart(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/delpart.8.html -.. _`delscreen(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/delscreen.3ncurses.html -.. _`delta(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/delta.1posix.html -.. _`deluser(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/deluser.8.html -.. _`deluser.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/deluser.conf.5.html -.. _`delwin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/delwin.3ncurses.html -.. _`depmod(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/depmod.8.html -.. _`depmod.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/depmod.conf.5.html -.. _`derwin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/derwin.3ncurses.html -.. _`des_crypt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/des_crypt.3.html -.. _`des_modes(7ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man7/des_modes.7ssl.html -.. _`des_setparity(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/des_setparity.3.html -.. _`df(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/df.1.html -.. _`df(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/df.1posix.html -.. _`dgst(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dgst.1ssl.html -.. _`dhclient(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/dhclient.8.html -.. _`dhclient.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/dhclient.conf.5.html -.. _`dhclient.leases(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/dhclient.leases.5.html -.. _`dhclient-script(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/dhclient-script.8.html -.. _`dhcp-eval(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/dhcp-eval.5.html -.. _`dhcp-options(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/dhcp-options.5.html -.. _`dh_installxmlcatalogs(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dh_installxmlcatalogs.1.html -.. _`dhparam(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dhparam.1ssl.html -.. _`dh_pycentral(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dh_pycentral.1.html -.. _`dh_pysupport(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dh_pysupport.1.html -.. _`dh_python2(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dh_python2.1.html -.. _`diff(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/diff.1.html -.. _`diff(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/diff.1posix.html -.. _`diff3(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/diff3.1.html -.. _`diffindex-download(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/diffindex-download.1.html -.. _`diffindex-rred(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/diffindex-rred.1.html -.. _`difftime(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/difftime.3.html -.. _`difftime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/difftime.3posix.html -.. _`dir(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dir.1.html -.. _`dircolors(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dircolors.1.html -.. _`dir_colors(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/dir_colors.5.html -.. _`dirent.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/dirent.h.7posix.html -.. _`dirfd(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dirfd.3.html -.. _`dirname(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dirname.1.html -.. _`dirname(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dirname.1posix.html -.. _`dirname(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dirname.3.html -.. _`dirname(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dirname.3posix.html -.. _`div(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/div.3.html -.. _`div(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/div.3posix.html -.. _`dladdr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dladdr.3.html -.. _`dlclose(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dlclose.3.html -.. _`dlclose(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dlclose.3posix.html -.. _`dlerror(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dlerror.3.html -.. _`dlerror(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dlerror.3posix.html -.. _`dlfcn.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/dlfcn.h.7posix.html -.. _`dl_iterate_phdr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dl_iterate_phdr.3.html -.. _`dlltool(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dlltool.1.html -.. _`dlopen(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dlopen.3.html -.. _`dlopen(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dlopen.3posix.html -.. _`dlsym(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dlsym.3.html -.. _`dlsym(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dlsym.3posix.html -.. _`dlvsym(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dlvsym.3.html -.. _`dmesg(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dmesg.1.html -.. _`dmidecode(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/dmidecode.8.html -.. _`dn_comp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dn_comp.3.html -.. _`dn_expand(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dn_expand.3.html -.. _`dnsdomainname(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dnsdomainname.1.html -.. _`domainname(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/domainname.1.html -.. _`dot(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dot.1posix.html -.. _`doupdate(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/doupdate.3ncurses.html -.. _`dpkg(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg.1.html -.. _`dpkg-architecture(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-architecture.1.html -.. _`dpkg-buildflags(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-buildflags.1.html -.. _`dpkg::buildflags(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::buildflags.3.html -.. _`dpkg::buildoptions(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::buildoptions.3.html -.. _`dpkg-buildpackage(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-buildpackage.1.html -.. _`dpkg.cfg(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/dpkg.cfg.5.html -.. _`dpkg::changelog(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::changelog.3.html -.. _`dpkg::changelog::debian(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::changelog::debian.3.html -.. _`dpkg::changelog::entry(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::changelog::entry.3.html -.. _`dpkg::changelog::entry::debian(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::changelog::entry::debian.3.html -.. _`dpkg::changelog::parse(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::changelog::parse.3.html -.. _`dpkg-checkbuilddeps(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-checkbuilddeps.1.html -.. _`dpkg::checksums(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::checksums.3.html -.. _`dpkg::compression(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::compression.3.html -.. _`dpkg::compression::filehandle(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::compression::filehandle.3.html -.. _`dpkg::compression::process(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::compression::process.3.html -.. _`dpkg::conf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::conf.3.html -.. _`dpkg::control(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::control.3.html -.. _`dpkg::control::changelog(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::control::changelog.3.html -.. _`dpkg::control::fields(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::control::fields.3.html -.. _`dpkg::control::hash(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::control::hash.3.html -.. _`dpkg::control::info(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::control::info.3.html -.. _`dpkg::control::types(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::control::types.3.html -.. _`dpkg-deb(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-deb.1.html -.. _`dpkg::deps(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::deps.3.html -.. _`dpkg-distaddfile(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-distaddfile.1.html -.. _`dpkg-divert(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/dpkg-divert.8.html -.. _`dpkg-genchanges(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-genchanges.1.html -.. _`dpkg-gencontrol(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-gencontrol.1.html -.. _`dpkg-gensymbols(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-gensymbols.1.html -.. _`dpkg::index(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::index.3.html -.. _`dpkg::interface::storable(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::interface::storable.3.html -.. _`dpkg::ipc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::ipc.3.html -.. _`dpkg-maintscript-helper(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-maintscript-helper.1.html -.. _`dpkg-mergechangelogs(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-mergechangelogs.1.html -.. _`dpkg-name(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-name.1.html -.. _`dpkg-parsechangelog(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-parsechangelog.1.html -.. _`dpkg::path(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::path.3.html -.. _`dpkg-preconfigure(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/dpkg-preconfigure.8.html -.. _`dpkg-query(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-query.1.html -.. _`dpkg-reconfigure(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/dpkg-reconfigure.8.html -.. _`dpkg-scanpackages(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-scanpackages.1.html -.. _`dpkg-scansources(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-scansources.1.html -.. _`dpkg-shlibdeps(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-shlibdeps.1.html -.. _`dpkg-source(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-source.1.html -.. _`dpkg-split(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-split.1.html -.. _`dpkg-statoverride(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/dpkg-statoverride.8.html -.. _`dpkg::substvars(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::substvars.3.html -.. _`dpkg-trigger(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-trigger.1.html -.. _`dpkg-vendor(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dpkg-vendor.1.html -.. _`dpkg::vendor(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::vendor.3.html -.. _`dpkg::vendor::debian(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::vendor::debian.3.html -.. _`dpkg::vendor::default(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::vendor::default.3.html -.. _`dpkg::vendor::ubuntu(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::vendor::ubuntu.3.html -.. _`dpkg::version(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dpkg::version.3.html -.. _`dprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dprintf.3.html -.. _`dprofpp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dprofpp.1.html -.. _`drand48(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/drand48.3.html -.. _`drand48(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/drand48.3posix.html -.. _`drand48_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/drand48_r.3.html -.. _`drem(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/drem.3.html -.. _`dremf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dremf.3.html -.. _`dreml(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dreml.3.html -.. _`driver(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/driver.3form.html -.. _`driver(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/driver.3menu.html -.. _`dsa(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dsa.1ssl.html -.. _`dsaparam(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/dsaparam.1ssl.html -.. _`dsp56k(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/dsp56k.4.html -.. _`du(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/du.1.html -.. _`du(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/du.1posix.html -.. _`dumpe2fs(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/dumpe2fs.8.html -.. _`dup2(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/dup2.2.html -.. _`dup2(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dup2.3posix.html -.. _`dup(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/dup.2.html -.. _`dup3(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/dup3.2.html -.. _`dup(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dup.3posix.html -.. _`dup_field(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dup_field.3form.html -.. _`dupwin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dupwin.3ncurses.html -.. _`dynamic_field_info(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dynamic_field_info.3form.html -.. _`dysize(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/dysize.3.html -.. _`e2freefrag(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/e2freefrag.8.html -.. _`e2fsck(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/e2fsck.8.html -.. _`e2fsck.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/e2fsck.conf.5.html -.. _`e2image(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/e2image.8.html -.. _`e2label(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/e2label.8.html -.. _`e2undo(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/e2undo.8.html -.. _`eaccess(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/eaccess.3.html -.. _`ec(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ec.1ssl.html -.. _`ecb_crypt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ecb_crypt.3.html -.. _`echo(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/echo.1.html -.. _`echo(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/echo.1posix.html -.. _`echo(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/echo.3ncurses.html -.. _`echochar(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/echochar.3ncurses.html -.. _`echo_wchar(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/echo_wchar.3ncurses.html -.. _`ecparam(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ecparam.1ssl.html -.. _`ecvt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ecvt.3.html -.. _`ecvt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ecvt.3posix.html -.. _`ecvt_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ecvt_r.3.html -.. _`ed(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ed.1posix.html -.. _`edata(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/edata.3.html -.. _`edit(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/edit.1.html -.. _`editor(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/editor.1.html -.. _`egrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/egrep.1.html -.. _`elf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/elf.5.html -.. _`enc(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/enc.1ssl.html -.. _`enc2xs(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/enc2xs.1.html -.. _`encrypt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/encrypt.3.html -.. _`encrypt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/encrypt.3posix.html -.. _`encrypt_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/encrypt_r.3.html -.. _`end(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/end.3.html -.. _`endaliasent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endaliasent.3.html -.. _`endfsent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endfsent.3.html -.. _`endgrent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endgrent.3.html -.. _`endgrent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endgrent.3posix.html -.. _`endhostent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endhostent.3.html -.. _`endhostent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endhostent.3posix.html -.. _`endian(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endian.3.html -.. _`endmntent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endmntent.3.html -.. _`endnetent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endnetent.3.html -.. _`endnetent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endnetent.3posix.html -.. _`endnetgrent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endnetgrent.3.html -.. _`endprotoent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endprotoent.3.html -.. _`endprotoent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endprotoent.3posix.html -.. _`endpwent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endpwent.3.html -.. _`endpwent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endpwent.3posix.html -.. _`endrpcent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endrpcent.3.html -.. _`endservent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endservent.3.html -.. _`endservent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endservent.3posix.html -.. _`endspent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endspent.3.html -.. _`endttyent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endttyent.3.html -.. _`endusershell(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endusershell.3.html -.. _`endutent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endutent.3.html -.. _`endutxent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endutxent.3.html -.. _`endutxent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endutxent.3posix.html -.. _`endwin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/endwin.3ncurses.html -.. _`env(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/env.1.html -.. _`env(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/env.1posix.html -.. _`environ(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/environ.3posix.html -.. _`environ(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/environ.7.html -.. _`envz(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/envz.3.html -.. _`envz_add(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/envz_add.3.html -.. _`envz_entry(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/envz_entry.3.html -.. _`envz_get(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/envz_get.3.html -.. _`envz_merge(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/envz_merge.3.html -.. _`envz_remove(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/envz_remove.3.html -.. _`envz_strip(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/envz_strip.3.html -.. _`epoll(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/epoll.4.html -.. _`epoll(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/epoll.7.html -.. _`epoll_create1(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/epoll_create1.2.html -.. _`epoll_create(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/epoll_create.2.html -.. _`epoll_ctl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/epoll_ctl.2.html -.. _`epoll_pwait(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/epoll_pwait.2.html -.. _`epoll_wait(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/epoll_wait.2.html -.. _`eqn(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/eqn.1.html -.. _`erand48(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erand48.3.html -.. _`erand48(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erand48.3posix.html -.. _`erand48_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erand48_r.3.html -.. _`erase(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erase.3ncurses.html -.. _`erasechar(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erasechar.3ncurses.html -.. _`erasewchar(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erasewchar.3ncurses.html -.. _`erf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erf.3.html -.. _`erf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erf.3posix.html -.. _`erfc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erfc.3.html -.. _`erfc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erfc.3posix.html -.. _`erfcf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erfcf.3.html -.. _`erfcf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erfcf.3posix.html -.. _`erfcl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erfcl.3.html -.. _`erfcl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erfcl.3posix.html -.. _`erff(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erff.3.html -.. _`erff(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erff.3posix.html -.. _`erfl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erfl.3.html -.. _`erfl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/erfl.3posix.html -.. _`err(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/err.3.html -.. _`errno(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/errno.3.html -.. _`errno(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/errno.3posix.html -.. _`errno.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/errno.h.7posix.html -.. _`error(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/error.3.html -.. _`error(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/error.3pm.html -.. _`error_at_line(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/error_at_line.3.html -.. _`error_message_count(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/error_message_count.3.html -.. _`error_on_per_line(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/error_on_per_line.3.html -.. _`error_print_progname(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/error_print_progname.3.html -.. _`error::simple(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/error::simple.3pm.html -.. _`errstr(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/errstr.1ssl.html -.. _`errx(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/errx.3.html -.. _`etc-aliases(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/etc-aliases.5.html -.. _`etc-email-addresses(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/etc-email-addresses.5.html -.. _`etext(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/etext.3.html -.. _`ether_aton(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ether_aton.3.html -.. _`ether_aton_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ether_aton_r.3.html -.. _`ether_hostton(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ether_hostton.3.html -.. _`ether_line(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ether_line.3.html -.. _`ether_ntoa(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ether_ntoa.3.html -.. _`ether_ntoa_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ether_ntoa_r.3.html -.. _`ether_ntohost(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ether_ntohost.3.html -.. _`ethers(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/ethers.5.html -.. _`euidaccess(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/euidaccess.3.html -.. _`eval(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/eval.1posix.html -.. _`eventfd2(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/eventfd2.2.html -.. _`eventfd(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/eventfd.2.html -.. _`eventfd_read(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/eventfd_read.3.html -.. _`eventfd_write(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/eventfd_write.3.html -.. _`ex(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ex.1.html -.. _`ex(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ex.1posix.html -.. _`exec(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/exec.1posix.html -.. _`exec(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/exec.3.html -.. _`exec(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/exec.3posix.html -.. _`execl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/execl.3.html -.. _`execl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/execl.3posix.html -.. _`execle(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/execle.3.html -.. _`execle(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/execle.3posix.html -.. _`execlp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/execlp.3.html -.. _`execlp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/execlp.3posix.html -.. _`execv(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/execv.3.html -.. _`execv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/execv.3posix.html -.. _`execve(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/execve.2.html -.. _`execve(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/execve.3posix.html -.. _`execvp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/execvp.3.html -.. _`execvp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/execvp.3posix.html -.. _`exicyclog(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exicyclog.8.html -.. _`exigrep(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exigrep.8.html -.. _`exim4(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exim4.8.html -.. _`exim4-config_files(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/exim4-config_files.5.html -.. _`exim4_exim_crt(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/exim4_exim_crt.5.html -.. _`exim4_exim_key(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/exim4_exim_key.5.html -.. _`exim4_hubbed_hosts(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/exim4_hubbed_hosts.5.html -.. _`exim4_local_domain_dnsbl_whitelist(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/exim4_local_domain_dnsbl_whitelist.5.html -.. _`exim4_local_host_blacklist(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/exim4_local_host_blacklist.5.html -.. _`exim4_local_host_whitelist(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/exim4_local_host_whitelist.5.html -.. _`exim4_local_rcpt_callout(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/exim4_local_rcpt_callout.5.html -.. _`exim4_local_sender_blacklist(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/exim4_local_sender_blacklist.5.html -.. _`exim4_local_sender_callout(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/exim4_local_sender_callout.5.html -.. _`exim4_local_sender_whitelist(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/exim4_local_sender_whitelist.5.html -.. _`exim4_passwd(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/exim4_passwd.5.html -.. _`exim4_passwd_client(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/exim4_passwd_client.5.html -.. _`exim(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exim.8.html -.. _`exim_checkaccess(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exim_checkaccess.8.html -.. _`exim_convert4r4(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exim_convert4r4.8.html -.. _`exim_db(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exim_db.8.html -.. _`exim_dbmbuild(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exim_dbmbuild.8.html -.. _`exim_dumpdb(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exim_dumpdb.8.html -.. _`exim_fixdb(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exim_fixdb.8.html -.. _`exim_lock(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exim_lock.8.html -.. _`eximstats(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/eximstats.8.html -.. _`exim_tidydb(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exim_tidydb.8.html -.. _`exinext(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exinext.8.html -.. _`exipick(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exipick.8.html -.. _`exiqgrep(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exiqgrep.8.html -.. _`exiqsumm(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exiqsumm.8.html -.. _`exit(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/exit.1posix.html -.. _`_exit(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/_exit.2.html -.. _`exit(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/exit.2.html -.. _`exit(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/exit.3.html -.. _`_exit(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_exit.3posix.html -.. _`exit(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/exit.3posix.html -.. _`exit_group(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/exit_group.2.html -.. _`exiwhat(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/exiwhat.8.html -.. _`exp10(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/exp10.3.html -.. _`exp10f(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/exp10f.3.html -.. _`exp10l(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/exp10l.3.html -.. _`exp2(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/exp2.3.html -.. _`exp2(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/exp2.3posix.html -.. _`exp2f(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/exp2f.3.html -.. _`exp2f(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/exp2f.3posix.html -.. _`exp2l(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/exp2l.3.html -.. _`exp2l(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/exp2l.3posix.html -.. _`exp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/exp.3.html -.. _`exp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/exp.3posix.html -.. _`expand(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/expand.1.html -.. _`expand(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/expand.1posix.html -.. _`expf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/expf.3.html -.. _`expf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/expf.3posix.html -.. _`expiry(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/expiry.1.html -.. _`expl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/expl.3.html -.. _`expl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/expl.3posix.html -.. _`expm1(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/expm1.3.html -.. _`expm1(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/expm1.3posix.html -.. _`expm1f(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/expm1f.3.html -.. _`expm1f(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/expm1f.3posix.html -.. _`expm1l(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/expm1l.3.html -.. _`expm1l(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/expm1l.3posix.html -.. _`export(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/export.1posix.html -.. _`expr(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/expr.1.html -.. _`expr(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/expr.1posix.html -.. _`extensions(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/extensions.3ncurses.html -.. _`fabs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fabs.3.html -.. _`fabs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fabs.3posix.html -.. _`fabsf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fabsf.3.html -.. _`fabsf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fabsf.3posix.html -.. _`fabsl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fabsl.3.html -.. _`fabsl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fabsl.3posix.html -.. _`faccessat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/faccessat.2.html -.. _`factor(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/factor.1.html -.. _`fadvise64(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fadvise64.2.html -.. _`fadvise64_64(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fadvise64_64.2.html -.. _`faillog(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/faillog.5.html -.. _`faillog(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/faillog.8.html -.. _`faked(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/faked.1.html -.. _`faked-sysv(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/faked-sysv.1.html -.. _`faked-tcp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/faked-tcp.1.html -.. _`fakeroot(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/fakeroot.1.html -.. _`fakeroot-sysv(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/fakeroot-sysv.1.html -.. _`fakeroot-tcp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/fakeroot-tcp.1.html -.. _`fallocate(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/fallocate.1.html -.. _`fallocate(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fallocate.2.html -.. _`false(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/false.1.html -.. _`false(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/false.1posix.html -.. _`fattach(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fattach.3posix.html -.. _`__fbufsize(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/__fbufsize.3.html -.. _`fc(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/fc.1posix.html -.. _`fchdir(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fchdir.2.html -.. _`fchdir(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fchdir.3posix.html -.. _`fchmod(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fchmod.2.html -.. _`fchmod(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fchmod.3posix.html -.. _`fchmodat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fchmodat.2.html -.. _`fchown(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fchown.2.html -.. _`fchown32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fchown32.2.html -.. _`fchown(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fchown.3posix.html -.. _`fchownat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fchownat.2.html -.. _`fclose(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fclose.3.html -.. _`fclose(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fclose.3posix.html -.. _`fcloseall(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fcloseall.3.html -.. _`fcntl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fcntl.2.html -.. _`fcntl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fcntl.3posix.html -.. _`fcntl64(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fcntl64.2.html -.. _`fcntl.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/fcntl.h.7posix.html -.. _`fcvt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fcvt.3.html -.. _`fcvt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fcvt.3posix.html -.. _`fcvt_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fcvt_r.3.html -.. _`fdatasync(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fdatasync.2.html -.. _`fdatasync(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fdatasync.3posix.html -.. _`fd_clr(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fd_clr.2.html -.. _`fd_clr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fd_clr.3.html -.. _`fd_clr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fd_clr.3posix.html -.. _`fdetach(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fdetach.3posix.html -.. _`fdformat(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/fdformat.8.html -.. _`fdim(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fdim.3.html -.. _`fdim(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fdim.3posix.html -.. _`fdimf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fdimf.3.html -.. _`fdimf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fdimf.3posix.html -.. _`fdiml(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fdiml.3.html -.. _`fdiml(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fdiml.3posix.html -.. _`fdisk(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/fdisk.8.html -.. _`fd_isset(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fd_isset.2.html -.. _`fd_isset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fd_isset.3.html -.. _`fd_isset(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fd_isset.3posix.html -.. _`fdopen(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fdopen.3.html -.. _`fdopen(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fdopen.3posix.html -.. _`fdopendir(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fdopendir.3.html -.. _`fd_set(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fd_set.2.html -.. _`fd_set(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fd_set.3.html -.. _`fd_set(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fd_set.3posix.html -.. _`fd_zero(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fd_zero.2.html -.. _`fd_zero(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fd_zero.3.html -.. _`fd_zero(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fd_zero.3posix.html -.. _`feature_test_macros(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/feature_test_macros.7.html -.. _`feclearexcept(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/feclearexcept.3.html -.. _`feclearexcept(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/feclearexcept.3posix.html -.. _`fedisableexcept(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fedisableexcept.3.html -.. _`feenableexcept(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/feenableexcept.3.html -.. _`fegetenv(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fegetenv.3.html -.. _`fegetenv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fegetenv.3posix.html -.. _`fegetexcept(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fegetexcept.3.html -.. _`fegetexceptflag(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fegetexceptflag.3.html -.. _`fegetexceptflag(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fegetexceptflag.3posix.html -.. _`fegetround(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fegetround.3.html -.. _`fegetround(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fegetround.3posix.html -.. _`feholdexcept(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/feholdexcept.3.html -.. _`feholdexcept(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/feholdexcept.3posix.html -.. _`fenv(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fenv.3.html -.. _`fenv.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/fenv.h.7posix.html -.. _`feof(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/feof.3.html -.. _`feof(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/feof.3posix.html -.. _`feof_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/feof_unlocked.3.html -.. _`feraiseexcept(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/feraiseexcept.3.html -.. _`feraiseexcept(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/feraiseexcept.3posix.html -.. _`ferror(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ferror.3.html -.. _`ferror(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ferror.3posix.html -.. _`ferror_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ferror_unlocked.3.html -.. _`fesetenv(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fesetenv.3.html -.. _`fesetenv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fesetenv.3posix.html -.. _`fesetexceptflag(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fesetexceptflag.3.html -.. _`fesetexceptflag(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fesetexceptflag.3posix.html -.. _`fesetround(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fesetround.3.html -.. _`fesetround(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fesetround.3posix.html -.. _`fetestexcept(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fetestexcept.3.html -.. _`fetestexcept(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fetestexcept.3posix.html -.. _`feupdateenv(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/feupdateenv.3.html -.. _`feupdateenv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/feupdateenv.3posix.html -.. _`fexecve(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fexecve.3.html -.. _`fflush(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fflush.3.html -.. _`fflush(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fflush.3posix.html -.. _`fflush_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fflush_unlocked.3.html -.. _`ffs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ffs.3.html -.. _`ffs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ffs.3posix.html -.. _`ffsl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ffsl.3.html -.. _`ffsll(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ffsll.3.html -.. _`fg(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/fg.1posix.html -.. _`fgetc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetc.3.html -.. _`fgetc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetc.3posix.html -.. _`fgetc_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetc_unlocked.3.html -.. _`fgetgrent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetgrent.3.html -.. _`fgetgrent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetgrent_r.3.html -.. _`fgetpos(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetpos.3.html -.. _`fgetpos(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetpos.3posix.html -.. _`fgetpwent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetpwent.3.html -.. _`fgetpwent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetpwent_r.3.html -.. _`fgets(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgets.3.html -.. _`fgets(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgets.3posix.html -.. _`fgetspent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetspent.3.html -.. _`fgetspent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetspent_r.3.html -.. _`fgets_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgets_unlocked.3.html -.. _`fgetwc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetwc.3.html -.. _`fgetwc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetwc.3posix.html -.. _`fgetwc_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetwc_unlocked.3.html -.. _`fgetws(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetws.3.html -.. _`fgetws(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetws.3posix.html -.. _`fgetws_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fgetws_unlocked.3.html -.. _`fgrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/fgrep.1.html -.. _`field(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field.3form.html -.. _`field_arg(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_arg.3form.html -.. _`field_attributes(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_attributes.3form.html -.. _`field_back(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_back.3form.html -.. _`field_buffer(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_buffer.3form.html -.. _`field_count(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_count.3form.html -.. _`field_fore(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_fore.3form.html -.. _`field_index(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_index.3form.html -.. _`field_info(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_info.3form.html -.. _`field_init(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_init.3form.html -.. _`field_just(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_just.3form.html -.. _`field_new(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_new.3form.html -.. _`field_opts(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_opts.3form.html -.. _`field_opts_off(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_opts_off.3form.html -.. _`field_opts_on(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_opts_on.3form.html -.. _`field_pad(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_pad.3form.html -.. _`field_status(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_status.3form.html -.. _`field_term(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_term.3form.html -.. _`field_type(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_type.3form.html -.. _`fieldtype(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fieldtype.3form.html -.. _`field_userptr(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_userptr.3form.html -.. _`field_validation(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/field_validation.3form.html -.. _`fifo(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/fifo.4.html -.. _`fifo(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/fifo.7.html -.. _`file(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/file.1.html -.. _`file(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/file.1posix.html -.. _`filefrag(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/filefrag.8.html -.. _`fileno(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fileno.3.html -.. _`fileno(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fileno.3posix.html -.. _`fileno_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fileno_unlocked.3.html -.. _`filesystems(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/filesystems.5.html -.. _`filter(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/filter.3ncurses.html -.. _`find(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/find.1.html -.. _`find(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/find.1posix.html -.. _`find2perl(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/find2perl.1.html -.. _`findfs(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/findfs.8.html -.. _`finite(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/finite.3.html -.. _`finitef(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/finitef.3.html -.. _`finitel(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/finitel.3.html -.. _`flash(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/flash.3ncurses.html -.. _`__flbf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/__flbf.3.html -.. _`flex(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/flex.1.html -.. _`flex++(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/flex++.1.html -.. _`float.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/float.h.7posix.html -.. _`flock(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/flock.1.html -.. _`flock(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/flock.2.html -.. _`flockfile(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/flockfile.3.html -.. _`flockfile(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/flockfile.3posix.html -.. _`floor(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/floor.3.html -.. _`floor(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/floor.3posix.html -.. _`floorf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/floorf.3.html -.. _`floorf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/floorf.3posix.html -.. _`floorl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/floorl.3.html -.. _`floorl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/floorl.3posix.html -.. _`flushinp(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/flushinp.3ncurses.html -.. _`_flushlbf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_flushlbf.3.html -.. _`fma(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fma.3.html -.. _`fma(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fma.3posix.html -.. _`fmaf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmaf.3.html -.. _`fmaf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmaf.3posix.html -.. _`fmal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmal.3.html -.. _`fmal(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmal.3posix.html -.. _`fmax(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmax.3.html -.. _`fmax(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmax.3posix.html -.. _`fmaxf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmaxf.3.html -.. _`fmaxf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmaxf.3posix.html -.. _`fmaxl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmaxl.3.html -.. _`fmaxl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmaxl.3posix.html -.. _`fmemopen(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmemopen.3.html -.. _`fmin(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmin.3.html -.. _`fmin(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmin.3posix.html -.. _`fminf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fminf.3.html -.. _`fminf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fminf.3posix.html -.. _`fminl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fminl.3.html -.. _`fminl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fminl.3posix.html -.. _`fmod(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmod.3.html -.. _`fmod(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmod.3posix.html -.. _`fmodf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmodf.3.html -.. _`fmodf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmodf.3posix.html -.. _`fmodl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmodl.3.html -.. _`fmodl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmodl.3posix.html -.. _`fmt(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/fmt.1.html -.. _`fmtmsg(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmtmsg.3.html -.. _`fmtmsg(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fmtmsg.3posix.html -.. _`fmtmsg.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/fmtmsg.h.7posix.html -.. _`fnmatch(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fnmatch.3.html -.. _`fnmatch(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fnmatch.3posix.html -.. _`fnmatch.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/fnmatch.h.7posix.html -.. _`fold(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/fold.1.html -.. _`fold(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/fold.1posix.html -.. _`fopen(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fopen.3.html -.. _`fopen(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fopen.3posix.html -.. _`fopencookie(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fopencookie.3.html -.. _`fork(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fork.2.html -.. _`fork(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fork.3posix.html -.. _`forkpty(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/forkpty.3.html -.. _`form(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form.3form.html -.. _`format(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/format.3menu.html -.. _`form_cursor(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_cursor.3form.html -.. _`form_data(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_data.3form.html -.. _`form_driver(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_driver.3form.html -.. _`form_field(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_field.3form.html -.. _`form_field_attributes(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_field_attributes.3form.html -.. _`form_field_buffer(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_field_buffer.3form.html -.. _`form_field_info(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_field_info.3form.html -.. _`form_field_just(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_field_just.3form.html -.. _`form_field_new(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_field_new.3form.html -.. _`form_field_opts(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_field_opts.3form.html -.. _`form_fields(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_fields.3form.html -.. _`form_fieldtype(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_fieldtype.3form.html -.. _`form_field_userptr(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_field_userptr.3form.html -.. _`form_field_validation(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_field_validation.3form.html -.. _`form_hook(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_hook.3form.html -.. _`form_init(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_init.3form.html -.. _`form_new(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_new.3form.html -.. _`form_new_page(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_new_page.3form.html -.. _`form_opts(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_opts.3form.html -.. _`form_opts_off(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_opts_off.3form.html -.. _`form_opts_on(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_opts_on.3form.html -.. _`form_page(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_page.3form.html -.. _`form_post(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_post.3form.html -.. _`form_request_by_name(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_request_by_name.3form.html -.. _`form_request_name(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_request_name.3form.html -.. _`form_requestname(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_requestname.3form.html -.. _`form_sub(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_sub.3form.html -.. _`form_term(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_term.3form.html -.. _`form_userptr(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_userptr.3form.html -.. _`form_win(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/form_win.3form.html -.. _`fort77(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/fort77.1posix.html -.. _`fpathconf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fpathconf.3.html -.. _`fpathconf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fpathconf.3posix.html -.. _`fpclassify(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fpclassify.3.html -.. _`fpclassify(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fpclassify.3posix.html -.. _`__fpending(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/__fpending.3.html -.. _`fprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fprintf.3.html -.. _`fprintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fprintf.3posix.html -.. _`__fpurge(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/__fpurge.3.html -.. _`fpurge(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fpurge.3.html -.. _`fputc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fputc.3.html -.. _`fputc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fputc.3posix.html -.. _`fputc_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fputc_unlocked.3.html -.. _`fputs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fputs.3.html -.. _`fputs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fputs.3posix.html -.. _`fputs_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fputs_unlocked.3.html -.. _`fputwc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fputwc.3.html -.. _`fputwc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fputwc.3posix.html -.. _`fputwc_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fputwc_unlocked.3.html -.. _`fputws(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fputws.3.html -.. _`fputws(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fputws.3posix.html -.. _`fputws_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fputws_unlocked.3.html -.. _`fread(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fread.3.html -.. _`fread(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fread.3posix.html -.. _`__freadable(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/__freadable.3.html -.. _`__freading(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/__freading.3.html -.. _`fread_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fread_unlocked.3.html -.. _`free(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/free.1.html -.. _`free(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/free.3.html -.. _`free(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/free.3posix.html -.. _`freeaddrinfo(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/freeaddrinfo.3.html -.. _`freeaddrinfo(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/freeaddrinfo.3posix.html -.. _`free_field(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/free_field.3form.html -.. _`free_fieldtype(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/free_fieldtype.3form.html -.. _`free_form(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/free_form.3form.html -.. _`freehostent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/freehostent.3.html -.. _`free_hugepages(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/free_hugepages.2.html -.. _`freeifaddrs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/freeifaddrs.3.html -.. _`free_item(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/free_item.3menu.html -.. _`free_menu(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/free_menu.3menu.html -.. _`freopen(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/freopen.3.html -.. _`freopen(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/freopen.3posix.html -.. _`frexp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/frexp.3.html -.. _`frexp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/frexp.3posix.html -.. _`frexpf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/frexpf.3.html -.. _`frexpf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/frexpf.3posix.html -.. _`frexpl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/frexpl.3.html -.. _`frexpl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/frexpl.3posix.html -.. _`from(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/from.1.html -.. _`fs(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/fs.5.html -.. _`fscanf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fscanf.3.html -.. _`fscanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fscanf.3posix.html -.. _`fsck(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/fsck.8.html -.. _`fsck.ext2(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/fsck.ext2.8.html -.. _`fsck.ext3(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/fsck.ext3.8.html -.. _`fsck.ext4(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/fsck.ext4.8.html -.. _`fsck.ext4dev(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/fsck.ext4dev.8.html -.. _`fsck.minix(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/fsck.minix.8.html -.. _`fsck.nfs(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/fsck.nfs.8.html -.. _`fseek(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fseek.3.html -.. _`fseek(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fseek.3posix.html -.. _`fseeko(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fseeko.3.html -.. _`fseeko(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fseeko.3posix.html -.. _`__fsetlocking(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/__fsetlocking.3.html -.. _`fsetpos(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fsetpos.3.html -.. _`fsetpos(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fsetpos.3posix.html -.. _`fsf-funding(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/fsf-funding.7.html -.. _`fstab(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/fstab.5.html -.. _`fstab-decode(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/fstab-decode.8.html -.. _`fstat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fstat.2.html -.. _`fstat(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fstat.3posix.html -.. _`fstat64(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fstat64.2.html -.. _`fstatat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fstatat.2.html -.. _`fstatat64(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fstatat64.2.html -.. _`fstatfs(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fstatfs.2.html -.. _`fstatfs64(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fstatfs64.2.html -.. _`fstatvfs(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fstatvfs.2.html -.. _`fstatvfs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fstatvfs.3.html -.. _`fstatvfs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fstatvfs.3posix.html -.. _`fsync(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/fsync.2.html -.. _`fsync(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fsync.3posix.html -.. _`ftell(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ftell.3.html -.. _`ftell(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ftell.3posix.html -.. _`ftello(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ftello.3.html -.. _`ftello(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ftello.3posix.html -.. _`ftime(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ftime.3.html -.. _`ftime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ftime.3posix.html -.. _`ftm(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/ftm.7.html -.. _`ftok(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ftok.3.html -.. _`ftok(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ftok.3posix.html -.. _`ftruncate(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/ftruncate.2.html -.. _`ftruncate(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ftruncate.3posix.html -.. _`ftruncate64(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/ftruncate64.2.html -.. _`ftrylockfile(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ftrylockfile.3.html -.. _`ftrylockfile(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ftrylockfile.3posix.html -.. _`fts(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fts.3.html -.. _`fts_children(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fts_children.3.html -.. _`fts_close(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fts_close.3.html -.. _`fts_open(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fts_open.3.html -.. _`fts_read(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fts_read.3.html -.. _`fts_set(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fts_set.3.html -.. _`ftw(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ftw.3.html -.. _`ftw(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ftw.3posix.html -.. _`ftw.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/ftw.h.7posix.html -.. _`full(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/full.4.html -.. _`funlockfile(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/funlockfile.3.html -.. _`funlockfile(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/funlockfile.3posix.html -.. _`fuser(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/fuser.1.html -.. _`fuser(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/fuser.1posix.html -.. _`futex(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/futex.2.html -.. _`futex(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/futex.4.html -.. _`futex(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/futex.7.html -.. _`futimens(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/futimens.3.html -.. _`futimes(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/futimes.3.html -.. _`futimesat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/futimesat.2.html -.. _`fwide(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fwide.3.html -.. _`fwide(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fwide.3posix.html -.. _`fwprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fwprintf.3.html -.. _`fwprintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fwprintf.3posix.html -.. _`__fwritable(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/__fwritable.3.html -.. _`fwrite(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fwrite.3.html -.. _`fwrite(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fwrite.3posix.html -.. _`fwrite_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fwrite_unlocked.3.html -.. _`__fwriting(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/__fwriting.3.html -.. _`fwscanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/fwscanf.3posix.html -.. _`g++(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/g++.1.html -.. _`g++-4.4(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/g++-4.4.1.html -.. _`gai.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/gai.conf.5.html -.. _`gai_strerror(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gai_strerror.3.html -.. _`gai_strerror(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gai_strerror.3posix.html -.. _`gamma(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gamma.3.html -.. _`gammaf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gammaf.3.html -.. _`gammal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gammal.3.html -.. _`gawk(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gawk.1.html -.. _`gcc(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gcc.1.html -.. _`gcc-4.4(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gcc-4.4.1.html -.. _`gcore(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gcore.1.html -.. _`gcov(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gcov.1.html -.. _`gcov-4.4(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gcov-4.4.1.html -.. _`gcvt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gcvt.3.html -.. _`gcvt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gcvt.3posix.html -.. _`gdb(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gdb.1.html -.. _`gdbm(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gdbm.3.html -.. _`gdbserver(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gdbserver.1.html -.. _`gdbtui(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gdbtui.1.html -.. _`gencat(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gencat.1.html -.. _`gencat(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gencat.1posix.html -.. _`gendsa(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gendsa.1ssl.html -.. _`genrsa(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/genrsa.1ssl.html -.. _`geqn(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/geqn.1.html -.. _`get(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/get.1posix.html -.. _`getaddrinfo(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getaddrinfo.3.html -.. _`getaddrinfo(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getaddrinfo.3posix.html -.. _`getaliasbyname(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getaliasbyname.3.html -.. _`getaliasbyname_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getaliasbyname_r.3.html -.. _`getaliasent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getaliasent.3.html -.. _`getaliasent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getaliasent_r.3.html -.. _`getbegx(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getbegx.3ncurses.html -.. _`getbegy(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getbegy.3ncurses.html -.. _`getbegyx(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getbegyx.3ncurses.html -.. _`getbkgd(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getbkgd.3ncurses.html -.. _`getbkgrnd(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getbkgrnd.3ncurses.html -.. _`getc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getc.3.html -.. _`getc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getc.3posix.html -.. _`getcchar(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getcchar.3ncurses.html -.. _`getch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getch.3ncurses.html -.. _`getchar(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getchar.3.html -.. _`getchar(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getchar.3posix.html -.. _`getchar_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getchar_unlocked.3.html -.. _`getchar_unlocked(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getchar_unlocked.3posix.html -.. _`getconf(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/getconf.1.html -.. _`getconf(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/getconf.1posix.html -.. _`getcontext(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getcontext.2.html -.. _`getcontext(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getcontext.3posix.html -.. _`getcpu(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getcpu.2.html -.. _`getc_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getc_unlocked.3.html -.. _`getc_unlocked(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getc_unlocked.3posix.html -.. _`get_current_dir_name(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/get_current_dir_name.3.html -.. _`getcurx(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getcurx.3ncurses.html -.. _`getcury(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getcury.3ncurses.html -.. _`getcwd(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getcwd.2.html -.. _`getcwd(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getcwd.3.html -.. _`getcwd(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getcwd.3posix.html -.. _`getdate(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getdate.3.html -.. _`getdate(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getdate.3posix.html -.. _`getdate_err(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getdate_err.3.html -.. _`getdate_err(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getdate_err.3posix.html -.. _`getdate_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getdate_r.3.html -.. _`getdelim(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getdelim.3.html -.. _`getdents(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getdents.2.html -.. _`getdents64(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getdents64.2.html -.. _`getdirentries(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getdirentries.3.html -.. _`getdomainname(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getdomainname.2.html -.. _`getdtablesize(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getdtablesize.2.html -.. _`getegid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getegid.2.html -.. _`getegid32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getegid32.2.html -.. _`getegid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getegid.3posix.html -.. _`getent(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/getent.1.html -.. _`getenv(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getenv.3.html -.. _`getenv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getenv.3posix.html -.. _`geteuid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/geteuid.2.html -.. _`geteuid32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/geteuid32.2.html -.. _`geteuid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/geteuid.3posix.html -.. _`getfsent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getfsent.3.html -.. _`getfsfile(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getfsfile.3.html -.. _`getfsspec(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getfsspec.3.html -.. _`getgid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getgid.2.html -.. _`getgid32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getgid32.2.html -.. _`getgid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getgid.3posix.html -.. _`getgrent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getgrent.3.html -.. _`getgrent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getgrent.3posix.html -.. _`getgrent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getgrent_r.3.html -.. _`getgrgid(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getgrgid.3.html -.. _`getgrgid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getgrgid.3posix.html -.. _`getgrgid_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getgrgid_r.3.html -.. _`getgrgid_r(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getgrgid_r.3posix.html -.. _`getgrnam(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getgrnam.3.html -.. _`getgrnam(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getgrnam.3posix.html -.. _`getgrnam_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getgrnam_r.3.html -.. _`getgrnam_r(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getgrnam_r.3posix.html -.. _`getgrouplist(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getgrouplist.3.html -.. _`getgroups(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getgroups.2.html -.. _`getgroups32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getgroups32.2.html -.. _`getgroups(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getgroups.3posix.html -.. _`gethostbyaddr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gethostbyaddr.3.html -.. _`gethostbyaddr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gethostbyaddr.3posix.html -.. _`gethostbyaddr_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gethostbyaddr_r.3.html -.. _`gethostbyname2(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gethostbyname2.3.html -.. _`gethostbyname2_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gethostbyname2_r.3.html -.. _`gethostbyname(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gethostbyname.3.html -.. _`gethostbyname(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gethostbyname.3posix.html -.. _`gethostbyname_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gethostbyname_r.3.html -.. _`gethostent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gethostent.3.html -.. _`gethostent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gethostent.3posix.html -.. _`gethostent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gethostent_r.3.html -.. _`gethostid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/gethostid.2.html -.. _`gethostid(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gethostid.3.html -.. _`gethostid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gethostid.3posix.html -.. _`gethostname(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/gethostname.2.html -.. _`gethostname(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gethostname.3posix.html -.. _`getifaddrs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getifaddrs.3.html -.. _`getipnodebyaddr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getipnodebyaddr.3.html -.. _`getipnodebyname(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getipnodebyname.3.html -.. _`getitimer(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getitimer.2.html -.. _`getitimer(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getitimer.3posix.html -.. _`getline(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getline.3.html -.. _`getloadavg(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getloadavg.3.html -.. _`getlogin(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getlogin.3.html -.. _`getlogin(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getlogin.3posix.html -.. _`getlogin_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getlogin_r.3.html -.. _`getlogin_r(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getlogin_r.3posix.html -.. _`getmaxx(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getmaxx.3ncurses.html -.. _`getmaxy(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getmaxy.3ncurses.html -.. _`getmaxyx(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getmaxyx.3ncurses.html -.. _`get_mempolicy(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/get_mempolicy.2.html -.. _`getmntent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getmntent.3.html -.. _`getmntent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getmntent_r.3.html -.. _`getmouse(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getmouse.3ncurses.html -.. _`getmsg(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getmsg.3posix.html -.. _`get_myaddress(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/get_myaddress.3.html -.. _`getnameinfo(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getnameinfo.3.html -.. _`getnameinfo(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getnameinfo.3posix.html -.. _`getnetbyaddr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getnetbyaddr.3.html -.. _`getnetbyaddr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getnetbyaddr.3posix.html -.. _`getnetbyaddr_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getnetbyaddr_r.3.html -.. _`getnetbyname(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getnetbyname.3.html -.. _`getnetbyname(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getnetbyname.3posix.html -.. _`getnetbyname_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getnetbyname_r.3.html -.. _`getnetent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getnetent.3.html -.. _`getnetent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getnetent.3posix.html -.. _`getnetent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getnetent_r.3.html -.. _`getnetgrent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getnetgrent.3.html -.. _`getnetgrent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getnetgrent_r.3.html -.. _`getnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getnstr.3ncurses.html -.. _`getn_wstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getn_wstr.3ncurses.html -.. _`getopt(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/getopt.1.html -.. _`getopt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getopt.3.html -.. _`getopt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getopt.3posix.html -.. _`getopt_long(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getopt_long.3.html -.. _`getopt_long_only(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getopt_long_only.3.html -.. _`getopts(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/getopts.1posix.html -.. _`getpagesize(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getpagesize.2.html -.. _`getparx(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getparx.3ncurses.html -.. _`getpary(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpary.3ncurses.html -.. _`getparyx(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getparyx.3ncurses.html -.. _`getpass(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpass.3.html -.. _`getpeername(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getpeername.2.html -.. _`getpeername(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpeername.3posix.html -.. _`getpgid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getpgid.2.html -.. _`getpgid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpgid.3posix.html -.. _`getpgrp(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getpgrp.2.html -.. _`getpgrp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpgrp.3posix.html -.. _`getpid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getpid.2.html -.. _`getpid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpid.3posix.html -.. _`getpmsg(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getpmsg.2.html -.. _`getpmsg(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpmsg.3posix.html -.. _`getppid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getppid.2.html -.. _`getppid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getppid.3posix.html -.. _`getpriority(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getpriority.2.html -.. _`getpriority(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpriority.3posix.html -.. _`getprotobyname(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getprotobyname.3.html -.. _`getprotobyname(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getprotobyname.3posix.html -.. _`getprotobyname_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getprotobyname_r.3.html -.. _`getprotobynumber(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getprotobynumber.3.html -.. _`getprotobynumber(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getprotobynumber.3posix.html -.. _`getprotobynumber_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getprotobynumber_r.3.html -.. _`getprotoent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getprotoent.3.html -.. _`getprotoent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getprotoent.3posix.html -.. _`getprotoent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getprotoent_r.3.html -.. _`getpt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpt.3.html -.. _`getpw(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpw.3.html -.. _`getpwent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpwent.3.html -.. _`getpwent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpwent.3posix.html -.. _`getpwent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpwent_r.3.html -.. _`getpwnam(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpwnam.3.html -.. _`getpwnam(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpwnam.3posix.html -.. _`getpwnam_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpwnam_r.3.html -.. _`getpwnam_r(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpwnam_r.3posix.html -.. _`getpwuid(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpwuid.3.html -.. _`getpwuid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpwuid.3posix.html -.. _`getpwuid_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpwuid_r.3.html -.. _`getpwuid_r(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getpwuid_r.3posix.html -.. _`getresgid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getresgid.2.html -.. _`getresgid32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getresgid32.2.html -.. _`getresuid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getresuid.2.html -.. _`getresuid32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getresuid32.2.html -.. _`getrlimit(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getrlimit.2.html -.. _`getrlimit(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getrlimit.3posix.html -.. _`getrpcbyname(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getrpcbyname.3.html -.. _`getrpcbyname_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getrpcbyname_r.3.html -.. _`getrpcbynumber(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getrpcbynumber.3.html -.. _`getrpcbynumber_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getrpcbynumber_r.3.html -.. _`getrpcent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getrpcent.3.html -.. _`getrpcent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getrpcent_r.3.html -.. _`getrpcport(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getrpcport.3.html -.. _`getrusage(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getrusage.2.html -.. _`getrusage(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getrusage.3posix.html -.. _`gets(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gets.3.html -.. _`gets(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gets.3posix.html -.. _`getservbyname(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getservbyname.3.html -.. _`getservbyname(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getservbyname.3posix.html -.. _`getservbyname_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getservbyname_r.3.html -.. _`getservbyport(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getservbyport.3.html -.. _`getservbyport(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getservbyport.3posix.html -.. _`getservbyport_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getservbyport_r.3.html -.. _`getservent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getservent.3.html -.. _`getservent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getservent.3posix.html -.. _`getservent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getservent_r.3.html -.. _`getsid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getsid.2.html -.. _`getsid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getsid.3posix.html -.. _`getsockname(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getsockname.2.html -.. _`getsockname(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getsockname.3posix.html -.. _`getsockopt(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getsockopt.2.html -.. _`getsockopt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getsockopt.3posix.html -.. _`getspent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getspent.3.html -.. _`getspent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getspent_r.3.html -.. _`getspnam(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getspnam.3.html -.. _`getspnam_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getspnam_r.3.html -.. _`getstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getstr.3ncurses.html -.. _`getsubopt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getsubopt.3.html -.. _`getsubopt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getsubopt.3posix.html -.. _`getsyx(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getsyx.3ncurses.html -.. _`get_thread_area(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/get_thread_area.2.html -.. _`gettid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/gettid.2.html -.. _`gettimeofday(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/gettimeofday.2.html -.. _`gettimeofday(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gettimeofday.3posix.html -.. _`getttyent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getttyent.3.html -.. _`getttynam(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getttynam.3.html -.. _`getty(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/getty.8.html -.. _`getuid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getuid.2.html -.. _`getuid32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/getuid32.2.html -.. _`getuid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getuid.3posix.html -.. _`getumask(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getumask.3.html -.. _`getusershell(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getusershell.3.html -.. _`getutent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getutent.3.html -.. _`getutent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getutent_r.3.html -.. _`getutid(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getutid.3.html -.. _`getutid_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getutid_r.3.html -.. _`getutline(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getutline.3.html -.. _`getutline_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getutline_r.3.html -.. _`getutmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getutmp.3.html -.. _`getutmpx(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getutmpx.3.html -.. _`getutxent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getutxent.3.html -.. _`getutxent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getutxent.3posix.html -.. _`getutxid(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getutxid.3.html -.. _`getutxid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getutxid.3posix.html -.. _`getutxline(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getutxline.3.html -.. _`getutxline(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getutxline.3posix.html -.. _`getw(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getw.3.html -.. _`getwc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getwc.3.html -.. _`getwc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getwc.3posix.html -.. _`get_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/get_wch.3ncurses.html -.. _`getwchar(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getwchar.3.html -.. _`getwchar(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getwchar.3posix.html -.. _`getwchar_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getwchar_unlocked.3.html -.. _`getwc_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getwc_unlocked.3.html -.. _`getwd(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getwd.3.html -.. _`getwd(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getwd.3posix.html -.. _`getwin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getwin.3ncurses.html -.. _`get_wstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/get_wstr.3ncurses.html -.. _`getyx(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/getyx.3ncurses.html -.. _`gfdl(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/gfdl.7.html -.. _`ginstall-info(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ginstall-info.1.html -.. _`git(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git.1.html -.. _`git(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/git.3pm.html -.. _`git-add(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-add.1.html -.. _`git-am(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-am.1.html -.. _`git-annotate(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-annotate.1.html -.. _`git-apply(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-apply.1.html -.. _`git-archive(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-archive.1.html -.. _`gitattributes(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/gitattributes.5.html -.. _`git-bisect(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-bisect.1.html -.. _`git-blame(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-blame.1.html -.. _`git-branch(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-branch.1.html -.. _`git-bundle(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-bundle.1.html -.. _`git-cat-file(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-cat-file.1.html -.. _`git-check-attr(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-check-attr.1.html -.. _`git-checkout(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-checkout.1.html -.. _`git-checkout-index(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-checkout-index.1.html -.. _`git-check-ref-format(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-check-ref-format.1.html -.. _`git-cherry(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-cherry.1.html -.. _`git-cherry-pick(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-cherry-pick.1.html -.. _`git-clean(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-clean.1.html -.. _`gitcli(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/gitcli.7.html -.. _`git-clone(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-clone.1.html -.. _`git-commit(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-commit.1.html -.. _`git-commit-tree(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-commit-tree.1.html -.. _`git-config(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-config.1.html -.. _`gitcore-tutorial(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/gitcore-tutorial.7.html -.. _`git-count-objects(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-count-objects.1.html -.. _`gitcvs-migration(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/gitcvs-migration.7.html -.. _`git-daemon(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-daemon.1.html -.. _`git-describe(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-describe.1.html -.. _`git-diff(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-diff.1.html -.. _`gitdiffcore(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/gitdiffcore.7.html -.. _`git-diff-files(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-diff-files.1.html -.. _`git-diff-index(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-diff-index.1.html -.. _`git-difftool(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-difftool.1.html -.. _`git-diff-tree(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-diff-tree.1.html -.. _`git-fast-export(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-fast-export.1.html -.. _`git-fast-import(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-fast-import.1.html -.. _`git-fetch(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-fetch.1.html -.. _`git-fetch-pack(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-fetch-pack.1.html -.. _`git-filter-branch(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-filter-branch.1.html -.. _`git-fmt-merge-msg(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-fmt-merge-msg.1.html -.. _`git-for-each-ref(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-for-each-ref.1.html -.. _`git-format-patch(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-format-patch.1.html -.. _`git-fsck(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-fsck.1.html -.. _`git-fsck-objects(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-fsck-objects.1.html -.. _`git-gc(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-gc.1.html -.. _`git-get-tar-commit-id(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-get-tar-commit-id.1.html -.. _`gitglossary(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/gitglossary.7.html -.. _`git-grep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-grep.1.html -.. _`git-hash-object(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-hash-object.1.html -.. _`git-help(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-help.1.html -.. _`githooks(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/githooks.5.html -.. _`git-http-backend(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-http-backend.1.html -.. _`git-http-fetch(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-http-fetch.1.html -.. _`git-http-push(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-http-push.1.html -.. _`gitignore(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/gitignore.5.html -.. _`git-imap-send(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-imap-send.1.html -.. _`git-index-pack(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-index-pack.1.html -.. _`git-init(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-init.1.html -.. _`git-init-db(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-init-db.1.html -.. _`git-instaweb(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-instaweb.1.html -.. _`git-log(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-log.1.html -.. _`git-lost-found(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-lost-found.1.html -.. _`git-ls-files(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-ls-files.1.html -.. _`git-ls-remote(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-ls-remote.1.html -.. _`git-ls-tree(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-ls-tree.1.html -.. _`git-mailinfo(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-mailinfo.1.html -.. _`git-mailsplit(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-mailsplit.1.html -.. _`git-merge(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-merge.1.html -.. _`git-merge-base(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-merge-base.1.html -.. _`git-merge-file(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-merge-file.1.html -.. _`git-merge-index(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-merge-index.1.html -.. _`git-merge-one-file(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-merge-one-file.1.html -.. _`git-mergetool(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-mergetool.1.html -.. _`git-mergetool--lib(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-mergetool--lib.1.html -.. _`git-merge-tree(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-merge-tree.1.html -.. _`git-mktag(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-mktag.1.html -.. _`git-mktree(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-mktree.1.html -.. _`gitmodules(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/gitmodules.5.html -.. _`git-mv(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-mv.1.html -.. _`git-name-rev(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-name-rev.1.html -.. _`git-notes(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-notes.1.html -.. _`git-pack-objects(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-pack-objects.1.html -.. _`git-pack-redundant(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-pack-redundant.1.html -.. _`git-pack-refs(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-pack-refs.1.html -.. _`git-parse-remote(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-parse-remote.1.html -.. _`git-patch-id(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-patch-id.1.html -.. _`git-peek-remote(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-peek-remote.1.html -.. _`git-prune(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-prune.1.html -.. _`git-prune-packed(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-prune-packed.1.html -.. _`git-pull(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-pull.1.html -.. _`git-push(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-push.1.html -.. _`git-quiltimport(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-quiltimport.1.html -.. _`git-read-tree(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-read-tree.1.html -.. _`git-rebase(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-rebase.1.html -.. _`git-receive-pack(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-receive-pack.1.html -.. _`git-reflog(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-reflog.1.html -.. _`git-relink(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-relink.1.html -.. _`git-remote(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-remote.1.html -.. _`git-remote-helpers(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-remote-helpers.1.html -.. _`git-repack(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-repack.1.html -.. _`git-replace(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-replace.1.html -.. _`git-repo-config(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-repo-config.1.html -.. _`gitrepository-layout(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/gitrepository-layout.5.html -.. _`git-request-pull(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-request-pull.1.html -.. _`git-rerere(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-rerere.1.html -.. _`git-reset(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-reset.1.html -.. _`git-revert(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-revert.1.html -.. _`gitrevisions(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/gitrevisions.7.html -.. _`git-rev-list(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-rev-list.1.html -.. _`git-rev-parse(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-rev-parse.1.html -.. _`git-rm(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-rm.1.html -.. _`git-send-pack(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-send-pack.1.html -.. _`git-shell(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-shell.1.html -.. _`git-shortlog(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-shortlog.1.html -.. _`git-show(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-show.1.html -.. _`git-show-branch(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-show-branch.1.html -.. _`git-show-index(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-show-index.1.html -.. _`git-show-ref(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-show-ref.1.html -.. _`git-sh-setup(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-sh-setup.1.html -.. _`git-stage(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-stage.1.html -.. _`git-stash(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-stash.1.html -.. _`git-status(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-status.1.html -.. _`git-stripspace(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-stripspace.1.html -.. _`git-submodule(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-submodule.1.html -.. _`git-symbolic-ref(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-symbolic-ref.1.html -.. _`git-tag(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-tag.1.html -.. _`git-tar-tree(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-tar-tree.1.html -.. _`gittutorial-2(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/gittutorial-2.7.html -.. _`gittutorial(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/gittutorial.7.html -.. _`git-unpack-file(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-unpack-file.1.html -.. _`git-unpack-objects(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-unpack-objects.1.html -.. _`git-update-index(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-update-index.1.html -.. _`git-update-ref(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-update-ref.1.html -.. _`git-update-server-info(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-update-server-info.1.html -.. _`git-upload-archive(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-upload-archive.1.html -.. _`git-upload-pack(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-upload-pack.1.html -.. _`git-var(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-var.1.html -.. _`git-verify-pack(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-verify-pack.1.html -.. _`git-verify-tag(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-verify-tag.1.html -.. _`git-web--browse(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-web--browse.1.html -.. _`git-whatchanged(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-whatchanged.1.html -.. _`gitworkflows(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/gitworkflows.7.html -.. _`git-write-tree(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/git-write-tree.1.html -.. _`glibc(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/glibc.7.html -.. _`glob(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/glob.3.html -.. _`glob(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/glob.3posix.html -.. _`glob(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/glob.7.html -.. _`globfree(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/globfree.3.html -.. _`globfree(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/globfree.3posix.html -.. _`glob.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/glob.h.7posix.html -.. _`gmtime(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gmtime.3.html -.. _`gmtime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gmtime.3posix.html -.. _`gmtime_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gmtime_r.3.html -.. _`gmtime_r(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gmtime_r.3posix.html -.. _`gnu_dev_major(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gnu_dev_major.3.html -.. _`gnu_dev_makedev(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gnu_dev_makedev.3.html -.. _`gnu_dev_minor(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gnu_dev_minor.3.html -.. _`gnu_get_libc_release(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gnu_get_libc_release.3.html -.. _`gnu_get_libc_version(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gnu_get_libc_version.3.html -.. _`gnupg(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/gnupg.7.html -.. _`gold(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gold.1.html -.. _`gpasswd(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gpasswd.1.html -.. _`gpg(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gpg.1.html -.. _`gpgsplit(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gpgsplit.1.html -.. _`gpgv(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gpgv.1.html -.. _`gpg-zip(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gpg-zip.1.html -.. _`gpic(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gpic.1.html -.. _`gpl(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/gpl.7.html -.. _`gprof(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gprof.1.html -.. _`grantpt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/grantpt.3.html -.. _`grantpt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/grantpt.3posix.html -.. _`grep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/grep.1.html -.. _`grep(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/grep.1posix.html -.. _`groff(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/groff.1.html -.. _`grog(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/grog.1.html -.. _`grops(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/grops.1.html -.. _`grotty(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/grotty.1.html -.. _`group(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/group.5.html -.. _`groupadd(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/groupadd.8.html -.. _`group.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/group.conf.5.html -.. _`groupdel(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/groupdel.8.html -.. _`groupmod(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/groupmod.8.html -.. _`groups(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/groups.1.html -.. _`grpck(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/grpck.8.html -.. _`grpconv(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/grpconv.8.html -.. _`grp.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/grp.h.7posix.html -.. _`grpunconv(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/grpunconv.8.html -.. _`gshadow(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/gshadow.5.html -.. _`gsignal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/gsignal.3.html -.. _`gtbl(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gtbl.1.html -.. _`gtty(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/gtty.2.html -.. _`gunzip(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gunzip.1.html -.. _`gzexe(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gzexe.1.html -.. _`gzip(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/gzip.1.html -.. _`h2ph(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/h2ph.1.html -.. _`h2xs(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/h2xs.1.html -.. _`halfdelay(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/halfdelay.3ncurses.html -.. _`halt(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/halt.5.html -.. _`halt(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/halt.8.html -.. _`has_colors(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/has_colors.3ncurses.html -.. _`hash(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/hash.1posix.html -.. _`hash(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hash.3.html -.. _`has_ic(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/has_ic.3ncurses.html -.. _`has_il(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/has_il.3ncurses.html -.. _`has_key(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/has_key.3ncurses.html -.. _`hasmntopt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hasmntopt.3.html -.. _`has_mouse(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/has_mouse.3ncurses.html -.. _`hcreate(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hcreate.3.html -.. _`hcreate(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hcreate.3posix.html -.. _`hcreate_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hcreate_r.3.html -.. _`hd(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/hd.1.html -.. _`hd(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/hd.4.html -.. _`hdestroy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hdestroy.3.html -.. _`hdestroy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hdestroy.3posix.html -.. _`hdestroy_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hdestroy_r.3.html -.. _`head(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/head.1.html -.. _`head(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/head.1posix.html -.. _`heirloom-mailx(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/heirloom-mailx.1.html -.. _`helpztags(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/helpztags.1.html -.. _`h_errno(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/h_errno.3.html -.. _`h_errno(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/h_errno.3posix.html -.. _`herror(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/herror.3.html -.. _`hexdump(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/hexdump.1.html -.. _`hg(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/hg.1.html -.. _`hgignore(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/hgignore.5.html -.. _`hgrc(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/hgrc.5.html -.. _`hg-ssh(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/hg-ssh.8.html -.. _`hide_panel(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hide_panel.3curses.html -.. _`hier(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/hier.7.html -.. _`history(3readline)` : http://sites.uclouvain.be/SystInfo/manpages/man3/history.3readline.html -.. _`hline(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hline.3ncurses.html -.. _`hline_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hline_set.3ncurses.html -.. _`hman(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/hman.1.html -.. _`hook(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hook.3form.html -.. _`hook(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hook.3menu.html -.. _`host.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/host.conf.5.html -.. _`hostid(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/hostid.1.html -.. _`hostname(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/hostname.1.html -.. _`hostname(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/hostname.7.html -.. _`hosts(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/hosts.5.html -.. _`hosts_access(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/hosts_access.5.html -.. _`hosts.allow(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/hosts.allow.5.html -.. _`hosts.deny(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/hosts.deny.5.html -.. _`hosts.equiv(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/hosts.equiv.5.html -.. _`hosts_options(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/hosts_options.5.html -.. _`hsearch(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hsearch.3.html -.. _`hsearch(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hsearch.3posix.html -.. _`hsearch_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hsearch_r.3.html -.. _`hstrerror(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hstrerror.3.html -.. _`htcacheclean(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/htcacheclean.8.html -.. _`htdbm(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/htdbm.1.html -.. _`htdigest(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/htdigest.1.html -.. _`htobe16(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/htobe16.3.html -.. _`htobe32(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/htobe32.3.html -.. _`htobe64(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/htobe64.3.html -.. _`htole16(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/htole16.3.html -.. _`htole32(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/htole32.3.html -.. _`htole64(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/htole64.3.html -.. _`htonl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/htonl.3.html -.. _`htonl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/htonl.3posix.html -.. _`htons(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/htons.3.html -.. _`htons(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/htons.3posix.html -.. _`htpasswd(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/htpasswd.1.html -.. _`httxt2dbm(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/httxt2dbm.8.html -.. _`huge_val(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/huge_val.3.html -.. _`huge_valf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/huge_valf.3.html -.. _`huge_vall(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/huge_vall.3.html -.. _`hwclock(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/hwclock.8.html -.. _`hypot(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hypot.3.html -.. _`hypot(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hypot.3posix.html -.. _`hypotf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hypotf.3.html -.. _`hypotf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hypotf.3posix.html -.. _`hypotl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hypotl.3.html -.. _`hypotl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/hypotl.3posix.html -.. _`i386(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/i386.8.html -.. _`icmp(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/icmp.7.html -.. _`iconv(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/iconv.1.html -.. _`iconv(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/iconv.1posix.html -.. _`iconv(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iconv.3.html -.. _`iconv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iconv.3posix.html -.. _`iconv_close(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iconv_close.3.html -.. _`iconv_close(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iconv_close.3posix.html -.. _`iconvconfig(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/iconvconfig.8.html -.. _`iconv.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iconv.h.7posix.html -.. _`iconv_open(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iconv_open.3.html -.. _`iconv_open(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iconv_open.3posix.html -.. _`id(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/id.1.html -.. _`id(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/id.1posix.html -.. _`idcok(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/idcok.3ncurses.html -.. _`idle(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/idle.2.html -.. _`idlok(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/idlok.3ncurses.html -.. _`ifconfig(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ifconfig.8.html -.. _`ifdown(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ifdown.8.html -.. _`if_freenameindex(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/if_freenameindex.3posix.html -.. _`if.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/if.h.7posix.html -.. _`if_indextoname(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/if_indextoname.3posix.html -.. _`if_nameindex(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/if_nameindex.3posix.html -.. _`if_nametoindex(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/if_nametoindex.3posix.html -.. _`ifup(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ifup.8.html -.. _`igawk(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/igawk.1.html -.. _`ilogb(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ilogb.3.html -.. _`ilogb(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ilogb.3posix.html -.. _`ilogbf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ilogbf.3.html -.. _`ilogbf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ilogbf.3posix.html -.. _`ilogbl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ilogbl.3.html -.. _`ilogbl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ilogbl.3posix.html -.. _`imaxabs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/imaxabs.3.html -.. _`imaxabs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/imaxabs.3posix.html -.. _`imaxdiv(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/imaxdiv.3.html -.. _`imaxdiv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/imaxdiv.3posix.html -.. _`immedok(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/immedok.3ncurses.html -.. _`inb(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/inb.2.html -.. _`inb_p(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/inb_p.2.html -.. _`inch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inch.3ncurses.html -.. _`inchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inchnstr.3ncurses.html -.. _`inchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inchstr.3ncurses.html -.. _`index(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/index.3.html -.. _`index(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/index.3posix.html -.. _`inet(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inet.3.html -.. _`inet_addr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inet_addr.3.html -.. _`inet_addr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inet_addr.3posix.html -.. _`inet_aton(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inet_aton.3.html -.. _`inet.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/inet.h.7posix.html -.. _`inet_lnaof(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inet_lnaof.3.html -.. _`inet_makeaddr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inet_makeaddr.3.html -.. _`inet_netof(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inet_netof.3.html -.. _`inet_network(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inet_network.3.html -.. _`inet_ntoa(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inet_ntoa.3.html -.. _`inet_ntoa(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inet_ntoa.3posix.html -.. _`inet_ntop(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inet_ntop.3.html -.. _`inet_ntop(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inet_ntop.3posix.html -.. _`inet_pton(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inet_pton.3.html -.. _`inet_pton(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inet_pton.3posix.html -.. _`infinity(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/infinity.3.html -.. _`info(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/info.1.html -.. _`info(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/info.5.html -.. _`infobrowser(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/infobrowser.1.html -.. _`infocmp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/infocmp.1.html -.. _`infokey(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/infokey.1.html -.. _`infotocap(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/infotocap.1.html -.. _`in.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/in.h.7posix.html -.. _`init(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/init.8.html -.. _`init_color(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/init_color.3ncurses.html -.. _`initgroups(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/initgroups.3.html -.. _`init_pair(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/init_pair.3ncurses.html -.. _`initramfs.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/initramfs.conf.5.html -.. _`initramfs-tools(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/initramfs-tools.8.html -.. _`initrd(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/initrd.4.html -.. _`initscr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/initscr.3ncurses.html -.. _`initscript(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/initscript.5.html -.. _`initstate(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/initstate.3.html -.. _`initstate(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/initstate.3posix.html -.. _`initstate_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/initstate_r.3.html -.. _`inittab(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/inittab.5.html -.. _`inl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/inl.2.html -.. _`inl_p(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/inl_p.2.html -.. _`innetgr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/innetgr.3.html -.. _`innstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/innstr.3ncurses.html -.. _`innwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/innwstr.3ncurses.html -.. _`inopts(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inopts.3ncurses.html -.. _`inotify(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/inotify.7.html -.. _`inotify_add_watch(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/inotify_add_watch.2.html -.. _`inotify_init1(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/inotify_init1.2.html -.. _`inotify_init(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/inotify_init.2.html -.. _`inotify_rm_watch(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/inotify_rm_watch.2.html -.. _`insb(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/insb.2.html -.. _`insch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/insch.3ncurses.html -.. _`insdelln(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/insdelln.3ncurses.html -.. _`insertln(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/insertln.3ncurses.html -.. _`insl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/insl.2.html -.. _`insmod(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/insmod.8.html -.. _`insnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/insnstr.3ncurses.html -.. _`ins_nwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ins_nwstr.3ncurses.html -.. _`insque(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/insque.3.html -.. _`insque(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/insque.3posix.html -.. _`insserv(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/insserv.8.html -.. _`insstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/insstr.3ncurses.html -.. _`install(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/install.1.html -.. _`install-info(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/install-info.1.html -.. _`installkernel(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/installkernel.8.html -.. _`install-sgmlcatalog(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/install-sgmlcatalog.8.html -.. _`instmodsh(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/instmodsh.1.html -.. _`instr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/instr.3ncurses.html -.. _`insw(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/insw.2.html -.. _`ins_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ins_wch.3ncurses.html -.. _`ins_wstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ins_wstr.3ncurses.html -.. _`interfaces(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/interfaces.5.html -.. _`intrflush(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/intrflush.3ncurses.html -.. _`intro(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/intro.1.html -.. _`intro(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/intro.2.html -.. _`intro(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/intro.3.html -.. _`intro(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/intro.4.html -.. _`intro(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/intro.5.html -.. _`intro(6)` : http://sites.uclouvain.be/SystInfo/manpages/man6/intro.6.html -.. _`intro(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/intro.7.html -.. _`intro(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/intro.8.html -.. _`inttypes.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/inttypes.h.7posix.html -.. _`invoke-rc.d(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/invoke-rc.d.8.html -.. _`inw(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/inw.2.html -.. _`in_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/in_wch.3ncurses.html -.. _`in_wchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/in_wchnstr.3ncurses.html -.. _`in_wchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/in_wchstr.3ncurses.html -.. _`inw_p(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/inw_p.2.html -.. _`inwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/inwstr.3ncurses.html -.. _`io_cancel(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/io_cancel.2.html -.. _`ioctl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/ioctl.2.html -.. _`ioctl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ioctl.3posix.html -.. _`ioctl_list(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/ioctl_list.2.html -.. _`io_destroy(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/io_destroy.2.html -.. _`io_getevents(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/io_getevents.2.html -.. _`ionice(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ionice.1.html -.. _`ioperm(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/ioperm.2.html -.. _`iopl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/iopl.2.html -.. _`ioprio_get(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/ioprio_get.2.html -.. _`ioprio_set(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/ioprio_set.2.html -.. _`io_setup(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/io_setup.2.html -.. _`io_submit(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/io_submit.2.html -.. _`ip6tables(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ip6tables.8.html -.. _`ip6tables-apply(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ip6tables-apply.8.html -.. _`ip6tables-restore(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ip6tables-restore.8.html -.. _`ip6tables-save(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ip6tables-save.8.html -.. _`ip(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/ip.7.html -.. _`ip(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ip.8.html -.. _`ipc(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/ipc.2.html -.. _`ipc(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/ipc.5.html -.. _`ipc.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/ipc.h.7posix.html -.. _`ipcmk(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ipcmk.1.html -.. _`ipcrm(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ipcrm.1.html -.. _`ipcrm(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ipcrm.1posix.html -.. _`ipcs(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ipcs.1.html -.. _`ipcs(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ipcs.1posix.html -.. _`iperf(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/iperf.1.html -.. _`ipproto_icmp(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/ipproto_icmp.7.html -.. _`iptables(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/iptables.8.html -.. _`iptables-apply(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/iptables-apply.8.html -.. _`iptables-restore(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/iptables-restore.8.html -.. _`iptables-save(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/iptables-save.8.html -.. _`iptables-xml(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/iptables-xml.8.html -.. _`ipv6(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/ipv6.7.html -.. _`iruserok(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iruserok.3.html -.. _`isalnum(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isalnum.3.html -.. _`isalnum(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isalnum.3posix.html -.. _`isalpha(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isalpha.3.html -.. _`isalpha(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isalpha.3posix.html -.. _`isascii(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isascii.3.html -.. _`isascii(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isascii.3posix.html -.. _`isastream(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isastream.3posix.html -.. _`isatty(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isatty.3.html -.. _`isatty(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isatty.3posix.html -.. _`isblank(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isblank.3.html -.. _`isblank(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isblank.3posix.html -.. _`is_cleared(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/is_cleared.3ncurses.html -.. _`iscntrl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iscntrl.3.html -.. _`iscntrl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iscntrl.3posix.html -.. _`isdigit(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isdigit.3.html -.. _`isdigit(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isdigit.3posix.html -.. _`isendwin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isendwin.3ncurses.html -.. _`isfinite(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isfinite.3.html -.. _`isfinite(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isfinite.3posix.html -.. _`isgraph(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isgraph.3.html -.. _`isgraph(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isgraph.3posix.html -.. _`isgreater(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isgreater.3.html -.. _`isgreater(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isgreater.3posix.html -.. _`isgreaterequal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isgreaterequal.3.html -.. _`isgreaterequal(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isgreaterequal.3posix.html -.. _`is_idcok(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/is_idcok.3ncurses.html -.. _`is_idlok(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/is_idlok.3ncurses.html -.. _`is_immedok(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/is_immedok.3ncurses.html -.. _`isinf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isinf.3.html -.. _`isinf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isinf.3posix.html -.. _`isinff(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isinff.3.html -.. _`isinfl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isinfl.3.html -.. _`is_keypad(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/is_keypad.3ncurses.html -.. _`is_leaveok(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/is_leaveok.3ncurses.html -.. _`isless(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isless.3.html -.. _`isless(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isless.3posix.html -.. _`islessequal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/islessequal.3.html -.. _`islessequal(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/islessequal.3posix.html -.. _`islessgreater(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/islessgreater.3.html -.. _`islessgreater(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/islessgreater.3posix.html -.. _`is_linetouched(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/is_linetouched.3ncurses.html -.. _`islower(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/islower.3.html -.. _`islower(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/islower.3posix.html -.. _`isnan(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isnan.3.html -.. _`isnan(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isnan.3posix.html -.. _`isnanf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isnanf.3.html -.. _`isnanl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isnanl.3.html -.. _`is_nodelay(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/is_nodelay.3ncurses.html -.. _`isnormal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isnormal.3.html -.. _`isnormal(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isnormal.3posix.html -.. _`is_notimeout(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/is_notimeout.3ncurses.html -.. _`iso646.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso646.h.7posix.html -.. _`iso_8859_10(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859_10.7.html -.. _`iso_8859-10(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859-10.7.html -.. _`iso-8859-10(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso-8859-10.7.html -.. _`iso_8859_11(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859_11.7.html -.. _`iso_8859-11(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859-11.7.html -.. _`iso-8859-11(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso-8859-11.7.html -.. _`iso_8859_13(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859_13.7.html -.. _`iso_8859-13(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859-13.7.html -.. _`iso-8859-13(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso-8859-13.7.html -.. _`iso_8859_14(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859_14.7.html -.. _`iso_8859-14(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859-14.7.html -.. _`iso-8859-14(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso-8859-14.7.html -.. _`iso_8859_15(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859_15.7.html -.. _`iso_8859-15(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859-15.7.html -.. _`iso-8859-15(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso-8859-15.7.html -.. _`iso_8859_16(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859_16.7.html -.. _`iso_8859-16(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859-16.7.html -.. _`iso-8859-16(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso-8859-16.7.html -.. _`iso_8859_1(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859_1.7.html -.. _`iso_8859-1(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859-1.7.html -.. _`iso-8859-1(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso-8859-1.7.html -.. _`iso_8859_2(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859_2.7.html -.. _`iso_8859-2(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859-2.7.html -.. _`iso-8859-2(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso-8859-2.7.html -.. _`iso_8859_3(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859_3.7.html -.. _`iso_8859-3(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859-3.7.html -.. _`iso-8859-3(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso-8859-3.7.html -.. _`iso_8859_4(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859_4.7.html -.. _`iso_8859-4(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859-4.7.html -.. _`iso-8859-4(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso-8859-4.7.html -.. _`iso_8859_5(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859_5.7.html -.. _`iso_8859-5(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859-5.7.html -.. _`iso-8859-5(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso-8859-5.7.html -.. _`iso_8859_6(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859_6.7.html -.. _`iso_8859-6(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859-6.7.html -.. _`iso-8859-6(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso-8859-6.7.html -.. _`iso_8859_7(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859_7.7.html -.. _`iso_8859-7(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859-7.7.html -.. _`iso-8859-7(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso-8859-7.7.html -.. _`iso_8859_8(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859_8.7.html -.. _`iso_8859-8(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859-8.7.html -.. _`iso-8859-8(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso-8859-8.7.html -.. _`iso_8859_9(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859_9.7.html -.. _`iso_8859-9(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso_8859-9.7.html -.. _`iso-8859-9(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/iso-8859-9.7.html -.. _`isosize(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/isosize.8.html -.. _`is_pad(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/is_pad.3ncurses.html -.. _`isprint(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isprint.3.html -.. _`isprint(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isprint.3posix.html -.. _`ispunct(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ispunct.3.html -.. _`ispunct(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ispunct.3posix.html -.. _`is_scrollok(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/is_scrollok.3ncurses.html -.. _`isspace(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isspace.3.html -.. _`isspace(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isspace.3posix.html -.. _`is_subwin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/is_subwin.3ncurses.html -.. _`issue(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/issue.5.html -.. _`is_syncok(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/is_syncok.3ncurses.html -.. _`is_term_resized(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/is_term_resized.3ncurses.html -.. _`isunordered(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isunordered.3.html -.. _`isunordered(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isunordered.3posix.html -.. _`isupper(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isupper.3.html -.. _`isupper(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isupper.3posix.html -.. _`iswalnum(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswalnum.3.html -.. _`iswalnum(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswalnum.3posix.html -.. _`iswalpha(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswalpha.3.html -.. _`iswalpha(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswalpha.3posix.html -.. _`iswblank(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswblank.3.html -.. _`iswblank(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswblank.3posix.html -.. _`iswcntrl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswcntrl.3.html -.. _`iswcntrl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswcntrl.3posix.html -.. _`iswctype(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswctype.3.html -.. _`iswctype(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswctype.3posix.html -.. _`iswdigit(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswdigit.3.html -.. _`iswdigit(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswdigit.3posix.html -.. _`iswgraph(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswgraph.3.html -.. _`iswgraph(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswgraph.3posix.html -.. _`is_wintouched(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/is_wintouched.3ncurses.html -.. _`iswlower(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswlower.3.html -.. _`iswlower(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswlower.3posix.html -.. _`iswprint(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswprint.3.html -.. _`iswprint(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswprint.3posix.html -.. _`iswpunct(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswpunct.3.html -.. _`iswpunct(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswpunct.3posix.html -.. _`iswspace(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswspace.3.html -.. _`iswspace(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswspace.3posix.html -.. _`iswupper(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswupper.3.html -.. _`iswupper(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswupper.3posix.html -.. _`iswxdigit(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswxdigit.3.html -.. _`iswxdigit(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/iswxdigit.3posix.html -.. _`isxdigit(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isxdigit.3.html -.. _`isxdigit(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/isxdigit.3posix.html -.. _`item_count(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/item_count.3menu.html -.. _`item_description(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/item_description.3menu.html -.. _`item_index(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/item_index.3menu.html -.. _`item_init(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/item_init.3menu.html -.. _`item_name(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/item_name.3menu.html -.. _`item_opts(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/item_opts.3menu.html -.. _`item_opts_off(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/item_opts_off.3menu.html -.. _`item_opts_on(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/item_opts_on.3menu.html -.. _`items(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/items.3menu.html -.. _`item_term(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/item_term.3menu.html -.. _`item_userptr(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/item_userptr.3menu.html -.. _`item_value(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/item_value.3menu.html -.. _`item_visible(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/item_visible.3menu.html -.. _`j0(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/j0.3.html -.. _`j0(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/j0.3posix.html -.. _`j0f(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/j0f.3.html -.. _`j0l(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/j0l.3.html -.. _`j1(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/j1.3.html -.. _`j1(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/j1.3posix.html -.. _`j1f(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/j1f.3.html -.. _`j1l(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/j1l.3.html -.. _`jn(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/jn.3.html -.. _`jn(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/jn.3posix.html -.. _`jnf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/jnf.3.html -.. _`jnl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/jnl.3.html -.. _`jobs(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/jobs.1posix.html -.. _`join(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/join.1.html -.. _`join(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/join.1posix.html -.. _`jrand48(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/jrand48.3.html -.. _`jrand48(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/jrand48.3posix.html -.. _`jrand48_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/jrand48_r.3.html -.. _`kernel(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/kernel.3ncurses.html -.. _`keybound(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/keybound.3ncurses.html -.. _`keyctl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/keyctl.2.html -.. _`key_decryptsession(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/key_decryptsession.3.html -.. _`key_defined(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/key_defined.3ncurses.html -.. _`key_encryptsession(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/key_encryptsession.3.html -.. _`key_gendes(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/key_gendes.3.html -.. _`key_name(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/key_name.3ncurses.html -.. _`keyname(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/keyname.3ncurses.html -.. _`keyok(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/keyok.3ncurses.html -.. _`keypad(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/keypad.3ncurses.html -.. _`key_secretkey_is_set(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/key_secretkey_is_set.3.html -.. _`key_setsecret(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/key_setsecret.3.html -.. _`kill(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/kill.1.html -.. _`kill(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/kill.1posix.html -.. _`kill(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/kill.2.html -.. _`kill(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/kill.3posix.html -.. _`killall(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/killall.1.html -.. _`killall5(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/killall5.8.html -.. _`killchar(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/killchar.3ncurses.html -.. _`killpg(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/killpg.2.html -.. _`killpg(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/killpg.3posix.html -.. _`killwchar(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/killwchar.3ncurses.html -.. _`klogctl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/klogctl.3.html -.. _`kmem(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/kmem.4.html -.. _`koi8-r(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/koi8-r.7.html -.. _`koi8-u(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/koi8-u.7.html -.. _`ksh(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ksh.1.html -.. _`ksh93(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ksh93.1.html -.. _`l64a(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/l64a.3.html -.. _`l64a(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/l64a.3posix.html -.. _`labs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/labs.3.html -.. _`labs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/labs.3posix.html -.. _`langinfo.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/langinfo.h.7posix.html -.. _`last(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/last.1.html -.. _`lastb(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lastb.1.html -.. _`lastlog(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/lastlog.8.html -.. _`latin10(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/latin10.7.html -.. _`latin1(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/latin1.7.html -.. _`latin2(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/latin2.7.html -.. _`latin3(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/latin3.7.html -.. _`latin4(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/latin4.7.html -.. _`latin5(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/latin5.7.html -.. _`latin6(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/latin6.7.html -.. _`latin7(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/latin7.7.html -.. _`latin8(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/latin8.7.html -.. _`latin9(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/latin9.7.html -.. _`lcf(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lcf.1.html -.. _`lchown(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/lchown.2.html -.. _`lchown32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/lchown32.2.html -.. _`lchown(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lchown.3posix.html -.. _`lckpwdf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lckpwdf.3.html -.. _`lcong48(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lcong48.3.html -.. _`lcong48(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lcong48.3posix.html -.. _`lcong48_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lcong48_r.3.html -.. _`ld(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ld.1.html -.. _`ldap.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/ldap.conf.5.html -.. _`ldattach(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ldattach.8.html -.. _`ld.bfd(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ld.bfd.1.html -.. _`ldconfig(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ldconfig.8.html -.. _`ldd(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ldd.1.html -.. _`ldexp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ldexp.3.html -.. _`ldexp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ldexp.3posix.html -.. _`ldexpf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ldexpf.3.html -.. _`ldexpf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ldexpf.3posix.html -.. _`ldexpl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ldexpl.3.html -.. _`ldexpl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ldexpl.3posix.html -.. _`ldiv(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ldiv.3.html -.. _`ldiv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ldiv.3posix.html -.. _`ld-linux(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ld-linux.8.html -.. _`ld-linux.so(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ld-linux.so.8.html -.. _`ldp(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/ldp.7.html -.. _`ld.so(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ld.so.8.html -.. _`le16toh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/le16toh.3.html -.. _`le32toh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/le32toh.3.html -.. _`le64toh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/le64toh.3.html -.. _`leaveok(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/leaveok.3ncurses.html -.. _`legacy(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/legacy.3ncurses.html -.. _`legacy_coding(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/legacy_coding.3ncurses.html -.. _`less(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/less.1.html -.. _`lessecho(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lessecho.1.html -.. _`lessfile(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lessfile.1.html -.. _`lesskey(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lesskey.1.html -.. _`lesspipe(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lesspipe.1.html -.. _`lex(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lex.1.html -.. _`lex(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lex.1posix.html -.. _`lexgrog(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lexgrog.1.html -.. _`lfind(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lfind.3.html -.. _`lfind(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lfind.3posix.html -.. _`lft(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lft.1.html -.. _`lft.db(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lft.db.1.html -.. _`lgamma(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lgamma.3.html -.. _`lgamma(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lgamma.3posix.html -.. _`lgammaf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lgammaf.3.html -.. _`lgammaf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lgammaf.3posix.html -.. _`lgammaf_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lgammaf_r.3.html -.. _`lgammal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lgammal.3.html -.. _`lgammal(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lgammal.3posix.html -.. _`lgammal_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lgammal_r.3.html -.. _`lgamma_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lgamma_r.3.html -.. _`libc(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/libc.7.html -.. _`libgen.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/libgen.h.7posix.html -.. _`libnetcfg(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/libnetcfg.1.html -.. _`libnetlink(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/libnetlink.3.html -.. _`limits.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/limits.conf.5.html -.. _`limits.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/limits.h.7posix.html -.. _`line(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/line.1.html -.. _`link(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/link.1.html -.. _`link(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/link.1posix.html -.. _`link(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/link.2.html -.. _`link(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/link.3posix.html -.. _`linkat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/linkat.2.html -.. _`link_field(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/link_field.3form.html -.. _`link_fieldtype(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/link_fieldtype.3form.html -.. _`linux32(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/linux32.1.html -.. _`linux64(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/linux64.1.html -.. _`lio_listio(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lio_listio.3posix.html -.. _`listen(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/listen.2.html -.. _`listen(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/listen.3posix.html -.. _`list::moreutils(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/list::moreutils.3pm.html -.. _`llabs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/llabs.3.html -.. _`llabs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/llabs.3posix.html -.. _`lldiv(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lldiv.3.html -.. _`lldiv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lldiv.3posix.html -.. _`llrint(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/llrint.3.html -.. _`llrint(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/llrint.3posix.html -.. _`llrintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/llrintf.3.html -.. _`llrintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/llrintf.3posix.html -.. _`llrintl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/llrintl.3.html -.. _`llrintl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/llrintl.3posix.html -.. _`llround(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/llround.3.html -.. _`llround(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/llround.3posix.html -.. _`llroundf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/llroundf.3.html -.. _`llroundf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/llroundf.3posix.html -.. _`llroundl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/llroundl.3.html -.. _`llroundl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/llroundl.3posix.html -.. _`_llseek(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/_llseek.2.html -.. _`llseek(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/llseek.2.html -.. _`ln(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ln.1.html -.. _`ln(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ln.1posix.html -.. _`lnstat(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/lnstat.8.html -.. _`locale(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/locale.1.html -.. _`locale(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/locale.1posix.html -.. _`locale(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/locale.5.html -.. _`locale(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/locale.7.html -.. _`localeconv(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/localeconv.3.html -.. _`localeconv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/localeconv.3posix.html -.. _`localedef(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/localedef.1.html -.. _`localedef(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/localedef.1posix.html -.. _`locale.gen(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/locale.gen.5.html -.. _`locale-gen(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/locale-gen.8.html -.. _`locale::gettext(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/locale::gettext.3pm.html -.. _`locale.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/locale.h.7posix.html -.. _`localtime(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/localtime.3.html -.. _`localtime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/localtime.3posix.html -.. _`localtime_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/localtime_r.3.html -.. _`localtime_r(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/localtime_r.3posix.html -.. _`locate(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/locate.1.html -.. _`locatedb(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/locatedb.5.html -.. _`locate.findutils(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/locate.findutils.1.html -.. _`lock(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/lock.2.html -.. _`lockf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lockf.3.html -.. _`lockf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lockf.3posix.html -.. _`log10(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log10.3.html -.. _`log10(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log10.3posix.html -.. _`log10f(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log10f.3.html -.. _`log10f(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log10f.3posix.html -.. _`log10l(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log10l.3.html -.. _`log10l(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log10l.3posix.html -.. _`log1p(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log1p.3.html -.. _`log1p(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log1p.3posix.html -.. _`log1pf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log1pf.3.html -.. _`log1pf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log1pf.3posix.html -.. _`log1pl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log1pl.3.html -.. _`log1pl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log1pl.3posix.html -.. _`log2(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log2.3.html -.. _`log2(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log2.3posix.html -.. _`log2f(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log2f.3.html -.. _`log2f(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log2f.3posix.html -.. _`log2l(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log2l.3.html -.. _`log2l(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log2l.3posix.html -.. _`log(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log.3.html -.. _`log(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/log.3posix.html -.. _`logb(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/logb.3.html -.. _`logb(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/logb.3posix.html -.. _`logbf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/logbf.3.html -.. _`logbf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/logbf.3posix.html -.. _`logbl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/logbl.3.html -.. _`logbl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/logbl.3posix.html -.. _`logf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/logf.3.html -.. _`logf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/logf.3posix.html -.. _`logger(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/logger.1.html -.. _`logger(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/logger.1posix.html -.. _`login(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/login.1.html -.. _`login(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/login.3.html -.. _`login.defs(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/login.defs.5.html -.. _`login_tty(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/login_tty.3.html -.. _`logl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/logl.3.html -.. _`logl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/logl.3posix.html -.. _`logname(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/logname.1.html -.. _`logname(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/logname.1posix.html -.. _`logout(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/logout.3.html -.. _`logresolve(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/logresolve.1.html -.. _`logrotate(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/logrotate.8.html -.. _`logsave(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/logsave.8.html -.. _`logwtmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/logwtmp.3.html -.. _`longjmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/longjmp.3.html -.. _`_longjmp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_longjmp.3posix.html -.. _`longjmp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/longjmp.3posix.html -.. _`longname(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/longname.3ncurses.html -.. _`look(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/look.1.html -.. _`lookup_dcookie(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/lookup_dcookie.2.html -.. _`lorder(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lorder.1.html -.. _`losetup(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/losetup.8.html -.. _`lp(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lp.1posix.html -.. _`lp(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/lp.4.html -.. _`lrand48(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lrand48.3.html -.. _`lrand48(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lrand48.3posix.html -.. _`lrand48_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lrand48_r.3.html -.. _`lrint(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lrint.3.html -.. _`lrint(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lrint.3posix.html -.. _`lrintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lrintf.3.html -.. _`lrintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lrintf.3posix.html -.. _`lrintl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lrintl.3.html -.. _`lrintl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lrintl.3posix.html -.. _`lround(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lround.3.html -.. _`lround(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lround.3posix.html -.. _`lroundf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lroundf.3.html -.. _`lroundf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lroundf.3posix.html -.. _`lroundl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lroundl.3.html -.. _`lroundl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lroundl.3posix.html -.. _`ls(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ls.1.html -.. _`ls(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ls.1posix.html -.. _`lsattr(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lsattr.1.html -.. _`lscpu(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lscpu.1.html -.. _`lsearch(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lsearch.3.html -.. _`lsearch(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lsearch.3posix.html -.. _`lseek(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/lseek.2.html -.. _`lseek(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lseek.3posix.html -.. _`lseek64(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lseek64.3.html -.. _`lsinitramfs(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/lsinitramfs.8.html -.. _`lsmod(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/lsmod.8.html -.. _`lsof(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/lsof.8.html -.. _`lspgpot(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lspgpot.1.html -.. _`lstat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/lstat.2.html -.. _`lstat(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lstat.3posix.html -.. _`lstat64(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/lstat64.2.html -.. _`lutimes(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/lutimes.3.html -.. _`lzcat(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lzcat.1.html -.. _`lzcmp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lzcmp.1.html -.. _`lzdiff(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lzdiff.1.html -.. _`lzegrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lzegrep.1.html -.. _`lzfgrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lzfgrep.1.html -.. _`lzgrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lzgrep.1.html -.. _`lzless(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lzless.1.html -.. _`lzma(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lzma.1.html -.. _`lzmainfo(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lzmainfo.1.html -.. _`lzmore(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lzmore.1.html -.. _`lzop(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/lzop.1.html -.. _`m4(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/m4.1.html -.. _`m4(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/m4.1posix.html -.. _`madvise1(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/madvise1.2.html -.. _`madvise(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/madvise.2.html -.. _`magic(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/magic.5.html -.. _`mail(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mail.1.html -.. _`mailaddr(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/mailaddr.7.html -.. _`mailcap(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/mailcap.5.html -.. _`mailcap.order(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/mailcap.order.5.html -.. _`mailname(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/mailname.5.html -.. _`mailq(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mailq.8.html -.. _`mailx(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mailx.1.html -.. _`mailx(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mailx.1posix.html -.. _`major(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/major.3.html -.. _`make(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/make.1.html -.. _`make(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/make.1posix.html -.. _`makecontext(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/makecontext.3.html -.. _`makecontext(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/makecontext.3posix.html -.. _`makedev(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/makedev.3.html -.. _`make-ssl-cert(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/make-ssl-cert.8.html -.. _`malloc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/malloc.3.html -.. _`malloc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/malloc.3posix.html -.. _`__malloc_hook(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/__malloc_hook.3.html -.. _`malloc_hook(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/malloc_hook.3.html -.. _`mallopt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mallopt.3.html -.. _`man(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/man.1.html -.. _`man(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/man.1posix.html -.. _`man2html(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/man2html.1.html -.. _`man(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/man.7.html -.. _`manconv(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/manconv.1.html -.. _`mandb(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mandb.8.html -.. _`man-pages(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/man-pages.7.html -.. _`manpath(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/manpath.1.html -.. _`manpath(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/manpath.5.html -.. _`mark(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mark.3menu.html -.. _`matherr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/matherr.3.html -.. _`math_error(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/math_error.7.html -.. _`math.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/math.h.7posix.html -.. _`mawk(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mawk.1.html -.. _`mb_cur_max(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mb_cur_max.3.html -.. _`mbind(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mbind.2.html -.. _`mblen(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mblen.3.html -.. _`mblen(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mblen.3posix.html -.. _`mb_len_max(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mb_len_max.3.html -.. _`mbox(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/mbox.5.html -.. _`mbrlen(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mbrlen.3.html -.. _`mbrlen(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mbrlen.3posix.html -.. _`mbrtowc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mbrtowc.3.html -.. _`mbrtowc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mbrtowc.3posix.html -.. _`mbsinit(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mbsinit.3.html -.. _`mbsinit(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mbsinit.3posix.html -.. _`mbsnrtowcs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mbsnrtowcs.3.html -.. _`mbsrtowcs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mbsrtowcs.3.html -.. _`mbsrtowcs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mbsrtowcs.3posix.html -.. _`mbstowcs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mbstowcs.3.html -.. _`mbstowcs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mbstowcs.3posix.html -.. _`mbtowc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mbtowc.3.html -.. _`mbtowc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mbtowc.3posix.html -.. _`mcookie(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mcookie.1.html -.. _`mcprint(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mcprint.3ncurses.html -.. _`md2(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/md2.1ssl.html -.. _`md4(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/md4.1ssl.html -.. _`md5(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/md5.1ssl.html -.. _`md5sum(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/md5sum.1.html -.. _`md5sum.textutils(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/md5sum.textutils.1.html -.. _`mdc2(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mdc2.1ssl.html -.. _`mdoc(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/mdoc.7.html -.. _`mem(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/mem.4.html -.. _`memalign(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memalign.3.html -.. _`memccpy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memccpy.3.html -.. _`memccpy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memccpy.3posix.html -.. _`memchr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memchr.3.html -.. _`memchr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memchr.3posix.html -.. _`memcmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memcmp.3.html -.. _`memcmp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memcmp.3posix.html -.. _`memcpy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memcpy.3.html -.. _`memcpy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memcpy.3posix.html -.. _`memfrob(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memfrob.3.html -.. _`memleaks(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memleaks.3ncurses.html -.. _`memmem(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memmem.3.html -.. _`memmove(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memmove.3.html -.. _`memmove(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memmove.3posix.html -.. _`mempcpy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mempcpy.3.html -.. _`memrchr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memrchr.3.html -.. _`memset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memset.3.html -.. _`memset(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/memset.3posix.html -.. _`menu(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu.3menu.html -.. _`menu_attributes(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_attributes.3menu.html -.. _`menu_back(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_back.3menu.html -.. _`menu_current(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_current.3menu.html -.. _`menu_cursor(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_cursor.3menu.html -.. _`menu_driver(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_driver.3menu.html -.. _`menu_fore(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_fore.3menu.html -.. _`menu_format(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_format.3menu.html -.. _`menu_grey(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_grey.3menu.html -.. _`menu_hook(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_hook.3menu.html -.. _`menu_init(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_init.3menu.html -.. _`menu_items(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_items.3menu.html -.. _`menu_mark(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_mark.3menu.html -.. _`menu_name(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_name.3menu.html -.. _`menu_new(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_new.3menu.html -.. _`menu_opts(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_opts.3menu.html -.. _`menu_opts_off(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_opts_off.3menu.html -.. _`menu_opts_on(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_opts_on.3menu.html -.. _`menu_pad(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_pad.3menu.html -.. _`menu_pattern(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_pattern.3menu.html -.. _`menu_post(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_post.3menu.html -.. _`menu_request_by_name(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_request_by_name.3menu.html -.. _`menu_request_name(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_request_name.3menu.html -.. _`menu_requestname(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_requestname.3menu.html -.. _`menu_spacing(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_spacing.3menu.html -.. _`menu_sub(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_sub.3menu.html -.. _`menu_term(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_term.3menu.html -.. _`menu_userptr(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_userptr.3menu.html -.. _`menu_value(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_value.3menu.html -.. _`menu_visible(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_visible.3menu.html -.. _`menu_win(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/menu_win.3menu.html -.. _`mesg(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mesg.1.html -.. _`mesg(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mesg.1posix.html -.. _`meta(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/meta.3ncurses.html -.. _`migrate_pages(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/migrate_pages.2.html -.. _`mii-tool(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mii-tool.8.html -.. _`mincore(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mincore.2.html -.. _`minor(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/minor.3.html -.. _`missing(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/missing.7.html -.. _`mitem_current(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mitem_current.3menu.html -.. _`mitem_name(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mitem_name.3menu.html -.. _`mitem_new(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mitem_new.3menu.html -.. _`mitem_opts(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mitem_opts.3menu.html -.. _`mitem_userptr(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mitem_userptr.3menu.html -.. _`mitem_value(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mitem_value.3menu.html -.. _`mitem_visible(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mitem_visible.3menu.html -.. _`mkdir(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mkdir.1.html -.. _`mkdir(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mkdir.1posix.html -.. _`mkdir(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mkdir.2.html -.. _`mkdir(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mkdir.3posix.html -.. _`mkdirat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mkdirat.2.html -.. _`mkdtemp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mkdtemp.3.html -.. _`mke2fs(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mke2fs.8.html -.. _`mke2fs.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/mke2fs.conf.5.html -.. _`mkfifo(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mkfifo.1.html -.. _`mkfifo(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mkfifo.1posix.html -.. _`mkfifo(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mkfifo.3.html -.. _`mkfifo(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mkfifo.3posix.html -.. _`mkfifoat(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mkfifoat.3.html -.. _`mkfs(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mkfs.8.html -.. _`mkfs.bfs(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mkfs.bfs.8.html -.. _`mkfs.ext2(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mkfs.ext2.8.html -.. _`mkfs.ext3(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mkfs.ext3.8.html -.. _`mkfs.ext4(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mkfs.ext4.8.html -.. _`mkfs.ext4dev(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mkfs.ext4dev.8.html -.. _`mkfs.minix(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mkfs.minix.8.html -.. _`mkhomedir_helper(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mkhomedir_helper.8.html -.. _`mkinitramfs(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mkinitramfs.8.html -.. _`mkinitramfs-kpkg(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mkinitramfs-kpkg.8.html -.. _`mklost+found(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mklost+found.8.html -.. _`mknod(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mknod.1.html -.. _`mknod(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mknod.2.html -.. _`mknod(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mknod.3posix.html -.. _`mknodat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mknodat.2.html -.. _`mkostemp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mkostemp.3.html -.. _`mkostemps(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mkostemps.3.html -.. _`mkstemp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mkstemp.3.html -.. _`mkstemp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mkstemp.3posix.html -.. _`mkstemps(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mkstemps.3.html -.. _`mkswap(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mkswap.8.html -.. _`mktemp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mktemp.1.html -.. _`mktemp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mktemp.3.html -.. _`mktemp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mktemp.3posix.html -.. _`mktime(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mktime.3.html -.. _`mktime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mktime.3posix.html -.. _`mlock(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mlock.2.html -.. _`mlock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mlock.3posix.html -.. _`mlockall(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mlockall.2.html -.. _`mlockall(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mlockall.3posix.html -.. _`mman.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/mman.h.7posix.html -.. _`mmap2(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mmap2.2.html -.. _`mmap(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mmap.2.html -.. _`mmap(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mmap.3posix.html -.. _`mmap64(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mmap64.3.html -.. _`mmdf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/mmdf.5.html -.. _`modf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/modf.3.html -.. _`modf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/modf.3posix.html -.. _`modff(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/modff.3.html -.. _`modff(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/modff.3posix.html -.. _`modfl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/modfl.3.html -.. _`modfl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/modfl.3posix.html -.. _`modify_ldt(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/modify_ldt.2.html -.. _`modinfo(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/modinfo.8.html -.. _`modprobe(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/modprobe.8.html -.. _`modprobe.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/modprobe.conf.5.html -.. _`modules(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/modules.5.html -.. _`modules.dep(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/modules.dep.5.html -.. _`moduli(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/moduli.5.html -.. _`monetary.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/monetary.h.7posix.html -.. _`more(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/more.1.html -.. _`more(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/more.1posix.html -.. _`motd(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/motd.5.html -.. _`motd.tail(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/motd.tail.5.html -.. _`mount(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mount.2.html -.. _`mount(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/mount.8.html -.. _`mountpoint(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mountpoint.1.html -.. _`mouse(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mouse.3ncurses.html -.. _`mouse(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/mouse.4.html -.. _`mouseinterval(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mouseinterval.3ncurses.html -.. _`mousemask(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mousemask.3ncurses.html -.. _`mouse_trafo(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mouse_trafo.3ncurses.html -.. _`move(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/move.3ncurses.html -.. _`move_field(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/move_field.3form.html -.. _`move_pages(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/move_pages.2.html -.. _`move_panel(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/move_panel.3curses.html -.. _`mpool(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mpool.3.html -.. _`mprotect(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mprotect.2.html -.. _`mprotect(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mprotect.3posix.html -.. _`mpx(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mpx.2.html -.. _`mq_close(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_close.3.html -.. _`mq_close(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_close.3posix.html -.. _`mq_getattr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_getattr.3.html -.. _`mq_getattr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_getattr.3posix.html -.. _`mq_getsetattr(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mq_getsetattr.2.html -.. _`mq_notify(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mq_notify.2.html -.. _`mq_notify(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_notify.3.html -.. _`mq_notify(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_notify.3posix.html -.. _`mq_open(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mq_open.2.html -.. _`mq_open(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_open.3.html -.. _`mq_open(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_open.3posix.html -.. _`mq_overview(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/mq_overview.7.html -.. _`mq_receive(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_receive.3.html -.. _`mq_receive(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_receive.3posix.html -.. _`mq_send(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_send.3.html -.. _`mq_send(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_send.3posix.html -.. _`mq_setattr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_setattr.3.html -.. _`mq_setattr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_setattr.3posix.html -.. _`mq_timedreceive(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mq_timedreceive.2.html -.. _`mq_timedreceive(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_timedreceive.3.html -.. _`mq_timedreceive(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_timedreceive.3posix.html -.. _`mq_timedsend(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mq_timedsend.2.html -.. _`mq_timedsend(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_timedsend.3.html -.. _`mq_timedsend(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_timedsend.3posix.html -.. _`mqueue.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/mqueue.h.7posix.html -.. _`mq_unlink(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mq_unlink.2.html -.. _`mq_unlink(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_unlink.3.html -.. _`mq_unlink(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mq_unlink.3posix.html -.. _`mrand48(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mrand48.3.html -.. _`mrand48(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mrand48.3posix.html -.. _`mrand48_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mrand48_r.3.html -.. _`mremap(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/mremap.2.html -.. _`msgctl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/msgctl.2.html -.. _`msgctl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/msgctl.3posix.html -.. _`msgget(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/msgget.2.html -.. _`msgget(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/msgget.3posix.html -.. _`msg.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/msg.h.7posix.html -.. _`msgop(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/msgop.2.html -.. _`msgrcv(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/msgrcv.2.html -.. _`msgrcv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/msgrcv.3posix.html -.. _`msgsnd(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/msgsnd.2.html -.. _`msgsnd(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/msgsnd.3posix.html -.. _`ms_print(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ms_print.1.html -.. _`msr(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/msr.4.html -.. _`msync(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/msync.2.html -.. _`msync(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/msync.3posix.html -.. _`mt(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mt.1.html -.. _`mt-gnu(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mt-gnu.1.html -.. _`mtrace(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mtrace.1.html -.. _`mtrace(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mtrace.3.html -.. _`munlock(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/munlock.2.html -.. _`munlock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/munlock.3posix.html -.. _`munlockall(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/munlockall.2.html -.. _`munlockall(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/munlockall.3posix.html -.. _`munmap(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/munmap.2.html -.. _`munmap(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/munmap.3posix.html -.. _`muntrace(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/muntrace.3.html -.. _`mutt(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mutt.1.html -.. _`mutt_dotlock(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mutt_dotlock.1.html -.. _`muttrc(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/muttrc.5.html -.. _`mv(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mv.1.html -.. _`mv(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/mv.1posix.html -.. _`mvaddch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvaddch.3ncurses.html -.. _`mvaddchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvaddchnstr.3ncurses.html -.. _`mvaddchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvaddchstr.3ncurses.html -.. _`mvaddnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvaddnstr.3ncurses.html -.. _`mvaddnwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvaddnwstr.3ncurses.html -.. _`mvaddstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvaddstr.3ncurses.html -.. _`mvadd_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvadd_wch.3ncurses.html -.. _`mvadd_wchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvadd_wchnstr.3ncurses.html -.. _`mvadd_wchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvadd_wchstr.3ncurses.html -.. _`mvaddwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvaddwstr.3ncurses.html -.. _`mvchgat(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvchgat.3ncurses.html -.. _`mvcur(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvcur.3ncurses.html -.. _`mvdelch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvdelch.3ncurses.html -.. _`mvderwin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvderwin.3ncurses.html -.. _`mvgetch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvgetch.3ncurses.html -.. _`mvgetnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvgetnstr.3ncurses.html -.. _`mvgetn_wstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvgetn_wstr.3ncurses.html -.. _`mvgetstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvgetstr.3ncurses.html -.. _`mvget_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvget_wch.3ncurses.html -.. _`mvget_wstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvget_wstr.3ncurses.html -.. _`mvhline(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvhline.3ncurses.html -.. _`mvhline_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvhline_set.3ncurses.html -.. _`mvinch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvinch.3ncurses.html -.. _`mvinchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvinchnstr.3ncurses.html -.. _`mvinchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvinchstr.3ncurses.html -.. _`mvinnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvinnstr.3ncurses.html -.. _`mvinnwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvinnwstr.3ncurses.html -.. _`mvinsch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvinsch.3ncurses.html -.. _`mvinsnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvinsnstr.3ncurses.html -.. _`mvins_nwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvins_nwstr.3ncurses.html -.. _`mvinsstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvinsstr.3ncurses.html -.. _`mvinstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvinstr.3ncurses.html -.. _`mvins_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvins_wch.3ncurses.html -.. _`mvins_wstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvins_wstr.3ncurses.html -.. _`mvin_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvin_wch.3ncurses.html -.. _`mvin_wchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvin_wchnstr.3ncurses.html -.. _`mvin_wchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvin_wchstr.3ncurses.html -.. _`mvinwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvinwstr.3ncurses.html -.. _`mvprintw(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvprintw.3ncurses.html -.. _`mvscanw(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvscanw.3ncurses.html -.. _`mvvline(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvvline.3ncurses.html -.. _`mvvline_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvvline_set.3ncurses.html -.. _`mvwaddch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwaddch.3ncurses.html -.. _`mvwaddchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwaddchnstr.3ncurses.html -.. _`mvwaddchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwaddchstr.3ncurses.html -.. _`mvwaddnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwaddnstr.3ncurses.html -.. _`mvwaddnwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwaddnwstr.3ncurses.html -.. _`mvwaddstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwaddstr.3ncurses.html -.. _`mvwadd_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwadd_wch.3ncurses.html -.. _`mvwadd_wchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwadd_wchnstr.3ncurses.html -.. _`mvwadd_wchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwadd_wchstr.3ncurses.html -.. _`mvwaddwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwaddwstr.3ncurses.html -.. _`mvwchgat(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwchgat.3ncurses.html -.. _`mvwdelch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwdelch.3ncurses.html -.. _`mvwgetch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwgetch.3ncurses.html -.. _`mvwgetnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwgetnstr.3ncurses.html -.. _`mvwgetn_wstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwgetn_wstr.3ncurses.html -.. _`mvwgetstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwgetstr.3ncurses.html -.. _`mvwget_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwget_wch.3ncurses.html -.. _`mvwget_wstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwget_wstr.3ncurses.html -.. _`mvwhline(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwhline.3ncurses.html -.. _`mvwhline_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwhline_set.3ncurses.html -.. _`mvwin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwin.3ncurses.html -.. _`mvwinch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwinch.3ncurses.html -.. _`mvwinchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwinchnstr.3ncurses.html -.. _`mvwinchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwinchstr.3ncurses.html -.. _`mvwinnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwinnstr.3ncurses.html -.. _`mvwinnwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwinnwstr.3ncurses.html -.. _`mvwinsch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwinsch.3ncurses.html -.. _`mvwinsnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwinsnstr.3ncurses.html -.. _`mvwins_nwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwins_nwstr.3ncurses.html -.. _`mvwinsstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwinsstr.3ncurses.html -.. _`mvwinstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwinstr.3ncurses.html -.. _`mvwins_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwins_wch.3ncurses.html -.. _`mvwins_wstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwins_wstr.3ncurses.html -.. _`mvwin_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwin_wch.3ncurses.html -.. _`mvwin_wchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwin_wchnstr.3ncurses.html -.. _`mvwin_wchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwin_wchstr.3ncurses.html -.. _`mvwinwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwinwstr.3ncurses.html -.. _`mvwprintw(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwprintw.3ncurses.html -.. _`mvwscanw(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwscanw.3ncurses.html -.. _`mvwvline(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwvline.3ncurses.html -.. _`mvwvline_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/mvwvline_set.3ncurses.html -.. _`namei(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/namei.1.html -.. _`nameif(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/nameif.8.html -.. _`namespace.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/namespace.conf.5.html -.. _`nan(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nan.3.html -.. _`nan(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nan.3posix.html -.. _`nanf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nanf.3.html -.. _`nanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nanf.3posix.html -.. _`nanl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nanl.3.html -.. _`nanl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nanl.3posix.html -.. _`nano(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nano.1.html -.. _`nanorc(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/nanorc.5.html -.. _`nanosleep(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/nanosleep.2.html -.. _`nanosleep(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nanosleep.3posix.html -.. _`napms(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/napms.3ncurses.html -.. _`nawk(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nawk.1.html -.. _`nc(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nc.1.html -.. _`ncal(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ncal.1.html -.. _`_nc_freeall(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_nc_freeall.3ncurses.html -.. _`_nc_free_and_exit(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_nc_free_and_exit.3ncurses.html -.. _`_nc_tracebits(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_nc_tracebits.3ncurses.html -.. _`nc_traditional(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nc_traditional.1.html -.. _`ncurses(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ncurses.3ncurses.html -.. _`ncurses5-config(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ncurses5-config.1.html -.. _`ncursesw5-config(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ncursesw5-config.1.html -.. _`ndbm.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/ndbm.h.7posix.html -.. _`nearbyint(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nearbyint.3.html -.. _`nearbyint(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nearbyint.3posix.html -.. _`nearbyintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nearbyintf.3.html -.. _`nearbyintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nearbyintf.3posix.html -.. _`nearbyintl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nearbyintl.3.html -.. _`nearbyintl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nearbyintl.3posix.html -.. _`neqn(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/neqn.1.html -.. _`netcat(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/netcat.1.html -.. _`netdb.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/netdb.h.7posix.html -.. _`netdevice(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/netdevice.7.html -.. _`netlink(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/netlink.3.html -.. _`netlink(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/netlink.7.html -.. _`netlink_route(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/netlink_route.7.html -.. _`netstat(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/netstat.8.html -.. _`networks(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/networks.5.html -.. _`new(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/new.3form.html -.. _`new(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/new.3menu.html -.. _`newaliases(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/newaliases.8.html -.. _`new_field(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/new_field.3form.html -.. _`new_fieldtype(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/new_fieldtype.3form.html -.. _`new_form(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/new_form.3form.html -.. _`newgrp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/newgrp.1.html -.. _`newgrp(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/newgrp.1posix.html -.. _`new_item(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/new_item.3menu.html -.. _`new_menu(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/new_menu.3menu.html -.. _`newpad(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/newpad.3ncurses.html -.. _`new_page(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/new_page.3form.html -.. _`new_panel(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/new_panel.3curses.html -.. _`_newselect(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/_newselect.2.html -.. _`newterm(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/newterm.3ncurses.html -.. _`newusers(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/newusers.8.html -.. _`newwin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/newwin.3ncurses.html -.. _`nextafter(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nextafter.3.html -.. _`nextafter(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nextafter.3posix.html -.. _`nextafterf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nextafterf.3.html -.. _`nextafterf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nextafterf.3posix.html -.. _`nextafterl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nextafterl.3.html -.. _`nextafterl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nextafterl.3posix.html -.. _`nexttoward(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nexttoward.3.html -.. _`nexttoward(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nexttoward.3posix.html -.. _`nexttowardf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nexttowardf.3.html -.. _`nexttowardf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nexttowardf.3posix.html -.. _`nexttowardl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nexttowardl.3.html -.. _`nexttowardl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nexttowardl.3posix.html -.. _`nfsservctl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/nfsservctl.2.html -.. _`nftw(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nftw.3.html -.. _`nftw(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nftw.3posix.html -.. _`nice(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nice.1.html -.. _`nice(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nice.1posix.html -.. _`nice(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/nice.2.html -.. _`nice(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nice.3posix.html -.. _`nisdomainname(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nisdomainname.1.html -.. _`nl(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nl.1.html -.. _`nl(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nl.1posix.html -.. _`nl(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nl.3ncurses.html -.. _`nl_langinfo(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nl_langinfo.3.html -.. _`nl_langinfo(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nl_langinfo.3posix.html -.. _`nlmconv(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nlmconv.1.html -.. _`nl_types.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/nl_types.h.7posix.html -.. _`nm(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nm.1.html -.. _`nm(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nm.1posix.html -.. _`nocbreak(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nocbreak.3ncurses.html -.. _`nodelay(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nodelay.3ncurses.html -.. _`noecho(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/noecho.3ncurses.html -.. _`nofilter(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nofilter.3ncurses.html -.. _`nohup(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nohup.1.html -.. _`nohup(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nohup.1posix.html -.. _`nologin(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/nologin.5.html -.. _`nologin(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/nologin.8.html -.. _`nonl(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nonl.3ncurses.html -.. _`noqiflush(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/noqiflush.3ncurses.html -.. _`noraw(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/noraw.3ncurses.html -.. _`notimeout(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/notimeout.3ncurses.html -.. _`nproc(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nproc.1.html -.. _`nrand48(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nrand48.3.html -.. _`nrand48(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nrand48.3posix.html -.. _`nrand48_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/nrand48_r.3.html -.. _`nroff(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nroff.1.html -.. _`nseq(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/nseq.1ssl.html -.. _`nsswitch.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/nsswitch.conf.5.html -.. _`nstat(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/nstat.8.html -.. _`ntohl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ntohl.3.html -.. _`ntohl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ntohl.3posix.html -.. _`ntohs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ntohs.3.html -.. _`ntohs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ntohs.3posix.html -.. _`null(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/null.4.html -.. _`numa(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/numa.7.html -.. _`numa_maps(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/numa_maps.5.html -.. _`objcopy(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/objcopy.1.html -.. _`objdump(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/objdump.1.html -.. _`ocsp(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ocsp.1ssl.html -.. _`od(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/od.1.html -.. _`od(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/od.1posix.html -.. _`offsetof(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/offsetof.3.html -.. _`oldfind(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/oldfind.1.html -.. _`oldfstat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/oldfstat.2.html -.. _`oldlstat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/oldlstat.2.html -.. _`oldolduname(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/oldolduname.2.html -.. _`oldstat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/oldstat.2.html -.. _`olduname(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/olduname.2.html -.. _`omshell(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/omshell.1.html -.. _`on_exit(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/on_exit.3.html -.. _`opaque(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/opaque.3ncurses.html -.. _`open(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/open.2.html -.. _`open(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/open.3posix.html -.. _`openat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/openat.2.html -.. _`opendir(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/opendir.3.html -.. _`opendir(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/opendir.3posix.html -.. _`openlog(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/openlog.3.html -.. _`openlog(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/openlog.3posix.html -.. _`open_memstream(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/open_memstream.3.html -.. _`openpty(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/openpty.3.html -.. _`openssl(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/openssl.1ssl.html -.. _`open_wmemstream(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/open_wmemstream.3.html -.. _`operator(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/operator.7.html -.. _`optarg(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/optarg.3.html -.. _`optarg(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/optarg.3posix.html -.. _`opterr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/opterr.3.html -.. _`opterr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/opterr.3posix.html -.. _`optind(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/optind.3.html -.. _`optind(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/optind.3posix.html -.. _`optopt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/optopt.3.html -.. _`optopt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/optopt.3posix.html -.. _`opts(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/opts.3form.html -.. _`opts(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/opts.3menu.html -.. _`outb(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/outb.2.html -.. _`outb_p(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/outb_p.2.html -.. _`outl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/outl.2.html -.. _`outl_p(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/outl_p.2.html -.. _`outopts(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/outopts.3ncurses.html -.. _`outsb(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/outsb.2.html -.. _`outsl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/outsl.2.html -.. _`outsw(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/outsw.2.html -.. _`outw(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/outw.2.html -.. _`outw_p(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/outw_p.2.html -.. _`overlay(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/overlay.3ncurses.html -.. _`overwrite(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/overwrite.3ncurses.html -.. _`ownership(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ownership.8.html -.. _`packet(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/packet.7.html -.. _`pad(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pad.3ncurses.html -.. _`page(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/page.3form.html -.. _`pager(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pager.1.html -.. _`pair_content(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pair_content.3ncurses.html -.. _`pair_number(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pair_number.3ncurses.html -.. _`pam(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/pam.7.html -.. _`pam_access(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_access.8.html -.. _`pam-auth-update(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam-auth-update.8.html -.. _`pam.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/pam.conf.5.html -.. _`pam.d(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/pam.d.5.html -.. _`pam_debug(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_debug.8.html -.. _`pam_deny(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_deny.8.html -.. _`pam_echo(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_echo.8.html -.. _`pam_env(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_env.8.html -.. _`pam_env.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/pam_env.conf.5.html -.. _`pam_exec(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_exec.8.html -.. _`pam_faildelay(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_faildelay.8.html -.. _`pam_filter(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_filter.8.html -.. _`pam_ftp(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_ftp.8.html -.. _`pam_getenv(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_getenv.8.html -.. _`pam_group(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_group.8.html -.. _`pam_issue(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_issue.8.html -.. _`pam_keyinit(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_keyinit.8.html -.. _`pam_lastlog(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_lastlog.8.html -.. _`pam_limits(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_limits.8.html -.. _`pam_listfile(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_listfile.8.html -.. _`pam_localuser(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_localuser.8.html -.. _`pam_loginuid(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_loginuid.8.html -.. _`pam_mail(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_mail.8.html -.. _`pam_mkhomedir(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_mkhomedir.8.html -.. _`pam_motd(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_motd.8.html -.. _`pam_namespace(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_namespace.8.html -.. _`pam_nologin(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_nologin.8.html -.. _`pam_permit(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_permit.8.html -.. _`pam_pwhistory(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_pwhistory.8.html -.. _`pam_rhosts(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_rhosts.8.html -.. _`pam_rootok(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_rootok.8.html -.. _`pam_securetty(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_securetty.8.html -.. _`pam_selinux(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_selinux.8.html -.. _`pam_sepermit(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_sepermit.8.html -.. _`pam_shells(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_shells.8.html -.. _`pam_succeed_if(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_succeed_if.8.html -.. _`pam_tally2(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_tally2.8.html -.. _`pam_tally(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_tally.8.html -.. _`pam_time(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_time.8.html -.. _`pam_timestamp(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_timestamp.8.html -.. _`pam_timestamp_check(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_timestamp_check.8.html -.. _`pam_umask(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_umask.8.html -.. _`pam_unix(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_unix.8.html -.. _`pam_userdb(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_userdb.8.html -.. _`pam_warn(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_warn.8.html -.. _`pam_wheel(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_wheel.8.html -.. _`pam_xauth(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pam_xauth.8.html -.. _`panel(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/panel.3curses.html -.. _`panel_above(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/panel_above.3curses.html -.. _`panel_below(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/panel_below.3curses.html -.. _`panel_hidden(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/panel_hidden.3curses.html -.. _`panel_userptr(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/panel_userptr.3curses.html -.. _`panel_window(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/panel_window.3curses.html -.. _`partx(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/partx.8.html -.. _`passwd(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/passwd.1.html -.. _`passwd(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/passwd.1ssl.html -.. _`passwd2des(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/passwd2des.3.html -.. _`passwd(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/passwd.5.html -.. _`paste(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/paste.1.html -.. _`paste(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/paste.1posix.html -.. _`patch(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/patch.1.html -.. _`patch(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/patch.1posix.html -.. _`pathchk(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pathchk.1.html -.. _`pathchk(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pathchk.1posix.html -.. _`pathconf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pathconf.3.html -.. _`pathconf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pathconf.3posix.html -.. _`path_resolution(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/path_resolution.2.html -.. _`path_resolution(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/path_resolution.7.html -.. _`pattern(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pattern.3menu.html -.. _`pause(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/pause.2.html -.. _`pause(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pause.3posix.html -.. _`pax(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pax.1posix.html -.. _`pciconfig_iobase(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/pciconfig_iobase.2.html -.. _`pciconfig_read(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/pciconfig_read.2.html -.. _`pciconfig_write(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/pciconfig_write.2.html -.. _`pclose(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pclose.3.html -.. _`pclose(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pclose.3posix.html -.. _`pcrepattern(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pcrepattern.3.html -.. _`pcretest(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pcretest.1.html -.. _`pdb(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pdb.1.html -.. _`pdb2.6(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pdb2.6.1.html -.. _`pechochar(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pechochar.3ncurses.html -.. _`pecho_wchar(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pecho_wchar.3ncurses.html -.. _`peekfd(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/peekfd.1.html -.. _`perf(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/perf.1.html -.. _`perl(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/perl.1.html -.. _`perl5(10.1.1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/perl5.10.1.1.html -.. _`perlbug(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/perlbug.1.html -.. _`perlivp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/perlivp.1.html -.. _`perlthanks(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/perlthanks.1.html -.. _`perror(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/perror.3.html -.. _`perror(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/perror.3posix.html -.. _`personality(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/personality.2.html -.. _`pf_inet6(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/pf_inet6.7.html -.. _`pf_local(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/pf_local.7.html -.. _`pf_netlink(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/pf_netlink.7.html -.. _`pf_packet(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/pf_packet.7.html -.. _`pf_unix(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/pf_unix.7.html -.. _`pf_x25(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/pf_x25.7.html -.. _`pg(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pg.1.html -.. _`pgawk(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pgawk.1.html -.. _`pgrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pgrep.1.html -.. _`pic(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pic.1.html -.. _`pico(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pico.1.html -.. _`piconv(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/piconv.1.html -.. _`pidof(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pidof.8.html -.. _`ping6(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ping6.8.html -.. _`ping(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ping.8.html -.. _`pinky(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pinky.1.html -.. _`pipe2(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/pipe2.2.html -.. _`pipe(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/pipe.2.html -.. _`pipe(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pipe.3posix.html -.. _`pipe(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/pipe.7.html -.. _`pivot_root(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/pivot_root.2.html -.. _`pivot_root(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pivot_root.8.html -.. _`pkcs12(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pkcs12.1ssl.html -.. _`pkcs7(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pkcs7.1ssl.html -.. _`pkcs8(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pkcs8.1ssl.html -.. _`pkill(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pkill.1.html -.. _`pl2pm(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pl2pm.1.html -.. _`plipconfig(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/plipconfig.8.html -.. _`pmap(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pmap.1.html -.. _`pmap_getmaps(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pmap_getmaps.3.html -.. _`pmap_getport(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pmap_getport.3.html -.. _`pmap_rmtcall(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pmap_rmtcall.3.html -.. _`pmap_set(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pmap_set.3.html -.. _`pmap_unset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pmap_unset.3.html -.. _`pnoutrefresh(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pnoutrefresh.3ncurses.html -.. _`pod2html(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pod2html.1.html -.. _`pod2latex(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pod2latex.1.html -.. _`pod2man(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pod2man.1.html -.. _`pod2text(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pod2text.1.html -.. _`pod2usage(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pod2usage.1.html -.. _`podchecker(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/podchecker.1.html -.. _`podselect(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/podselect.1.html -.. _`poll(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/poll.2.html -.. _`poll(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/poll.3posix.html -.. _`poll.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/poll.h.7posix.html -.. _`popen(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/popen.3.html -.. _`popen(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/popen.3posix.html -.. _`port(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/port.4.html -.. _`pos_form_cursor(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pos_form_cursor.3form.html -.. _`posix_fadvise(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/posix_fadvise.2.html -.. _`posix_fadvise(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_fadvise.3posix.html -.. _`posix_fallocate(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_fallocate.3.html -.. _`posix_fallocate(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_fallocate.3posix.html -.. _`posix_madvise(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_madvise.3posix.html -.. _`posix_memalign(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_memalign.3.html -.. _`posix_memalign(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_memalign.3posix.html -.. _`posix_mem_offset(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_mem_offset.3posix.html -.. _`posix_openpt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_openpt.3.html -.. _`posix_openpt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_openpt.3posix.html -.. _`posixoptions(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/posixoptions.7.html -.. _`posix_spawn(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawn.3posix.html -.. _`posix_spawnattr_destroy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawnattr_destroy.3posix.html -.. _`posix_spawnattr_getflags(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawnattr_getflags.3posix.html -.. _`posix_spawnattr_getpgroup(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawnattr_getpgroup.3posix.html -.. _`posix_spawnattr_getschedparam(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawnattr_getschedparam.3posix.html -.. _`posix_spawnattr_getschedpolicy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawnattr_getschedpolicy.3posix.html -.. _`posix_spawnattr_getsigdefault(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawnattr_getsigdefault.3posix.html -.. _`posix_spawnattr_getsigmask(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawnattr_getsigmask.3posix.html -.. _`posix_spawnattr_init(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawnattr_init.3posix.html -.. _`posix_spawnattr_setflags(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawnattr_setflags.3posix.html -.. _`posix_spawnattr_setpgroup(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawnattr_setpgroup.3posix.html -.. _`posix_spawnattr_setschedparam(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawnattr_setschedparam.3posix.html -.. _`posix_spawnattr_setschedpolicy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawnattr_setschedpolicy.3posix.html -.. _`posix_spawnattr_setsigdefault(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawnattr_setsigdefault.3posix.html -.. _`posix_spawnattr_setsigmask(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawnattr_setsigmask.3posix.html -.. _`posix_spawn_file_actions_addclose(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawn_file_actions_addclose.3posix.html -.. _`posix_spawn_file_actions_adddup2(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawn_file_actions_adddup2.3posix.html -.. _`posix_spawn_file_actions_addopen(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawn_file_actions_addopen.3posix.html -.. _`posix_spawn_file_actions_destroy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawn_file_actions_destroy.3posix.html -.. _`posix_spawn_file_actions_init(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawn_file_actions_init.3posix.html -.. _`posix_spawnp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_spawnp.3posix.html -.. _`posix_trace_attr_destroy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_destroy.3posix.html -.. _`posix_trace_attr_getclockres(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_getclockres.3posix.html -.. _`posix_trace_attr_getcreatetime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_getcreatetime.3posix.html -.. _`posix_trace_attr_getgenversion(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_getgenversion.3posix.html -.. _`posix_trace_attr_getinherited(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_getinherited.3posix.html -.. _`posix_trace_attr_getlogfullpolicy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_getlogfullpolicy.3posix.html -.. _`posix_trace_attr_getlogsize(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_getlogsize.3posix.html -.. _`posix_trace_attr_getmaxdatasize(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_getmaxdatasize.3posix.html -.. _`posix_trace_attr_getmaxsystemeventsize(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_getmaxsystemeventsize.3posix.html -.. _`posix_trace_attr_getmaxusereventsize(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_getmaxusereventsize.3posix.html -.. _`posix_trace_attr_getname(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_getname.3posix.html -.. _`posix_trace_attr_getstreamfullpolicy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_getstreamfullpolicy.3posix.html -.. _`posix_trace_attr_getstreamsize(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_getstreamsize.3posix.html -.. _`posix_trace_attr_init(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_init.3posix.html -.. _`posix_trace_attr_setinherited(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_setinherited.3posix.html -.. _`posix_trace_attr_setlogfullpolicy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_setlogfullpolicy.3posix.html -.. _`posix_trace_attr_setlogsize(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_setlogsize.3posix.html -.. _`posix_trace_attr_setmaxdatasize(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_setmaxdatasize.3posix.html -.. _`posix_trace_attr_setname(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_setname.3posix.html -.. _`posix_trace_attr_setstreamfullpolicy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_setstreamfullpolicy.3posix.html -.. _`posix_trace_attr_setstreamsize(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_attr_setstreamsize.3posix.html -.. _`posix_trace_clear(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_clear.3posix.html -.. _`posix_trace_close(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_close.3posix.html -.. _`posix_trace_create(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_create.3posix.html -.. _`posix_trace_create_withlog(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_create_withlog.3posix.html -.. _`posix_trace_event(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_event.3posix.html -.. _`posix_trace_eventid_equal(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_eventid_equal.3posix.html -.. _`posix_trace_eventid_get_name(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_eventid_get_name.3posix.html -.. _`posix_trace_eventid_open(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_eventid_open.3posix.html -.. _`posix_trace_eventset_add(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_eventset_add.3posix.html -.. _`posix_trace_eventset_del(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_eventset_del.3posix.html -.. _`posix_trace_eventset_empty(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_eventset_empty.3posix.html -.. _`posix_trace_eventset_fill(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_eventset_fill.3posix.html -.. _`posix_trace_eventset_ismember(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_eventset_ismember.3posix.html -.. _`posix_trace_eventtypelist_getnext_id(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_eventtypelist_getnext_id.3posix.html -.. _`posix_trace_eventtypelist_rewind(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_eventtypelist_rewind.3posix.html -.. _`posix_trace_flush(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_flush.3posix.html -.. _`posix_trace_get_attr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_get_attr.3posix.html -.. _`posix_trace_get_filter(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_get_filter.3posix.html -.. _`posix_trace_getnext_event(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_getnext_event.3posix.html -.. _`posix_trace_get_status(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_get_status.3posix.html -.. _`posix_trace_open(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_open.3posix.html -.. _`posix_trace_rewind(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_rewind.3posix.html -.. _`posix_trace_set_filter(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_set_filter.3posix.html -.. _`posix_trace_shutdown(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_shutdown.3posix.html -.. _`posix_trace_start(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_start.3posix.html -.. _`posix_trace_stop(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_stop.3posix.html -.. _`posix_trace_timedgetnext_event(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_timedgetnext_event.3posix.html -.. _`posix_trace_trid_eventid_open(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_trid_eventid_open.3posix.html -.. _`posix_trace_trygetnext_event(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_trace_trygetnext_event.3posix.html -.. _`posix_typed_mem_get_info(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_typed_mem_get_info.3posix.html -.. _`posix_typed_mem_open(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/posix_typed_mem_open.3posix.html -.. _`pos_menu_cursor(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pos_menu_cursor.3menu.html -.. _`post(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/post.3form.html -.. _`post(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/post.3menu.html -.. _`post_form(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/post_form.3form.html -.. _`post_menu(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/post_menu.3menu.html -.. _`pow10(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pow10.3.html -.. _`pow10f(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pow10f.3.html -.. _`pow10l(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pow10l.3.html -.. _`pow(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pow.3.html -.. _`pow(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pow.3posix.html -.. _`poweroff(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/poweroff.8.html -.. _`powf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/powf.3.html -.. _`powf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/powf.3posix.html -.. _`powl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/powl.3.html -.. _`powl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/powl.3posix.html -.. _`ppoll(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/ppoll.2.html -.. _`pr(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pr.1.html -.. _`pr(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pr.1posix.html -.. _`prctl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/prctl.2.html -.. _`pread(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/pread.2.html -.. _`pread(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pread.3posix.html -.. _`pread64(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/pread64.2.html -.. _`preconv(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/preconv.1.html -.. _`prefresh(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/prefresh.3ncurses.html -.. _`prename(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/prename.1.html -.. _`print(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/print.1.html -.. _`print(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/print.3ncurses.html -.. _`printenv(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/printenv.1.html -.. _`printerbanner(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/printerbanner.1.html -.. _`printf(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/printf.1.html -.. _`printf(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/printf.1posix.html -.. _`printf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/printf.3.html -.. _`printf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/printf.3posix.html -.. _`printw(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/printw.3ncurses.html -.. _`proc(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/proc.5.html -.. _`prof(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/prof.2.html -.. _`profil(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/profil.3.html -.. _`program_invocation_name(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/program_invocation_name.3.html -.. _`program_invocation_short_name(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/program_invocation_short_name.3.html -.. _`protocols(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/protocols.5.html -.. _`prove(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/prove.1.html -.. _`prs(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/prs.1posix.html -.. _`prtstat(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/prtstat.1.html -.. _`ps(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ps.1.html -.. _`ps(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ps.1posix.html -.. _`psed(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/psed.1.html -.. _`pselect(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/pselect.2.html -.. _`pselect(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pselect.3posix.html -.. _`pselect6(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/pselect6.2.html -.. _`psignal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/psignal.3.html -.. _`pstree(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pstree.1.html -.. _`pstree.x11(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pstree.x11.1.html -.. _`pstruct(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pstruct.1.html -.. _`ptar(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ptar.1.html -.. _`ptardiff(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ptardiff.1.html -.. _`pthread_atfork(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_atfork.3posix.html -.. _`pthread_attr_destroy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_destroy.3.html -.. _`pthread_attr_destroy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_destroy.3posix.html -.. _`pthread_attr_getaffinity_np(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getaffinity_np.3.html -.. _`pthread_attr_getdetachstate(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getdetachstate.3.html -.. _`pthread_attr_getdetachstate(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getdetachstate.3posix.html -.. _`pthread_attr_getguardsize(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getguardsize.3.html -.. _`pthread_attr_getguardsize(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getguardsize.3posix.html -.. _`pthread_attr_getinheritsched(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getinheritsched.3.html -.. _`pthread_attr_getinheritsched(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getinheritsched.3posix.html -.. _`pthread_attr_getschedparam(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getschedparam.3.html -.. _`pthread_attr_getschedparam(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getschedparam.3posix.html -.. _`pthread_attr_getschedpolicy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getschedpolicy.3.html -.. _`pthread_attr_getschedpolicy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getschedpolicy.3posix.html -.. _`pthread_attr_getscope(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getscope.3.html -.. _`pthread_attr_getscope(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getscope.3posix.html -.. _`pthread_attr_getstack(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getstack.3.html -.. _`pthread_attr_getstack(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getstack.3posix.html -.. _`pthread_attr_getstackaddr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getstackaddr.3.html -.. _`pthread_attr_getstackaddr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getstackaddr.3posix.html -.. _`pthread_attr_getstacksize(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getstacksize.3.html -.. _`pthread_attr_getstacksize(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_getstacksize.3posix.html -.. _`pthread_attr_init(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_init.3.html -.. _`pthread_attr_init(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_init.3posix.html -.. _`pthread_attr_setaffinity_np(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setaffinity_np.3.html -.. _`pthread_attr_setdetachstate(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setdetachstate.3.html -.. _`pthread_attr_setdetachstate(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setdetachstate.3posix.html -.. _`pthread_attr_setguardsize(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setguardsize.3.html -.. _`pthread_attr_setguardsize(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setguardsize.3posix.html -.. _`pthread_attr_setinheritsched(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setinheritsched.3.html -.. _`pthread_attr_setinheritsched(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setinheritsched.3posix.html -.. _`pthread_attr_setschedparam(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setschedparam.3.html -.. _`pthread_attr_setschedparam(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setschedparam.3posix.html -.. _`pthread_attr_setschedpolicy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setschedpolicy.3.html -.. _`pthread_attr_setschedpolicy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setschedpolicy.3posix.html -.. _`pthread_attr_setscope(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setscope.3.html -.. _`pthread_attr_setscope(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setscope.3posix.html -.. _`pthread_attr_setstack(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setstack.3.html -.. _`pthread_attr_setstack(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setstack.3posix.html -.. _`pthread_attr_setstackaddr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setstackaddr.3.html -.. _`pthread_attr_setstackaddr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setstackaddr.3posix.html -.. _`pthread_attr_setstacksize(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setstacksize.3.html -.. _`pthread_attr_setstacksize(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_attr_setstacksize.3posix.html -.. _`pthread_barrierattr_destroy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_barrierattr_destroy.3posix.html -.. _`pthread_barrierattr_getpshared(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_barrierattr_getpshared.3posix.html -.. _`pthread_barrierattr_init(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_barrierattr_init.3posix.html -.. _`pthread_barrierattr_setpshared(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_barrierattr_setpshared.3posix.html -.. _`pthread_barrier_destroy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_barrier_destroy.3posix.html -.. _`pthread_barrier_init(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_barrier_init.3posix.html -.. _`pthread_barrier_wait(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_barrier_wait.3posix.html -.. _`pthread_cancel(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_cancel.3.html -.. _`pthread_cancel(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_cancel.3posix.html -.. _`pthread_cleanup_pop(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_cleanup_pop.3.html -.. _`pthread_cleanup_pop(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_cleanup_pop.3posix.html -.. _`pthread_cleanup_pop_restore_np(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_cleanup_pop_restore_np.3.html -.. _`pthread_cleanup_push(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_cleanup_push.3.html -.. _`pthread_cleanup_push(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_cleanup_push.3posix.html -.. _`pthread_cleanup_push_defer_np(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_cleanup_push_defer_np.3.html -.. _`pthread_condattr_destroy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_condattr_destroy.3posix.html -.. _`pthread_condattr_getclock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_condattr_getclock.3posix.html -.. _`pthread_condattr_getpshared(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_condattr_getpshared.3posix.html -.. _`pthread_condattr_init(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_condattr_init.3posix.html -.. _`pthread_condattr_setclock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_condattr_setclock.3posix.html -.. _`pthread_condattr_setpshared(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_condattr_setpshared.3posix.html -.. _`pthread_cond_broadcast(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_cond_broadcast.3posix.html -.. _`pthread_cond_destroy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_cond_destroy.3posix.html -.. _`pthread_cond_init(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_cond_init.3posix.html -.. _`pthread_cond_signal(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_cond_signal.3posix.html -.. _`pthread_cond_timedwait(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_cond_timedwait.3posix.html -.. _`pthread_cond_wait(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_cond_wait.3posix.html -.. _`pthread_create(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_create.3.html -.. _`pthread_create(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_create.3posix.html -.. _`pthread_detach(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_detach.3.html -.. _`pthread_detach(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_detach.3posix.html -.. _`pthread_equal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_equal.3.html -.. _`pthread_equal(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_equal.3posix.html -.. _`pthread_exit(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_exit.3.html -.. _`pthread_exit(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_exit.3posix.html -.. _`pthread_getaffinity_np(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_getaffinity_np.3.html -.. _`pthread_getattr_np(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_getattr_np.3.html -.. _`pthread_getconcurrency(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_getconcurrency.3.html -.. _`pthread_getconcurrency(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_getconcurrency.3posix.html -.. _`pthread_getcpuclockid(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_getcpuclockid.3.html -.. _`pthread_getcpuclockid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_getcpuclockid.3posix.html -.. _`pthread_getschedparam(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_getschedparam.3.html -.. _`pthread_getschedparam(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_getschedparam.3posix.html -.. _`pthread_getspecific(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_getspecific.3posix.html -.. _`pthread.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/pthread.h.7posix.html -.. _`pthread_join(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_join.3.html -.. _`pthread_join(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_join.3posix.html -.. _`pthread_key_create(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_key_create.3posix.html -.. _`pthread_key_delete(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_key_delete.3posix.html -.. _`pthread_kill(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_kill.3.html -.. _`pthread_kill(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_kill.3posix.html -.. _`pthread_kill_other_threads_np(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_kill_other_threads_np.3.html -.. _`pthread_mutexattr_destroy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutexattr_destroy.3posix.html -.. _`pthread_mutexattr_getprioceiling(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutexattr_getprioceiling.3posix.html -.. _`pthread_mutexattr_getprotocol(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutexattr_getprotocol.3posix.html -.. _`pthread_mutexattr_getpshared(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutexattr_getpshared.3posix.html -.. _`pthread_mutexattr_gettype(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutexattr_gettype.3posix.html -.. _`pthread_mutexattr_init(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutexattr_init.3posix.html -.. _`pthread_mutexattr_setprioceiling(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutexattr_setprioceiling.3posix.html -.. _`pthread_mutexattr_setprotocol(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutexattr_setprotocol.3posix.html -.. _`pthread_mutexattr_setpshared(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutexattr_setpshared.3posix.html -.. _`pthread_mutexattr_settype(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutexattr_settype.3posix.html -.. _`pthread_mutex_destroy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutex_destroy.3posix.html -.. _`pthread_mutex_getprioceiling(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutex_getprioceiling.3posix.html -.. _`pthread_mutex_init(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutex_init.3posix.html -.. _`pthread_mutex_lock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutex_lock.3posix.html -.. _`pthread_mutex_setprioceiling(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutex_setprioceiling.3posix.html -.. _`pthread_mutex_timedlock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutex_timedlock.3posix.html -.. _`pthread_mutex_trylock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutex_trylock.3posix.html -.. _`pthread_mutex_unlock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_mutex_unlock.3posix.html -.. _`pthread_once(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_once.3posix.html -.. _`pthread_rwlockattr_destroy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_rwlockattr_destroy.3posix.html -.. _`pthread_rwlockattr_getpshared(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_rwlockattr_getpshared.3posix.html -.. _`pthread_rwlockattr_init(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_rwlockattr_init.3posix.html -.. _`pthread_rwlockattr_setpshared(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_rwlockattr_setpshared.3posix.html -.. _`pthread_rwlock_destroy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_rwlock_destroy.3posix.html -.. _`pthread_rwlock_init(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_rwlock_init.3posix.html -.. _`pthread_rwlock_rdlock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_rwlock_rdlock.3posix.html -.. _`pthread_rwlock_timedrdlock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_rwlock_timedrdlock.3posix.html -.. _`pthread_rwlock_timedwrlock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_rwlock_timedwrlock.3posix.html -.. _`pthread_rwlock_tryrdlock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_rwlock_tryrdlock.3posix.html -.. _`pthread_rwlock_trywrlock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_rwlock_trywrlock.3posix.html -.. _`pthread_rwlock_unlock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_rwlock_unlock.3posix.html -.. _`pthread_rwlock_wrlock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_rwlock_wrlock.3posix.html -.. _`pthreads(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/pthreads.7.html -.. _`pthread_self(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_self.3.html -.. _`pthread_self(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_self.3posix.html -.. _`pthread_setaffinity_np(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_setaffinity_np.3.html -.. _`pthread_setcancelstate(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_setcancelstate.3.html -.. _`pthread_setcancelstate(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_setcancelstate.3posix.html -.. _`pthread_setcanceltype(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_setcanceltype.3.html -.. _`pthread_setcanceltype(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_setcanceltype.3posix.html -.. _`pthread_setconcurrency(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_setconcurrency.3.html -.. _`pthread_setconcurrency(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_setconcurrency.3posix.html -.. _`pthread_setschedparam(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_setschedparam.3.html -.. _`pthread_setschedparam(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_setschedparam.3posix.html -.. _`pthread_setschedprio(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_setschedprio.3.html -.. _`pthread_setschedprio(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_setschedprio.3posix.html -.. _`pthread_setspecific(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_setspecific.3posix.html -.. _`pthread_sigmask(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_sigmask.3.html -.. _`pthread_sigmask(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_sigmask.3posix.html -.. _`pthread_spin_destroy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_spin_destroy.3posix.html -.. _`pthread_spin_init(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_spin_init.3posix.html -.. _`pthread_spin_lock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_spin_lock.3posix.html -.. _`pthread_spin_trylock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_spin_trylock.3posix.html -.. _`pthread_spin_unlock(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_spin_unlock.3posix.html -.. _`pthread_testcancel(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_testcancel.3.html -.. _`pthread_testcancel(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_testcancel.3posix.html -.. _`pthread_timedjoin_np(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_timedjoin_np.3.html -.. _`pthread_tryjoin_np(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_tryjoin_np.3.html -.. _`pthread_yield(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pthread_yield.3.html -.. _`ptmx(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/ptmx.4.html -.. _`ptrace(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/ptrace.2.html -.. _`pts(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/pts.4.html -.. _`ptsname(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ptsname.3.html -.. _`ptsname(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ptsname.3posix.html -.. _`ptsname_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ptsname_r.3.html -.. _`ptx(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ptx.1.html -.. _`pty(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/pty.7.html -.. _`putc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putc.3.html -.. _`putc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putc.3posix.html -.. _`putchar(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putchar.3.html -.. _`putchar(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putchar.3posix.html -.. _`putchar_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putchar_unlocked.3.html -.. _`putchar_unlocked(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putchar_unlocked.3posix.html -.. _`putc_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putc_unlocked.3.html -.. _`putc_unlocked(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putc_unlocked.3posix.html -.. _`putenv(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putenv.3.html -.. _`putenv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putenv.3posix.html -.. _`putgrent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putgrent.3.html -.. _`putmsg(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putmsg.3posix.html -.. _`putp(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putp.3ncurses.html -.. _`putpmsg(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/putpmsg.2.html -.. _`putpmsg(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putpmsg.3posix.html -.. _`putpwent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putpwent.3.html -.. _`puts(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/puts.3.html -.. _`puts(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/puts.3posix.html -.. _`putspent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putspent.3.html -.. _`pututline(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pututline.3.html -.. _`pututxline(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pututxline.3.html -.. _`pututxline(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pututxline.3posix.html -.. _`putw(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putw.3.html -.. _`putwc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putwc.3.html -.. _`putwc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putwc.3posix.html -.. _`putwchar(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putwchar.3.html -.. _`putwchar(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putwchar.3posix.html -.. _`putwchar_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putwchar_unlocked.3.html -.. _`putwc_unlocked(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putwc_unlocked.3.html -.. _`putwin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/putwin.3ncurses.html -.. _`pwck(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pwck.8.html -.. _`pwconv(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pwconv.8.html -.. _`pwd(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pwd.1.html -.. _`pwd(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pwd.1posix.html -.. _`pwd.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/pwd.h.7posix.html -.. _`pwdx(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pwdx.1.html -.. _`pwrite(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/pwrite.2.html -.. _`pwrite(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/pwrite.3posix.html -.. _`pwrite64(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/pwrite64.2.html -.. _`pwunconv(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/pwunconv.8.html -.. _`pycentral(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pycentral.1.html -.. _`pyclean(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pyclean.1.html -.. _`pycompile(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pycompile.1.html -.. _`py_compilefiles(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/py_compilefiles.1.html -.. _`pydoc(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pydoc.1.html -.. _`pydoc2.6(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pydoc2.6.1.html -.. _`pygettext(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pygettext.1.html -.. _`pygettext2.6(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pygettext2.6.1.html -.. _`python(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/python.1.html -.. _`python2.6(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/python2.6.1.html -.. _`pyversions(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/pyversions.1.html -.. _`qalter(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/qalter.1posix.html -.. _`qdel(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/qdel.1posix.html -.. _`qecvt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/qecvt.3.html -.. _`qecvt_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/qecvt_r.3.html -.. _`qfcvt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/qfcvt.3.html -.. _`qfcvt_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/qfcvt_r.3.html -.. _`qgcvt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/qgcvt.3.html -.. _`qhold(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/qhold.1posix.html -.. _`qiflush(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/qiflush.3ncurses.html -.. _`qmove(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/qmove.1posix.html -.. _`qmsg(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/qmsg.1posix.html -.. _`qrerun(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/qrerun.1posix.html -.. _`qrls(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/qrls.1posix.html -.. _`qselect(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/qselect.1posix.html -.. _`qsig(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/qsig.1posix.html -.. _`qsort(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/qsort.3.html -.. _`qsort(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/qsort.3posix.html -.. _`qstat(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/qstat.1posix.html -.. _`qsub(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/qsub.1posix.html -.. _`queue(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/queue.3.html -.. _`quotactl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/quotactl.2.html -.. _`raise(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/raise.3.html -.. _`raise(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/raise.3posix.html -.. _`ram(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/ram.4.html -.. _`ramsize(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ramsize.8.html -.. _`rand(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rand.1ssl.html -.. _`rand(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rand.3.html -.. _`rand(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rand.3posix.html -.. _`random(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/random.3.html -.. _`random(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/random.3posix.html -.. _`random(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/random.4.html -.. _`random_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/random_r.3.html -.. _`rand_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rand_r.3.html -.. _`rand_r(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rand_r.3posix.html -.. _`ranlib(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ranlib.1.html -.. _`rarp(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/rarp.8.html -.. _`raw(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/raw.3ncurses.html -.. _`raw(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/raw.7.html -.. _`raw(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/raw.8.html -.. _`rawmemchr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rawmemchr.3.html -.. _`rbash(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rbash.1.html -.. _`rcmd(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rcmd.3.html -.. _`rcp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rcp.1.html -.. _`rcs(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/rcs.5.html -.. _`rdev(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/rdev.8.html -.. _`read(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/read.1posix.html -.. _`read(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/read.2.html -.. _`read(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/read.3posix.html -.. _`readahead(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/readahead.2.html -.. _`readdir(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/readdir.2.html -.. _`readdir(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/readdir.3.html -.. _`readdir(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/readdir.3posix.html -.. _`readdir_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/readdir_r.3.html -.. _`readdir_r(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/readdir_r.3posix.html -.. _`readelf(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/readelf.1.html -.. _`readline(3readline)` : http://sites.uclouvain.be/SystInfo/manpages/man3/readline.3readline.html -.. _`readlink(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/readlink.1.html -.. _`readlink(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/readlink.2.html -.. _`readlink(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/readlink.3posix.html -.. _`readlinkat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/readlinkat.2.html -.. _`readonly(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/readonly.1posix.html -.. _`readprofile(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/readprofile.1.html -.. _`readv(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/readv.2.html -.. _`readv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/readv.3posix.html -.. _`realloc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/realloc.3.html -.. _`realloc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/realloc.3posix.html -.. _`realpath(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/realpath.3.html -.. _`realpath(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/realpath.3posix.html -.. _`reboot(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/reboot.2.html -.. _`reboot(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/reboot.8.html -.. _`recno(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/recno.3.html -.. _`re_comp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/re_comp.3.html -.. _`recv(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/recv.2.html -.. _`recv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/recv.3posix.html -.. _`recvfrom(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/recvfrom.2.html -.. _`recvfrom(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/recvfrom.3posix.html -.. _`recvmsg(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/recvmsg.2.html -.. _`recvmsg(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/recvmsg.3posix.html -.. _`redrawwin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/redrawwin.3ncurses.html -.. _`re_exec(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/re_exec.3.html -.. _`re_format(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/re_format.7.html -.. _`refresh(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/refresh.3ncurses.html -.. _`regcomp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/regcomp.3.html -.. _`regcomp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/regcomp.3posix.html -.. _`regerror(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/regerror.3.html -.. _`regerror(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/regerror.3posix.html -.. _`regex(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/regex.3.html -.. _`regex(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/regex.7.html -.. _`regexec(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/regexec.3.html -.. _`regexec(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/regexec.3posix.html -.. _`regex.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/regex.h.7posix.html -.. _`regexp::assemble(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/regexp::assemble.3pm.html -.. _`regfree(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/regfree.3.html -.. _`regfree(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/regfree.3posix.html -.. _`registerrpc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/registerrpc.3.html -.. _`remainder(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remainder.3.html -.. _`remainder(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remainder.3posix.html -.. _`remainderf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remainderf.3.html -.. _`remainderf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remainderf.3posix.html -.. _`remainderl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remainderl.3.html -.. _`remainderl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remainderl.3posix.html -.. _`remap_file_pages(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/remap_file_pages.2.html -.. _`remove(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remove.3.html -.. _`remove(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remove.3posix.html -.. _`remove-shell(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/remove-shell.8.html -.. _`remque(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remque.3.html -.. _`remque(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remque.3posix.html -.. _`remquo(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remquo.3.html -.. _`remquo(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remquo.3posix.html -.. _`remquof(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remquof.3.html -.. _`remquof(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remquof.3posix.html -.. _`remquol(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remquol.3.html -.. _`remquol(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/remquol.3posix.html -.. _`rename(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rename.1.html -.. _`rename(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/rename.2.html -.. _`rename(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rename.3posix.html -.. _`renameat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/renameat.2.html -.. _`rename.ul(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rename.ul.1.html -.. _`renice(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/renice.1.html -.. _`renice(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/renice.1posix.html -.. _`replace_panel(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/replace_panel.3curses.html -.. _`req(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/req.1ssl.html -.. _`request_key(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/request_key.2.html -.. _`requestname(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/requestname.3form.html -.. _`requestname(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/requestname.3menu.html -.. _`reset(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/reset.1.html -.. _`reset_prog_mode(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/reset_prog_mode.3ncurses.html -.. _`reset_shell_mode(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/reset_shell_mode.3ncurses.html -.. _`resetty(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/resetty.3ncurses.html -.. _`res_init(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/res_init.3.html -.. _`resize2fs(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/resize2fs.8.html -.. _`resize_term(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/resize_term.3ncurses.html -.. _`resizeterm(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/resizeterm.3ncurses.html -.. _`res_mkquery(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/res_mkquery.3.html -.. _`resolv.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/resolv.conf.5.html -.. _`resolver(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/resolver.3.html -.. _`resolver(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/resolver.5.html -.. _`resource.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/resource.h.7posix.html -.. _`res_query(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/res_query.3.html -.. _`res_querydomain(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/res_querydomain.3.html -.. _`res_search(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/res_search.3.html -.. _`res_send(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/res_send.3.html -.. _`restartterm(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/restartterm.3ncurses.html -.. _`return(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/return.1posix.html -.. _`rev(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rev.1.html -.. _`rewind(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rewind.3.html -.. _`rewind(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rewind.3posix.html -.. _`rewinddir(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rewinddir.3.html -.. _`rewinddir(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rewinddir.3posix.html -.. _`rexec(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rexec.3.html -.. _`rgrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rgrep.1.html -.. _`rindex(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rindex.3.html -.. _`rindex(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rindex.3posix.html -.. _`rint(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rint.3.html -.. _`rint(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rint.3posix.html -.. _`rintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rintf.3.html -.. _`rintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rintf.3posix.html -.. _`rintl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rintl.3.html -.. _`rintl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rintl.3posix.html -.. _`ripemd160(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ripemd160.1ssl.html -.. _`ripoffline(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ripoffline.3ncurses.html -.. _`rlogin(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rlogin.1.html -.. _`rm(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rm.1.html -.. _`rm(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rm.1posix.html -.. _`rmail(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/rmail.8.html -.. _`rmdel(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rmdel.1posix.html -.. _`rmdir(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rmdir.1.html -.. _`rmdir(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rmdir.1posix.html -.. _`rmdir(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/rmdir.2.html -.. _`rmdir(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rmdir.3posix.html -.. _`rmmod(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/rmmod.8.html -.. _`rmt(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/rmt.8.html -.. _`rmt-tar(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/rmt-tar.8.html -.. _`rnano(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rnano.1.html -.. _`rootflags(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/rootflags.8.html -.. _`rotatelogs(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/rotatelogs.8.html -.. _`round(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/round.3.html -.. _`round(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/round.3posix.html -.. _`roundf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/roundf.3.html -.. _`roundf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/roundf.3posix.html -.. _`roundl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/roundl.3.html -.. _`roundl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/roundl.3posix.html -.. _`route(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/route.8.html -.. _`routef(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/routef.8.html -.. _`routel(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/routel.8.html -.. _`rpc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rpc.3.html -.. _`rpc(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/rpc.5.html -.. _`rpcgen(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rpcgen.1.html -.. _`rpcinfo(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/rpcinfo.8.html -.. _`rpmatch(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rpmatch.3.html -.. _`rresvport(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rresvport.3.html -.. _`rsa(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rsa.1ssl.html -.. _`rsautl(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rsautl.1ssl.html -.. _`rsh(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rsh.1.html -.. _`rsmtp(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/rsmtp.8.html -.. _`rsync(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rsync.1.html -.. _`rsyncd.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/rsyncd.conf.5.html -.. _`rsyslog.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/rsyslog.conf.5.html -.. _`rsyslogd(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/rsyslogd.8.html -.. _`rtacct(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/rtacct.8.html -.. _`rtc(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/rtc.4.html -.. _`rtcwake(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/rtcwake.8.html -.. _`rtime(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rtime.3.html -.. _`rtld-audit(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/rtld-audit.7.html -.. _`rtmon(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/rtmon.8.html -.. _`rtnetlink(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/rtnetlink.3.html -.. _`rtnetlink(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/rtnetlink.7.html -.. _`rt_sigaction(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/rt_sigaction.2.html -.. _`rt_sigpending(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/rt_sigpending.2.html -.. _`rt_sigprocmask(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/rt_sigprocmask.2.html -.. _`rt_sigqueueinfo(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/rt_sigqueueinfo.2.html -.. _`rt_sigreturn(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/rt_sigreturn.2.html -.. _`rt_sigsuspend(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/rt_sigsuspend.2.html -.. _`rt_sigtimedwait(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/rt_sigtimedwait.2.html -.. _`rtstat(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/rtstat.8.html -.. _`runcon(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/runcon.1.html -.. _`runlevel(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/runlevel.8.html -.. _`run-mailcap(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/run-mailcap.1.html -.. _`run-parts(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/run-parts.8.html -.. _`runq(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/runq.8.html -.. _`ruserok(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ruserok.3.html -.. _`rview(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rview.1.html -.. _`rvim(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rvim.1.html -.. _`rzsh(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/rzsh.1.html -.. _`s2p(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/s2p.1.html -.. _`sact(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sact.1posix.html -.. _`safe_finger(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/safe_finger.8.html -.. _`savelog(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/savelog.8.html -.. _`savetty(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/savetty.3ncurses.html -.. _`sbrk(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sbrk.2.html -.. _`scalb(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalb.3.html -.. _`scalb(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalb.3posix.html -.. _`scalbf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalbf.3.html -.. _`scalbl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalbl.3.html -.. _`scalbln(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalbln.3.html -.. _`scalbln(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalbln.3posix.html -.. _`scalblnf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalblnf.3.html -.. _`scalblnf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalblnf.3posix.html -.. _`scalblnl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalblnl.3.html -.. _`scalblnl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalblnl.3posix.html -.. _`scalbn(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalbn.3.html -.. _`scalbn(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalbn.3posix.html -.. _`scalbnf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalbnf.3.html -.. _`scalbnf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalbnf.3posix.html -.. _`scalbnl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalbnl.3.html -.. _`scalbnl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scalbnl.3posix.html -.. _`scale_form(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scale_form.3form.html -.. _`scale_menu(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scale_menu.3menu.html -.. _`scandir(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scandir.3.html -.. _`scanf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scanf.3.html -.. _`scanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scanf.3posix.html -.. _`scanw(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scanw.3ncurses.html -.. _`sccs(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sccs.1posix.html -.. _`sched_getaffinity(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sched_getaffinity.2.html -.. _`sched_getcpu(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sched_getcpu.3.html -.. _`sched_getparam(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sched_getparam.2.html -.. _`sched_getparam(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sched_getparam.3posix.html -.. _`sched_get_priority_max(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sched_get_priority_max.2.html -.. _`sched_get_priority_max(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sched_get_priority_max.3posix.html -.. _`sched_get_priority_min(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sched_get_priority_min.2.html -.. _`sched_get_priority_min(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sched_get_priority_min.3posix.html -.. _`sched_getscheduler(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sched_getscheduler.2.html -.. _`sched_getscheduler(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sched_getscheduler.3posix.html -.. _`sched.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sched.h.7posix.html -.. _`sched_rr_get_interval(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sched_rr_get_interval.2.html -.. _`sched_rr_get_interval(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sched_rr_get_interval.3posix.html -.. _`sched_setaffinity(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sched_setaffinity.2.html -.. _`sched_setparam(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sched_setparam.2.html -.. _`sched_setparam(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sched_setparam.3posix.html -.. _`sched_setscheduler(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sched_setscheduler.2.html -.. _`sched_setscheduler(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sched_setscheduler.3posix.html -.. _`sched_yield(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sched_yield.2.html -.. _`sched_yield(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sched_yield.3posix.html -.. _`s_client(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/s_client.1ssl.html -.. _`scp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/scp.1.html -.. _`scr_dump(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scr_dump.3ncurses.html -.. _`screen(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/screen.1.html -.. _`scr_init(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scr_init.3ncurses.html -.. _`script(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/script.1.html -.. _`scriptreplay(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/scriptreplay.1.html -.. _`scrl(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scrl.3ncurses.html -.. _`scroll(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scroll.3ncurses.html -.. _`scrollok(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scrollok.3ncurses.html -.. _`scr_restore(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scr_restore.3ncurses.html -.. _`scr_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/scr_set.3ncurses.html -.. _`scsi_id(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/scsi_id.8.html -.. _`sd(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/sd.4.html -.. _`sdiff(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sdiff.1.html -.. _`search.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/search.h.7posix.html -.. _`securetty(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/securetty.5.html -.. _`security(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/security.2.html -.. _`sed(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sed.1.html -.. _`sed(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sed.1posix.html -.. _`see(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/see.1.html -.. _`seed48(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/seed48.3.html -.. _`seed48(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/seed48.3posix.html -.. _`seed48_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/seed48_r.3.html -.. _`seekdir(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/seekdir.3.html -.. _`seekdir(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/seekdir.3posix.html -.. _`select(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/select.2.html -.. _`select(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/select.3posix.html -.. _`select.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/select.h.7posix.html -.. _`select_tut(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/select_tut.2.html -.. _`semaphore.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/semaphore.h.7posix.html -.. _`sem_close(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_close.3.html -.. _`sem_close(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_close.3posix.html -.. _`semctl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/semctl.2.html -.. _`semctl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/semctl.3posix.html -.. _`sem_destroy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_destroy.3.html -.. _`sem_destroy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_destroy.3posix.html -.. _`semget(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/semget.2.html -.. _`semget(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/semget.3posix.html -.. _`sem_getvalue(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_getvalue.3.html -.. _`sem_getvalue(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_getvalue.3posix.html -.. _`sem.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sem.h.7posix.html -.. _`sem_init(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_init.3.html -.. _`sem_init(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_init.3posix.html -.. _`semop(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/semop.2.html -.. _`semop(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/semop.3posix.html -.. _`sem_open(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_open.3.html -.. _`sem_open(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_open.3posix.html -.. _`sem_overview(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sem_overview.7.html -.. _`sem_post(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_post.3.html -.. _`sem_post(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_post.3posix.html -.. _`semtimedop(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/semtimedop.2.html -.. _`sem_timedwait(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_timedwait.3.html -.. _`sem_timedwait(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_timedwait.3posix.html -.. _`sem_trywait(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_trywait.3.html -.. _`sem_trywait(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_trywait.3posix.html -.. _`sem_unlink(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_unlink.3.html -.. _`sem_unlink(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_unlink.3posix.html -.. _`sem_wait(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_wait.3.html -.. _`sem_wait(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sem_wait.3posix.html -.. _`send(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/send.2.html -.. _`send(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/send.3posix.html -.. _`sendfile(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sendfile.2.html -.. _`sendfile64(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sendfile64.2.html -.. _`sendmail(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/sendmail.8.html -.. _`sendmsg(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sendmsg.2.html -.. _`sendmsg(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sendmsg.3posix.html -.. _`sendto(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sendto.2.html -.. _`sendto(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sendto.3posix.html -.. _`sensible-browser(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sensible-browser.1.html -.. _`sensible-editor(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sensible-editor.1.html -.. _`sensible-pager(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sensible-pager.1.html -.. _`sepermit.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/sepermit.conf.5.html -.. _`seq(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/seq.1.html -.. _`service(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/service.8.html -.. _`services(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/services.5.html -.. _`sess_id(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sess_id.1ssl.html -.. _`set(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/set.1posix.html -.. _`setaliasent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setaliasent.3.html -.. _`setarch(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/setarch.8.html -.. _`setbuf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setbuf.3.html -.. _`setbuf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setbuf.3posix.html -.. _`setbuffer(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setbuffer.3.html -.. _`setcchar(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setcchar.3ncurses.html -.. _`setcontext(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setcontext.2.html -.. _`setcontext(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setcontext.3posix.html -.. _`set_current_field(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_current_field.3form.html -.. _`set_current_item(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_current_item.3menu.html -.. _`set_curterm(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_curterm.3ncurses.html -.. _`setdomainname(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setdomainname.2.html -.. _`setegid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setegid.2.html -.. _`setegid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setegid.3posix.html -.. _`setenv(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setenv.3.html -.. _`setenv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setenv.3posix.html -.. _`set_escdelay(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_escdelay.3ncurses.html -.. _`seteuid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/seteuid.2.html -.. _`seteuid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/seteuid.3posix.html -.. _`set_field_back(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_field_back.3form.html -.. _`set_field_buffer(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_field_buffer.3form.html -.. _`set_field_fore(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_field_fore.3form.html -.. _`set_field_init(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_field_init.3form.html -.. _`set_field_just(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_field_just.3form.html -.. _`set_field_opts(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_field_opts.3form.html -.. _`set_field_pad(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_field_pad.3form.html -.. _`set_field_status(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_field_status.3form.html -.. _`set_field_term(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_field_term.3form.html -.. _`set_field_type(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_field_type.3form.html -.. _`set_fieldtype_arg(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_fieldtype_arg.3form.html -.. _`set_fieldtype_choice(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_fieldtype_choice.3form.html -.. _`set_field_userptr(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_field_userptr.3form.html -.. _`set_form_fields(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_form_fields.3form.html -.. _`set_form_init(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_form_init.3form.html -.. _`set_form_opts(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_form_opts.3form.html -.. _`set_form_page(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_form_page.3form.html -.. _`set_form_sub(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_form_sub.3form.html -.. _`set_form_term(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_form_term.3form.html -.. _`set_form_userptr(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_form_userptr.3form.html -.. _`set_form_win(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_form_win.3form.html -.. _`__setfpucw(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/__setfpucw.3.html -.. _`setfsent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setfsent.3.html -.. _`setfsgid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setfsgid.2.html -.. _`setfsgid32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setfsgid32.2.html -.. _`setfsuid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setfsuid.2.html -.. _`setfsuid32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setfsuid32.2.html -.. _`setgid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setgid.2.html -.. _`setgid32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setgid32.2.html -.. _`setgid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setgid.3posix.html -.. _`setgrent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setgrent.3.html -.. _`setgrent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setgrent.3posix.html -.. _`setgroups(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setgroups.2.html -.. _`setgroups32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setgroups32.2.html -.. _`sethostent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sethostent.3.html -.. _`sethostent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sethostent.3posix.html -.. _`sethostid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sethostid.2.html -.. _`sethostid(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sethostid.3.html -.. _`sethostname(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sethostname.2.html -.. _`set_item_init(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_item_init.3menu.html -.. _`set_item_opts(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_item_opts.3menu.html -.. _`set_item_term(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_item_term.3menu.html -.. _`set_item_userptr(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_item_userptr.3menu.html -.. _`set_item_value(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_item_value.3menu.html -.. _`setitimer(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setitimer.2.html -.. _`setitimer(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setitimer.3posix.html -.. _`setjmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setjmp.3.html -.. _`_setjmp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_setjmp.3posix.html -.. _`setjmp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setjmp.3posix.html -.. _`setjmp.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/setjmp.h.7posix.html -.. _`setkey(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setkey.3.html -.. _`setkey(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setkey.3posix.html -.. _`setkey_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setkey_r.3.html -.. _`setlinebuf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setlinebuf.3.html -.. _`setlocale(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setlocale.3.html -.. _`setlocale(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setlocale.3posix.html -.. _`setlogmask(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setlogmask.3.html -.. _`setlogmask(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setlogmask.3posix.html -.. _`set_max_field(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_max_field.3form.html -.. _`set_menu_back(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_menu_back.3menu.html -.. _`set_menu_fore(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_menu_fore.3menu.html -.. _`set_menu_format(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_menu_format.3menu.html -.. _`set_menu_grey(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_menu_grey.3menu.html -.. _`set_menu_init(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_menu_init.3menu.html -.. _`set_menu_items(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_menu_items.3menu.html -.. _`set_menu_mark(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_menu_mark.3menu.html -.. _`set_menu_opts(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_menu_opts.3menu.html -.. _`set_menu_pad(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_menu_pad.3menu.html -.. _`set_menu_pattern(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_menu_pattern.3menu.html -.. _`set_menu_spacing(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_menu_spacing.3menu.html -.. _`set_menu_sub(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_menu_sub.3menu.html -.. _`set_menu_term(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_menu_term.3menu.html -.. _`set_menu_userptr(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_menu_userptr.3menu.html -.. _`set_menu_win(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_menu_win.3menu.html -.. _`setmntent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setmntent.3.html -.. _`setnetent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setnetent.3.html -.. _`setnetent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setnetent.3posix.html -.. _`setnetgrent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setnetgrent.3.html -.. _`set_new_page(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_new_page.3form.html -.. _`set_panel_userptr(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_panel_userptr.3curses.html -.. _`setpgid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setpgid.2.html -.. _`setpgid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setpgid.3posix.html -.. _`setpgrp(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setpgrp.2.html -.. _`setpgrp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setpgrp.3posix.html -.. _`setpriority(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setpriority.2.html -.. _`setpriority(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setpriority.3posix.html -.. _`setprotoent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setprotoent.3.html -.. _`setprotoent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setprotoent.3posix.html -.. _`setpwent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setpwent.3.html -.. _`setpwent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setpwent.3posix.html -.. _`setregid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setregid.2.html -.. _`setregid32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setregid32.2.html -.. _`setregid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setregid.3posix.html -.. _`setresgid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setresgid.2.html -.. _`setresgid32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setresgid32.2.html -.. _`setresuid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setresuid.2.html -.. _`setresuid32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setresuid32.2.html -.. _`setreuid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setreuid.2.html -.. _`setreuid32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setreuid32.2.html -.. _`setreuid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setreuid.3posix.html -.. _`setrlimit(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setrlimit.2.html -.. _`setrlimit(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setrlimit.3posix.html -.. _`setrpcent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setrpcent.3.html -.. _`setscrreg(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setscrreg.3ncurses.html -.. _`setservent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setservent.3.html -.. _`setservent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setservent.3posix.html -.. _`setsid(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/setsid.1.html -.. _`setsid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setsid.2.html -.. _`setsid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setsid.3posix.html -.. _`setsockopt(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setsockopt.2.html -.. _`setsockopt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setsockopt.3posix.html -.. _`setspent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setspent.3.html -.. _`setstate(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setstate.3.html -.. _`setstate(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setstate.3posix.html -.. _`setstate_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setstate_r.3.html -.. _`setsyx(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setsyx.3ncurses.html -.. _`set_tabsize(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_tabsize.3ncurses.html -.. _`setterm(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/setterm.1.html -.. _`set_term(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_term.3ncurses.html -.. _`setterm(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setterm.3ncurses.html -.. _`set_thread_area(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/set_thread_area.2.html -.. _`set_tid_address(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/set_tid_address.2.html -.. _`settimeofday(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/settimeofday.2.html -.. _`set_top_row(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/set_top_row.3menu.html -.. _`setttyent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setttyent.3.html -.. _`setuid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setuid.2.html -.. _`setuid32(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setuid32.2.html -.. _`setuid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setuid.3posix.html -.. _`setup(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/setup.2.html -.. _`setupterm(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setupterm.3ncurses.html -.. _`setusershell(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setusershell.3.html -.. _`setutent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setutent.3.html -.. _`setutxent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setutxent.3.html -.. _`setutxent(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setutxent.3posix.html -.. _`setvbuf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setvbuf.3.html -.. _`setvbuf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/setvbuf.3posix.html -.. _`sfdisk(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/sfdisk.8.html -.. _`sftp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sftp.1.html -.. _`sftp-server(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/sftp-server.8.html -.. _`sg(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sg.1.html -.. _`sgetmask(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sgetmask.2.html -.. _`sgetspent(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sgetspent.3.html -.. _`sgetspent_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sgetspent_r.3.html -.. _`sh(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sh.1.html -.. _`sh(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sh.1posix.html -.. _`sha1(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sha1.1ssl.html -.. _`sha(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sha.1ssl.html -.. _`sha1sum(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sha1sum.1.html -.. _`sha224sum(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sha224sum.1.html -.. _`sha256sum(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sha256sum.1.html -.. _`sha384sum(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sha384sum.1.html -.. _`sha512sum(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sha512sum.1.html -.. _`shadow(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/shadow.5.html -.. _`shadowconfig(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/shadowconfig.8.html -.. _`shasum(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/shasum.1.html -.. _`shcomp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/shcomp.1.html -.. _`sh.distrib(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sh.distrib.1.html -.. _`shells(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/shells.5.html -.. _`shift(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/shift.1posix.html -.. _`shmat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/shmat.2.html -.. _`shmat(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/shmat.3posix.html -.. _`shmctl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/shmctl.2.html -.. _`shmctl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/shmctl.3posix.html -.. _`shmdt(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/shmdt.2.html -.. _`shmdt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/shmdt.3posix.html -.. _`shmget(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/shmget.2.html -.. _`shmget(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/shmget.3posix.html -.. _`shm.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/shm.h.7posix.html -.. _`shmop(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/shmop.2.html -.. _`shm_open(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/shm_open.3.html -.. _`shm_open(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/shm_open.3posix.html -.. _`shm_overview(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/shm_overview.7.html -.. _`shm_unlink(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/shm_unlink.3.html -.. _`shm_unlink(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/shm_unlink.3posix.html -.. _`show_panel(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/show_panel.3curses.html -.. _`shred(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/shred.1.html -.. _`shuf(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/shuf.1.html -.. _`shutdown(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/shutdown.2.html -.. _`shutdown(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/shutdown.3posix.html -.. _`shutdown(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/shutdown.8.html -.. _`sigaction(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sigaction.2.html -.. _`sigaction(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigaction.3posix.html -.. _`sigaddset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigaddset.3.html -.. _`sigaddset(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigaddset.3posix.html -.. _`sigaltstack(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sigaltstack.2.html -.. _`sigaltstack(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigaltstack.3posix.html -.. _`sigandset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigandset.3.html -.. _`sigblock(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigblock.3.html -.. _`sigdelset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigdelset.3.html -.. _`sigdelset(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigdelset.3posix.html -.. _`sigemptyset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigemptyset.3.html -.. _`sigemptyset(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigemptyset.3posix.html -.. _`sigevent(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sigevent.7.html -.. _`sigfillset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigfillset.3.html -.. _`sigfillset(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigfillset.3posix.html -.. _`siggetmask(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/siggetmask.3.html -.. _`sighold(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sighold.3.html -.. _`sighold(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sighold.3posix.html -.. _`sigignore(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigignore.3.html -.. _`sigignore(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigignore.3posix.html -.. _`siginterrupt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/siginterrupt.3.html -.. _`siginterrupt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/siginterrupt.3posix.html -.. _`sigisemptyset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigisemptyset.3.html -.. _`sigismember(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigismember.3.html -.. _`sigismember(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigismember.3posix.html -.. _`siglongjmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/siglongjmp.3.html -.. _`siglongjmp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/siglongjmp.3posix.html -.. _`sigmask(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigmask.3.html -.. _`signal(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/signal.2.html -.. _`signal(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/signal.3posix.html -.. _`signal(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/signal.7.html -.. _`signalfd(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/signalfd.2.html -.. _`signalfd4(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/signalfd4.2.html -.. _`signal.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/signal.h.7posix.html -.. _`signbit(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/signbit.3.html -.. _`signbit(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/signbit.3posix.html -.. _`signgam(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/signgam.3.html -.. _`signgam(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/signgam.3posix.html -.. _`significand(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/significand.3.html -.. _`significandf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/significandf.3.html -.. _`significandl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/significandl.3.html -.. _`sigorset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigorset.3.html -.. _`sigpause(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigpause.3.html -.. _`sigpause(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigpause.3posix.html -.. _`sigpending(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sigpending.2.html -.. _`sigpending(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigpending.3posix.html -.. _`sigprocmask(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sigprocmask.2.html -.. _`sigprocmask(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigprocmask.3posix.html -.. _`sigqueue(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sigqueue.2.html -.. _`sigqueue(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigqueue.3posix.html -.. _`sigrelse(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigrelse.3.html -.. _`sigrelse(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigrelse.3posix.html -.. _`sigreturn(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sigreturn.2.html -.. _`sigset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigset.3.html -.. _`sigset(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigset.3posix.html -.. _`sigsetjmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigsetjmp.3.html -.. _`sigsetjmp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigsetjmp.3posix.html -.. _`sigsetmask(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigsetmask.3.html -.. _`sigsetops(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigsetops.3.html -.. _`sigsuspend(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sigsuspend.2.html -.. _`sigsuspend(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigsuspend.3posix.html -.. _`sigtimedwait(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sigtimedwait.2.html -.. _`sigtimedwait(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigtimedwait.3posix.html -.. _`sigvec(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigvec.3.html -.. _`sigwait(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigwait.3posix.html -.. _`sigwaitinfo(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sigwaitinfo.2.html -.. _`sigwaitinfo(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sigwaitinfo.3posix.html -.. _`sin(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sin.3.html -.. _`sin(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sin.3posix.html -.. _`sincos(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sincos.3.html -.. _`sincosf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sincosf.3.html -.. _`sincosl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sincosl.3.html -.. _`sinf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sinf.3.html -.. _`sinf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sinf.3posix.html -.. _`sinh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sinh.3.html -.. _`sinh(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sinh.3posix.html -.. _`sinhf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sinhf.3.html -.. _`sinhf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sinhf.3posix.html -.. _`sinhl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sinhl.3.html -.. _`sinhl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sinhl.3posix.html -.. _`sinl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sinl.3.html -.. _`sinl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sinl.3posix.html -.. _`size(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/size.1.html -.. _`sk98lin(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/sk98lin.4.html -.. _`skill(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/skill.1.html -.. _`slabinfo(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/slabinfo.5.html -.. _`slabtop(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/slabtop.1.html -.. _`slattach(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/slattach.8.html -.. _`sleep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sleep.1.html -.. _`sleep(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sleep.1posix.html -.. _`sleep(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sleep.3.html -.. _`sleep(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sleep.3posix.html -.. _`slk(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk.3ncurses.html -.. _`slk_attr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_attr.3ncurses.html -.. _`slk_attr_off(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_attr_off.3ncurses.html -.. _`slk_attroff(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_attroff.3ncurses.html -.. _`slk_attr_on(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_attr_on.3ncurses.html -.. _`slk_attron(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_attron.3ncurses.html -.. _`slk_attr_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_attr_set.3ncurses.html -.. _`slk_attrset(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_attrset.3ncurses.html -.. _`slk_clear(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_clear.3ncurses.html -.. _`slk_color(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_color.3ncurses.html -.. _`slk_init(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_init.3ncurses.html -.. _`slk_label(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_label.3ncurses.html -.. _`slk_noutrefresh(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_noutrefresh.3ncurses.html -.. _`slk_refresh(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_refresh.3ncurses.html -.. _`slk_restore(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_restore.3ncurses.html -.. _`slk_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_set.3ncurses.html -.. _`slk_touch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/slk_touch.3ncurses.html -.. _`slogin(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/slogin.1.html -.. _`smime(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/smime.1ssl.html -.. _`smime_keys(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/smime_keys.1.html -.. _`snice(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/snice.1.html -.. _`snprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/snprintf.3.html -.. _`snprintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/snprintf.3posix.html -.. _`sockatmark(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sockatmark.3.html -.. _`sockatmark(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sockatmark.3posix.html -.. _`socket(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/socket.2.html -.. _`socket(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/socket.3posix.html -.. _`socket(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/socket.7.html -.. _`socketcall(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/socketcall.2.html -.. _`socket.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/socket.h.7posix.html -.. _`socketpair(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/socketpair.2.html -.. _`socketpair(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/socketpair.3posix.html -.. _`sock_raw(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sock_raw.7.html -.. _`soelim(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/soelim.1.html -.. _`sort(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sort.1.html -.. _`sort(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sort.1posix.html -.. _`sources.list(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/sources.list.5.html -.. _`spacing(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/spacing.3menu.html -.. _`spawn.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/spawn.h.7posix.html -.. _`speed(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/speed.1ssl.html -.. _`spkac(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/spkac.1ssl.html -.. _`splain(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/splain.1.html -.. _`splice(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/splice.2.html -.. _`split(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/split.1.html -.. _`split(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/split.1posix.html -.. _`split-logfile(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/split-logfile.8.html -.. _`sprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sprintf.3.html -.. _`sprintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sprintf.3posix.html -.. _`sprof(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sprof.1.html -.. _`spu_create(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/spu_create.2.html -.. _`spufs(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/spufs.7.html -.. _`spu_run(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/spu_run.2.html -.. _`sqlite3(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sqlite3.1.html -.. _`sqrt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sqrt.3.html -.. _`sqrt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sqrt.3posix.html -.. _`sqrtf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sqrtf.3.html -.. _`sqrtf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sqrtf.3posix.html -.. _`sqrtl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sqrtl.3.html -.. _`sqrtl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sqrtl.3posix.html -.. _`srand(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/srand.3.html -.. _`srand(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/srand.3posix.html -.. _`srand48(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/srand48.3.html -.. _`srand48(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/srand48.3posix.html -.. _`srand48_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/srand48_r.3.html -.. _`srandom(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/srandom.3.html -.. _`srandom(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/srandom.3posix.html -.. _`srandom_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/srandom_r.3.html -.. _`ss(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ss.8.html -.. _`sscanf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sscanf.3.html -.. _`sscanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sscanf.3posix.html -.. _`s_server(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/s_server.1ssl.html -.. _`ssetmask(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/ssetmask.2.html -.. _`ssh(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ssh.1.html -.. _`ssh-add(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ssh-add.1.html -.. _`ssh-agent(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ssh-agent.1.html -.. _`ssh-argv0(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ssh-argv0.1.html -.. _`ssh_config(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/ssh_config.5.html -.. _`ssh-copy-id(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ssh-copy-id.1.html -.. _`sshd(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/sshd.8.html -.. _`sshd_config(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/sshd_config.5.html -.. _`ssh-keygen(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ssh-keygen.1.html -.. _`ssh-keyscan(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ssh-keyscan.1.html -.. _`ssh-keysign(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ssh-keysign.8.html -.. _`ssh-pkcs11-helper(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/ssh-pkcs11-helper.8.html -.. _`ssh-vulnkey(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ssh-vulnkey.1.html -.. _`ssignal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ssignal.3.html -.. _`st(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/st.4.html -.. _`standards(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/standards.7.html -.. _`standend(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/standend.3ncurses.html -.. _`standout(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/standout.3ncurses.html -.. _`start_color(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/start_color.3ncurses.html -.. _`startpar(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/startpar.8.html -.. _`start-stop-daemon(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/start-stop-daemon.8.html -.. _`stat(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/stat.1.html -.. _`stat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/stat.2.html -.. _`stat(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/stat.3posix.html -.. _`stat64(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/stat64.2.html -.. _`statfs(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/statfs.2.html -.. _`statfs64(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/statfs64.2.html -.. _`stat.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/stat.h.7posix.html -.. _`statvfs(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/statvfs.2.html -.. _`statvfs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/statvfs.3.html -.. _`statvfs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/statvfs.3posix.html -.. _`statvfs.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/statvfs.h.7posix.html -.. _`stdarg(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/stdarg.3.html -.. _`stdarg.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/stdarg.h.7posix.html -.. _`stdbool.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/stdbool.h.7posix.html -.. _`stdbuf(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/stdbuf.1.html -.. _`stddef.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/stddef.h.7posix.html -.. _`stderr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/stderr.3.html -.. _`stderr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/stderr.3posix.html -.. _`stdin(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/stdin.3.html -.. _`stdin(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/stdin.3posix.html -.. _`stdint.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/stdint.h.7posix.html -.. _`stdio(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/stdio.3.html -.. _`stdio_ext(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/stdio_ext.3.html -.. _`stdio.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/stdio.h.7posix.html -.. _`stdlib.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/stdlib.h.7posix.html -.. _`stdout(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/stdout.3.html -.. _`stdout(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/stdout.3posix.html -.. _`s_time(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/s_time.1ssl.html -.. _`stime(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/stime.2.html -.. _`stpcpy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/stpcpy.3.html -.. _`stpncpy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/stpncpy.3.html -.. _`strace(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/strace.1.html -.. _`strcasecmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strcasecmp.3.html -.. _`strcasecmp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strcasecmp.3posix.html -.. _`strcasestr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strcasestr.3.html -.. _`strcat(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strcat.3.html -.. _`strcat(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strcat.3posix.html -.. _`strchr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strchr.3.html -.. _`strchr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strchr.3posix.html -.. _`strchrnul(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strchrnul.3.html -.. _`strcmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strcmp.3.html -.. _`strcmp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strcmp.3posix.html -.. _`strcoll(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strcoll.3.html -.. _`strcoll(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strcoll.3posix.html -.. _`strcpy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strcpy.3.html -.. _`strcpy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strcpy.3posix.html -.. _`strcspn(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strcspn.3.html -.. _`strcspn(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strcspn.3posix.html -.. _`strdup(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strdup.3.html -.. _`strdup(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strdup.3posix.html -.. _`strdupa(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strdupa.3.html -.. _`strerror(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strerror.3.html -.. _`strerror(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strerror.3posix.html -.. _`strerror_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strerror_r.3.html -.. _`strerror_r(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strerror_r.3posix.html -.. _`strfmon(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strfmon.3.html -.. _`strfmon(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strfmon.3posix.html -.. _`strfry(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strfry.3.html -.. _`strftime(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strftime.3.html -.. _`strftime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strftime.3posix.html -.. _`string(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/string.3.html -.. _`string.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/string.h.7posix.html -.. _`strings(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/strings.1.html -.. _`strings(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/strings.1posix.html -.. _`strings.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/strings.h.7posix.html -.. _`strip(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/strip.1.html -.. _`strip(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/strip.1posix.html -.. _`strlen(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strlen.3.html -.. _`strlen(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strlen.3posix.html -.. _`strncasecmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strncasecmp.3.html -.. _`strncasecmp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strncasecmp.3posix.html -.. _`strncat(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strncat.3.html -.. _`strncat(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strncat.3posix.html -.. _`strncmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strncmp.3.html -.. _`strncmp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strncmp.3posix.html -.. _`strncpy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strncpy.3.html -.. _`strncpy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strncpy.3posix.html -.. _`strndup(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strndup.3.html -.. _`strndupa(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strndupa.3.html -.. _`strnlen(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strnlen.3.html -.. _`stropts.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/stropts.h.7posix.html -.. _`strpbrk(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strpbrk.3.html -.. _`strpbrk(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strpbrk.3posix.html -.. _`strptime(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strptime.3.html -.. _`strptime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strptime.3posix.html -.. _`strrchr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strrchr.3.html -.. _`strrchr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strrchr.3posix.html -.. _`strsep(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strsep.3.html -.. _`strsignal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strsignal.3.html -.. _`strspn(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strspn.3.html -.. _`strspn(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strspn.3posix.html -.. _`strstr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strstr.3.html -.. _`strstr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strstr.3posix.html -.. _`strtod(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtod.3.html -.. _`strtod(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtod.3posix.html -.. _`strtof(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtof.3.html -.. _`strtof(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtof.3posix.html -.. _`strtoimax(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtoimax.3.html -.. _`strtoimax(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtoimax.3posix.html -.. _`strtok(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtok.3.html -.. _`strtok(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtok.3posix.html -.. _`strtok_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtok_r.3.html -.. _`strtok_r(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtok_r.3posix.html -.. _`strtol(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtol.3.html -.. _`strtol(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtol.3posix.html -.. _`strtold(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtold.3.html -.. _`strtold(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtold.3posix.html -.. _`strtoll(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtoll.3.html -.. _`strtoll(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtoll.3posix.html -.. _`strtoq(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtoq.3.html -.. _`strtoul(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtoul.3.html -.. _`strtoul(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtoul.3posix.html -.. _`strtoull(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtoull.3.html -.. _`strtoull(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtoull.3posix.html -.. _`strtoumax(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtoumax.3.html -.. _`strtoumax(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtoumax.3posix.html -.. _`strtouq(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strtouq.3.html -.. _`strverscmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strverscmp.3.html -.. _`strxfrm(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strxfrm.3.html -.. _`strxfrm(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/strxfrm.3posix.html -.. _`stty(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/stty.1.html -.. _`stty(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/stty.1posix.html -.. _`stty(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/stty.2.html -.. _`su(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/su.1.html -.. _`subpad(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/subpad.3ncurses.html -.. _`subwin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/subwin.3ncurses.html -.. _`sudo(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/sudo.8.html -.. _`sudoedit(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/sudoedit.8.html -.. _`sudoers(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/sudoers.5.html -.. _`sudoreplay(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/sudoreplay.8.html -.. _`suffixes(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/suffixes.7.html -.. _`sulogin(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/sulogin.8.html -.. _`sum(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sum.1.html -.. _`svc_destroy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svc_destroy.3.html -.. _`svcerr_auth(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svcerr_auth.3.html -.. _`svcerr_decode(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svcerr_decode.3.html -.. _`svcerr_noproc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svcerr_noproc.3.html -.. _`svcerr_noprog(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svcerr_noprog.3.html -.. _`svcerr_progvers(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svcerr_progvers.3.html -.. _`svcerr_systemerr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svcerr_systemerr.3.html -.. _`svcerr_weakauth(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svcerr_weakauth.3.html -.. _`svcfd_create(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svcfd_create.3.html -.. _`svc_freeargs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svc_freeargs.3.html -.. _`svc_getargs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svc_getargs.3.html -.. _`svc_getcaller(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svc_getcaller.3.html -.. _`svc_getreq(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svc_getreq.3.html -.. _`svc_getreqset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svc_getreqset.3.html -.. _`svcraw_create(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svcraw_create.3.html -.. _`svc_register(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svc_register.3.html -.. _`svc_run(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svc_run.3.html -.. _`svc_sendreply(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svc_sendreply.3.html -.. _`svctcp_create(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svctcp_create.3.html -.. _`svcudp_bufcreate(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svcudp_bufcreate.3.html -.. _`svcudp_create(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svcudp_create.3.html -.. _`svc_unregister(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/svc_unregister.3.html -.. _`svipc(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/svipc.7.html -.. _`svn(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/svn.1.html -.. _`svnadmin(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/svnadmin.1.html -.. _`svndumpfilter(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/svndumpfilter.1.html -.. _`svnlook(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/svnlook.1.html -.. _`svnserve(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/svnserve.8.html -.. _`svnserve.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/svnserve.conf.5.html -.. _`svnsync(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/svnsync.1.html -.. _`svnversion(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/svnversion.1.html -.. _`swab(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/swab.3.html -.. _`swab(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/swab.3posix.html -.. _`swapcontext(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/swapcontext.3.html -.. _`swapcontext(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/swapcontext.3posix.html -.. _`swapoff(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/swapoff.2.html -.. _`swapoff(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/swapoff.8.html -.. _`swapon(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/swapon.2.html -.. _`swapon(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/swapon.8.html -.. _`switch_root(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/switch_root.8.html -.. _`swprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/swprintf.3.html -.. _`swprintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/swprintf.3posix.html -.. _`swscanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/swscanf.3posix.html -.. _`symlink(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/symlink.2.html -.. _`symlink(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/symlink.3posix.html -.. _`symlink(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/symlink.7.html -.. _`symlinkat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/symlinkat.2.html -.. _`sync(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/sync.1.html -.. _`sync(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sync.2.html -.. _`sync(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sync.3posix.html -.. _`sync(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/sync.8.html -.. _`sync_file_range(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sync_file_range.2.html -.. _`syncok(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/syncok.3ncurses.html -.. _`_syscall(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/_syscall.2.html -.. _`syscall(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/syscall.2.html -.. _`syscalls(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/syscalls.2.html -.. _`sysconf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sysconf.3.html -.. _`sysconf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sysconf.3posix.html -.. _`_sysctl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/_sysctl.2.html -.. _`sysctl(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sysctl.2.html -.. _`sysctl(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/sysctl.8.html -.. _`sysctl.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/sysctl.conf.5.html -.. _`sys_errlist(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sys_errlist.3.html -.. _`sysfs(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sysfs.2.html -.. _`sysinfo(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/sysinfo.2.html -.. _`sys_ipc.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_ipc.h.7posix.html -.. _`syslog2eximlog(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/syslog2eximlog.8.html -.. _`syslog(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/syslog.2.html -.. _`syslog(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/syslog.3.html -.. _`syslog(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/syslog.3posix.html -.. _`syslog.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/syslog.h.7posix.html -.. _`sys_mman.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_mman.h.7posix.html -.. _`sys_msg.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_msg.h.7posix.html -.. _`sys_nerr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sys_nerr.3.html -.. _`sys_resource.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_resource.h.7posix.html -.. _`sys_select.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_select.h.7posix.html -.. _`sys_sem.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_sem.h.7posix.html -.. _`sys_shm.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_shm.h.7posix.html -.. _`sys_socket.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_socket.h.7posix.html -.. _`sys_stat.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_stat.h.7posix.html -.. _`sys_statvfs.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_statvfs.h.7posix.html -.. _`system(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/system.3.html -.. _`system(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/system.3posix.html -.. _`sys_timeb.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_timeb.h.7posix.html -.. _`sys_time.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_time.h.7posix.html -.. _`sys_times.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_times.h.7posix.html -.. _`sys_types.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_types.h.7posix.html -.. _`sys_uio.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_uio.h.7posix.html -.. _`sys_un.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_un.h.7posix.html -.. _`sys_utsname.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_utsname.h.7posix.html -.. _`sysv_signal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/sysv_signal.3.html -.. _`sys_wait.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/sys_wait.h.7posix.html -.. _`tabs(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tabs.1.html -.. _`tabs(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tabs.1posix.html -.. _`tac(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tac.1.html -.. _`tail(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tail.1.html -.. _`tail(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tail.1posix.html -.. _`tailf(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tailf.1.html -.. _`talk(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/talk.1posix.html -.. _`tan(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tan.3.html -.. _`tan(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tan.3posix.html -.. _`tanf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tanf.3.html -.. _`tanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tanf.3posix.html -.. _`tanh(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tanh.3.html -.. _`tanh(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tanh.3posix.html -.. _`tanhf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tanhf.3.html -.. _`tanhf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tanhf.3posix.html -.. _`tanhl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tanhl.3.html -.. _`tanhl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tanhl.3posix.html -.. _`tanl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tanl.3.html -.. _`tanl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tanl.3posix.html -.. _`tar(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tar.1.html -.. _`tar.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/tar.h.7posix.html -.. _`tasksel(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tasksel.8.html -.. _`taskset(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/taskset.1.html -.. _`tbl(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tbl.1.html -.. _`tc(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tc.8.html -.. _`tc-bfifo(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tc-bfifo.8.html -.. _`tc-cbq(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tc-cbq.8.html -.. _`tc-cbq-details(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tc-cbq-details.8.html -.. _`tcdrain(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcdrain.3.html -.. _`tcdrain(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcdrain.3posix.html -.. _`tc-drr(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tc-drr.8.html -.. _`tcflow(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcflow.3.html -.. _`tcflow(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcflow.3posix.html -.. _`tcflush(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcflush.3.html -.. _`tcflush(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcflush.3posix.html -.. _`tcgetattr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcgetattr.3.html -.. _`tcgetattr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcgetattr.3posix.html -.. _`tcgetpgrp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcgetpgrp.3.html -.. _`tcgetpgrp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcgetpgrp.3posix.html -.. _`tcgetsid(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcgetsid.3.html -.. _`tcgetsid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcgetsid.3posix.html -.. _`tc-htb(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tc-htb.8.html -.. _`tcp(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/tcp.7.html -.. _`tcpd(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tcpd.8.html -.. _`tcpdchk(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tcpdchk.8.html -.. _`tcpdmatch(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tcpdmatch.8.html -.. _`tc-pfifo(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tc-pfifo.8.html -.. _`tc-pfifo_fast(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tc-pfifo_fast.8.html -.. _`tcp.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/tcp.h.7posix.html -.. _`tc-prio(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tc-prio.8.html -.. _`tcptraceroute(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tcptraceroute.8.html -.. _`tcptraceroute.db(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tcptraceroute.db.8.html -.. _`tc-red(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tc-red.8.html -.. _`tcsendbreak(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcsendbreak.3.html -.. _`tcsendbreak(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcsendbreak.3posix.html -.. _`tcsetattr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcsetattr.3.html -.. _`tcsetattr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcsetattr.3posix.html -.. _`tcsetpgrp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcsetpgrp.3.html -.. _`tcsetpgrp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tcsetpgrp.3posix.html -.. _`tc-sfq(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tc-sfq.8.html -.. _`tcsh(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tcsh.1.html -.. _`tc-tbf(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tc-tbf.8.html -.. _`tdelete(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tdelete.3.html -.. _`tdelete(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tdelete.3posix.html -.. _`tdestroy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tdestroy.3.html -.. _`tee(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tee.1.html -.. _`tee(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tee.1posix.html -.. _`tee(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/tee.2.html -.. _`telinit(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/telinit.8.html -.. _`telldir(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/telldir.3.html -.. _`telldir(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/telldir.3posix.html -.. _`telnet(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/telnet.1.html -.. _`telnet.netkit(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/telnet.netkit.1.html -.. _`tempfile(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tempfile.1.html -.. _`tempnam(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tempnam.3.html -.. _`tempnam(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tempnam.3posix.html -.. _`term(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/term.5.html -.. _`term(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/term.7.html -.. _`term_attrs(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/term_attrs.3ncurses.html -.. _`termattrs(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/termattrs.3ncurses.html -.. _`termcap(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/termcap.3ncurses.html -.. _`termcap(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/termcap.5.html -.. _`terminfo(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/terminfo.3ncurses.html -.. _`terminfo(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/terminfo.5.html -.. _`termio(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/termio.7.html -.. _`termios(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/termios.3.html -.. _`termios.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/termios.h.7posix.html -.. _`termname(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/termname.3ncurses.html -.. _`test(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/test.1.html -.. _`test(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/test.1posix.html -.. _`text::charwidth(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/text::charwidth.3pm.html -.. _`text::iconv(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/text::iconv.3pm.html -.. _`text::wrapi18n(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/text::wrapi18n.3pm.html -.. _`tfind(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tfind.3.html -.. _`tfind(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tfind.3posix.html -.. _`tgamma(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tgamma.3.html -.. _`tgamma(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tgamma.3posix.html -.. _`tgammaf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tgammaf.3.html -.. _`tgammaf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tgammaf.3posix.html -.. _`tgammal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tgammal.3.html -.. _`tgammal(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tgammal.3posix.html -.. _`tgetent(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tgetent.3ncurses.html -.. _`tgetflag(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tgetflag.3ncurses.html -.. _`tgetnum(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tgetnum.3ncurses.html -.. _`tgetstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tgetstr.3ncurses.html -.. _`tgkill(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/tgkill.2.html -.. _`tgmath.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/tgmath.h.7posix.html -.. _`tgoto(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tgoto.3ncurses.html -.. _`threads(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/threads.3ncurses.html -.. _`tic(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tic.1.html -.. _`tigetflag(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tigetflag.3ncurses.html -.. _`tigetnum(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tigetnum.3ncurses.html -.. _`tigetstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tigetstr.3ncurses.html -.. _`time(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/time.1posix.html -.. _`time(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/time.2.html -.. _`time(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/time.3posix.html -.. _`time(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/time.7.html -.. _`timeb.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/timeb.h.7posix.html -.. _`time.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/time.conf.5.html -.. _`timegm(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/timegm.3.html -.. _`time.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/time.h.7posix.html -.. _`timelocal(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/timelocal.3.html -.. _`timeout(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/timeout.1.html -.. _`timeout(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/timeout.3ncurses.html -.. _`timeradd(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/timeradd.3.html -.. _`timerclear(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/timerclear.3.html -.. _`timercmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/timercmp.3.html -.. _`timer_create(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/timer_create.2.html -.. _`timer_create(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/timer_create.3posix.html -.. _`timer_delete(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/timer_delete.2.html -.. _`timer_delete(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/timer_delete.3posix.html -.. _`timerfd_create(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/timerfd_create.2.html -.. _`timerfd_gettime(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/timerfd_gettime.2.html -.. _`timerfd_settime(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/timerfd_settime.2.html -.. _`timer_getoverrun(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/timer_getoverrun.2.html -.. _`timer_getoverrun(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/timer_getoverrun.3posix.html -.. _`timer_gettime(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/timer_gettime.2.html -.. _`timer_gettime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/timer_gettime.3posix.html -.. _`timerisset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/timerisset.3.html -.. _`timer_settime(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/timer_settime.2.html -.. _`timer_settime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/timer_settime.3posix.html -.. _`timersub(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/timersub.3.html -.. _`times(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/times.1posix.html -.. _`times(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/times.2.html -.. _`times(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/times.3posix.html -.. _`times.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/times.h.7posix.html -.. _`timezone(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/timezone.3.html -.. _`time::zone(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/time::zone.3pm.html -.. _`timezone(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/timezone.3posix.html -.. _`tiparm(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tiparm.3ncurses.html -.. _`tis-620(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/tis-620.7.html -.. _`tkill(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/tkill.2.html -.. _`tload(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tload.1.html -.. _`tmpfile(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tmpfile.3.html -.. _`tmpfile(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tmpfile.3posix.html -.. _`tmpnam(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tmpnam.3.html -.. _`tmpnam(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tmpnam.3posix.html -.. _`tmpnam_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tmpnam_r.3.html -.. _`toascii(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/toascii.3.html -.. _`toascii(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/toascii.3posix.html -.. _`toe(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/toe.1.html -.. _`tolower(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tolower.3.html -.. _`_tolower(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_tolower.3posix.html -.. _`tolower(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tolower.3posix.html -.. _`top(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/top.1.html -.. _`top_panel(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/top_panel.3curses.html -.. _`top_row(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/top_row.3menu.html -.. _`touch(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/touch.1.html -.. _`touch(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/touch.1posix.html -.. _`touch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/touch.3ncurses.html -.. _`touchline(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/touchline.3ncurses.html -.. _`touchwin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/touchwin.3ncurses.html -.. _`toupper(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/toupper.3.html -.. _`_toupper(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_toupper.3posix.html -.. _`toupper(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/toupper.3posix.html -.. _`towctrans(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/towctrans.3.html -.. _`towctrans(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/towctrans.3posix.html -.. _`towlower(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/towlower.3.html -.. _`towlower(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/towlower.3posix.html -.. _`towupper(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/towupper.3.html -.. _`towupper(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/towupper.3posix.html -.. _`tparm(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tparm.3ncurses.html -.. _`tput(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tput.1.html -.. _`tput(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tput.1posix.html -.. _`tputs(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tputs.3ncurses.html -.. _`tr(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tr.1.html -.. _`tr(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tr.1posix.html -.. _`trace(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/trace.3ncurses.html -.. _`_traceattr2(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_traceattr2.3ncurses.html -.. _`_traceattr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_traceattr.3ncurses.html -.. _`_tracecchar_t2(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_tracecchar_t2.3ncurses.html -.. _`_tracecchar_t(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_tracecchar_t.3ncurses.html -.. _`_tracechar(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_tracechar.3ncurses.html -.. _`_tracechtype2(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_tracechtype2.3ncurses.html -.. _`_tracechtype(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_tracechtype.3ncurses.html -.. _`_tracedump(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_tracedump.3ncurses.html -.. _`_tracef(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_tracef.3ncurses.html -.. _`trace.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/trace.h.7posix.html -.. _`_tracemouse(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/_tracemouse.3ncurses.html -.. _`traceproto(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/traceproto.1.html -.. _`traceproto.db(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/traceproto.db.1.html -.. _`traceroute(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/traceroute.1.html -.. _`traceroute6(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/traceroute6.1.html -.. _`traceroute6.db(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/traceroute6.db.1.html -.. _`traceroute.db(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/traceroute.db.1.html -.. _`traceroute-nanog(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/traceroute-nanog.1.html -.. _`trap(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/trap.1posix.html -.. _`troff(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/troff.1.html -.. _`true(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/true.1.html -.. _`true(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/true.1posix.html -.. _`trunc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/trunc.3.html -.. _`trunc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/trunc.3posix.html -.. _`truncate(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/truncate.1.html -.. _`truncate(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/truncate.2.html -.. _`truncate(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/truncate.3posix.html -.. _`truncate64(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/truncate64.2.html -.. _`truncf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/truncf.3.html -.. _`truncf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/truncf.3posix.html -.. _`truncl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/truncl.3.html -.. _`truncl(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/truncl.3posix.html -.. _`try-from(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/try-from.8.html -.. _`tsearch(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tsearch.3.html -.. _`tsearch(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tsearch.3posix.html -.. _`tset(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tset.1.html -.. _`tsort(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tsort.1.html -.. _`tsort(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tsort.1posix.html -.. _`tty(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tty.1.html -.. _`tty(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tty.1posix.html -.. _`tty(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/tty.4.html -.. _`tty_ioctl(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/tty_ioctl.4.html -.. _`ttyname(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ttyname.3.html -.. _`ttyname(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ttyname.3posix.html -.. _`ttyname_r(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ttyname_r.3.html -.. _`ttyname_r(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ttyname_r.3posix.html -.. _`ttys(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/ttys.4.html -.. _`ttyslot(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ttyslot.3.html -.. _`tune2fs(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tune2fs.8.html -.. _`tunelp(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tunelp.8.html -.. _`tuxcall(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/tuxcall.2.html -.. _`twalk(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/twalk.3.html -.. _`twalk(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/twalk.3posix.html -.. _`type(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/type.1posix.html -.. _`typeahead(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/typeahead.3ncurses.html -.. _`types.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/types.h.7posix.html -.. _`tzfile(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/tzfile.5.html -.. _`tzname(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tzname.3.html -.. _`tzname(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tzname.3posix.html -.. _`tzselect(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/tzselect.1.html -.. _`tzselect(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/tzselect.8.html -.. _`tzset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tzset.3.html -.. _`tzset(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/tzset.3posix.html -.. _`ualarm(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ualarm.3.html -.. _`ualarm(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ualarm.3posix.html -.. _`ucf(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ucf.1.html -.. _`ucf.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/ucf.conf.5.html -.. _`ucfq(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ucfq.1.html -.. _`ucfr(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ucfr.1.html -.. _`ucontext.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/ucontext.h.7posix.html -.. _`udev(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/udev.7.html -.. _`udevadm(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/udevadm.8.html -.. _`udevd(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/udevd.8.html -.. _`udp(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/udp.7.html -.. _`udplite(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/udplite.7.html -.. _`ugetrlimit(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/ugetrlimit.2.html -.. _`uio.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/uio.h.7posix.html -.. _`ul(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ul.1.html -.. _`ulckpwdf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ulckpwdf.3.html -.. _`ulimit(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ulimit.1posix.html -.. _`ulimit(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ulimit.3.html -.. _`ulimit(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ulimit.3posix.html -.. _`ulimit.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/ulimit.h.7posix.html -.. _`umask(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/umask.1posix.html -.. _`umask(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/umask.2.html -.. _`umask(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/umask.3posix.html -.. _`umount2(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/umount2.2.html -.. _`umount(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/umount.2.html -.. _`umount(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/umount.8.html -.. _`unalias(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/unalias.1posix.html -.. _`uname(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/uname.1.html -.. _`uname(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/uname.1posix.html -.. _`uname(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/uname.2.html -.. _`uname(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/uname.3posix.html -.. _`uncompress(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/uncompress.1.html -.. _`uncompress(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/uncompress.1posix.html -.. _`unctrl(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/unctrl.3ncurses.html -.. _`undocumented(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/undocumented.3.html -.. _`undocumented(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/undocumented.7.html -.. _`unexpand(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/unexpand.1.html -.. _`unexpand(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/unexpand.1posix.html -.. _`unget(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/unget.1posix.html -.. _`ungetc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ungetc.3.html -.. _`ungetc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ungetc.3posix.html -.. _`ungetch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ungetch.3ncurses.html -.. _`ungetmouse(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ungetmouse.3ncurses.html -.. _`ungetwc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ungetwc.3.html -.. _`ungetwc(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ungetwc.3posix.html -.. _`unget_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/unget_wch.3ncurses.html -.. _`un.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/un.h.7posix.html -.. _`unicode(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/unicode.7.html -.. _`unimplemented(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/unimplemented.2.html -.. _`uniq(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/uniq.1.html -.. _`uniq(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/uniq.1posix.html -.. _`unistd.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/unistd.h.7posix.html -.. _`units(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/units.7.html -.. _`unix(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/unix.7.html -.. _`unix_chkpwd(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/unix_chkpwd.8.html -.. _`unix_update(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/unix_update.8.html -.. _`unlink(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/unlink.1.html -.. _`unlink(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/unlink.1posix.html -.. _`unlink(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/unlink.2.html -.. _`unlink(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/unlink.3posix.html -.. _`unlinkat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/unlinkat.2.html -.. _`unlocked_stdio(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/unlocked_stdio.3.html -.. _`unlockpt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/unlockpt.3.html -.. _`unlockpt(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/unlockpt.3posix.html -.. _`unlzma(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/unlzma.1.html -.. _`unpost_form(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/unpost_form.3form.html -.. _`unpost_menu(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/unpost_menu.3menu.html -.. _`unset(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/unset.1posix.html -.. _`unsetenv(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/unsetenv.3.html -.. _`unsetenv(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/unsetenv.3posix.html -.. _`unshare(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/unshare.1.html -.. _`unshare(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/unshare.2.html -.. _`untouchwin(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/untouchwin.3ncurses.html -.. _`unxz(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/unxz.1.html -.. _`update-alternatives(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/update-alternatives.8.html -.. _`update-ca-certificates(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/update-ca-certificates.8.html -.. _`update-catalog(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/update-catalog.8.html -.. _`updatedb(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/updatedb.1.html -.. _`updatedb.findutils(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/updatedb.findutils.1.html -.. _`update-exim4.conf(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/update-exim4.conf.8.html -.. _`update-exim4.conf.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/update-exim4.conf.conf.5.html -.. _`update-exim4.conf.template(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/update-exim4.conf.template.8.html -.. _`update-exim4defaults(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/update-exim4defaults.8.html -.. _`update-info-dir(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/update-info-dir.8.html -.. _`update-initramfs(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/update-initramfs.8.html -.. _`update-initramfs.conf(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/update-initramfs.conf.5.html -.. _`update-locale(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/update-locale.8.html -.. _`update-mime(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/update-mime.8.html -.. _`update_panels(3curses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/update_panels.3curses.html -.. _`update-passwd(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/update-passwd.8.html -.. _`update-python-modules(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/update-python-modules.8.html -.. _`update-rc.d(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/update-rc.d.8.html -.. _`update-rc.d-insserv(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/update-rc.d-insserv.8.html -.. _`update-xmlcatalog(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/update-xmlcatalog.8.html -.. _`updwtmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/updwtmp.3.html -.. _`updwtmpx(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/updwtmpx.3.html -.. _`uptime(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/uptime.1.html -.. _`urandom(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/urandom.4.html -.. _`uri(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/uri.7.html -.. _`url(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/url.7.html -.. _`urn(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/urn.7.html -.. _`use_default_colors(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/use_default_colors.3ncurses.html -.. _`use_env(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/use_env.3ncurses.html -.. _`use_extended_names(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/use_extended_names.3ncurses.html -.. _`use_legacy_coding(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/use_legacy_coding.3ncurses.html -.. _`uselib(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/uselib.2.html -.. _`useradd(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/useradd.8.html -.. _`userdel(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/userdel.8.html -.. _`usermod(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/usermod.8.html -.. _`userptr(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/userptr.3form.html -.. _`userptr(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/userptr.3menu.html -.. _`users(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/users.1.html -.. _`use_screen(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/use_screen.3ncurses.html -.. _`use_window(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/use_window.3ncurses.html -.. _`usleep(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/usleep.3.html -.. _`usleep(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/usleep.3posix.html -.. _`ustat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/ustat.2.html -.. _`utf-8(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/utf-8.7.html -.. _`utf8(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/utf8.7.html -.. _`util(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/util.3ncurses.html -.. _`utime(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/utime.2.html -.. _`utime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/utime.3posix.html -.. _`utime.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/utime.h.7posix.html -.. _`utimensat(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/utimensat.2.html -.. _`utimes(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/utimes.2.html -.. _`utimes(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/utimes.3posix.html -.. _`utmp(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/utmp.5.html -.. _`utmpname(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/utmpname.3.html -.. _`utmpx(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/utmpx.5.html -.. _`utmpx.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/utmpx.h.7posix.html -.. _`utmpxname(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/utmpxname.3.html -.. _`utsname.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/utsname.h.7posix.html -.. _`uucp(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/uucp.1posix.html -.. _`uudecode(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/uudecode.1posix.html -.. _`uuencode(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/uuencode.1posix.html -.. _`uuid(3pm)` : http://sites.uclouvain.be/SystInfo/manpages/man3/uuid.3pm.html -.. _`uustat(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/uustat.1posix.html -.. _`uux(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/uux.1posix.html -.. _`va_arg(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/va_arg.3.html -.. _`va_arg(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/va_arg.3posix.html -.. _`va_copy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/va_copy.3.html -.. _`va_copy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/va_copy.3posix.html -.. _`va_end(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/va_end.3.html -.. _`va_end(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/va_end.3posix.html -.. _`val(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/val.1posix.html -.. _`valgrind(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/valgrind.1.html -.. _`valgrind.bin(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/valgrind.bin.1.html -.. _`validlocale(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/validlocale.8.html -.. _`valloc(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/valloc.3.html -.. _`vasprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vasprintf.3.html -.. _`va_start(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/va_start.3.html -.. _`va_start(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/va_start.3posix.html -.. _`vcs(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/vcs.4.html -.. _`vcsa(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/vcsa.4.html -.. _`vdir(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/vdir.1.html -.. _`vdprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vdprintf.3.html -.. _`verify(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/verify.1ssl.html -.. _`verr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/verr.3.html -.. _`verrx(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/verrx.3.html -.. _`version(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/version.1ssl.html -.. _`versionsort(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/versionsort.3.html -.. _`vfork(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/vfork.2.html -.. _`vfork(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vfork.3posix.html -.. _`vfprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vfprintf.3.html -.. _`vfprintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vfprintf.3posix.html -.. _`vfscanf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vfscanf.3.html -.. _`vfscanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vfscanf.3posix.html -.. _`vfwprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vfwprintf.3.html -.. _`vfwprintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vfwprintf.3posix.html -.. _`vfwscanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vfwscanf.3posix.html -.. _`vhangup(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/vhangup.2.html -.. _`vi(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/vi.1.html -.. _`vi(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/vi.1posix.html -.. _`vid_attr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vid_attr.3ncurses.html -.. _`vidattr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vidattr.3ncurses.html -.. _`vidmode(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/vidmode.8.html -.. _`vid_puts(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vid_puts.3ncurses.html -.. _`vidputs(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vidputs.3ncurses.html -.. _`view(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/view.1.html -.. _`vigr(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/vigr.8.html -.. _`vim(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/vim.1.html -.. _`vimdiff(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/vimdiff.1.html -.. _`vimtutor(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/vimtutor.1.html -.. _`vipw(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/vipw.8.html -.. _`visudo(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/visudo.8.html -.. _`vline(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vline.3ncurses.html -.. _`vline_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vline_set.3ncurses.html -.. _`vm86(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/vm86.2.html -.. _`vm86old(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/vm86old.2.html -.. _`vmsplice(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/vmsplice.2.html -.. _`vmstat(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/vmstat.8.html -.. _`vpddecode(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/vpddecode.8.html -.. _`vprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vprintf.3.html -.. _`vprintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vprintf.3posix.html -.. _`vscanf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vscanf.3.html -.. _`vscanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vscanf.3posix.html -.. _`vserver(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/vserver.2.html -.. _`vsnprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vsnprintf.3.html -.. _`vsnprintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vsnprintf.3posix.html -.. _`vsprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vsprintf.3.html -.. _`vsprintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vsprintf.3posix.html -.. _`vsscanf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vsscanf.3.html -.. _`vsscanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vsscanf.3posix.html -.. _`vswprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vswprintf.3.html -.. _`vswprintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vswprintf.3posix.html -.. _`vswscanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vswscanf.3posix.html -.. _`vsyslog(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vsyslog.3.html -.. _`vwarn(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vwarn.3.html -.. _`vwarnx(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vwarnx.3.html -.. _`vwprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vwprintf.3.html -.. _`vwprintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vwprintf.3posix.html -.. _`vw_printw(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vw_printw.3ncurses.html -.. _`vwprintw(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vwprintw.3ncurses.html -.. _`vwscanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vwscanf.3posix.html -.. _`vw_scanw(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vw_scanw.3ncurses.html -.. _`vwscanw(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/vwscanw.3ncurses.html -.. _`w(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/w.1.html -.. _`waddch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/waddch.3ncurses.html -.. _`waddchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/waddchnstr.3ncurses.html -.. _`waddchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/waddchstr.3ncurses.html -.. _`waddnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/waddnstr.3ncurses.html -.. _`waddnwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/waddnwstr.3ncurses.html -.. _`waddstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/waddstr.3ncurses.html -.. _`wadd_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wadd_wch.3ncurses.html -.. _`wadd_wchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wadd_wchnstr.3ncurses.html -.. _`wadd_wchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wadd_wchstr.3ncurses.html -.. _`waddwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/waddwstr.3ncurses.html -.. _`wait(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/wait.1posix.html -.. _`wait(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/wait.2.html -.. _`wait3(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/wait3.2.html -.. _`wait(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wait.3posix.html -.. _`wait4(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/wait4.2.html -.. _`wait.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/wait.h.7posix.html -.. _`waitid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/waitid.2.html -.. _`waitid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/waitid.3posix.html -.. _`waitpid(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/waitpid.2.html -.. _`waitpid(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/waitpid.3posix.html -.. _`wall(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/wall.1.html -.. _`warn(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/warn.3.html -.. _`warnx(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/warnx.3.html -.. _`watch(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/watch.1.html -.. _`wattr_get(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wattr_get.3ncurses.html -.. _`wattr_off(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wattr_off.3ncurses.html -.. _`wattroff(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wattroff.3ncurses.html -.. _`wattr_on(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wattr_on.3ncurses.html -.. _`wattron(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wattron.3ncurses.html -.. _`wattr_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wattr_set.3ncurses.html -.. _`wattrset(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wattrset.3ncurses.html -.. _`wavelan(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/wavelan.4.html -.. _`wbkgd(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wbkgd.3ncurses.html -.. _`wbkgdset(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wbkgdset.3ncurses.html -.. _`wbkgrnd(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wbkgrnd.3ncurses.html -.. _`wbkgrndset(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wbkgrndset.3ncurses.html -.. _`wborder(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wborder.3ncurses.html -.. _`wborder_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wborder_set.3ncurses.html -.. _`wc(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/wc.1.html -.. _`wc(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/wc.1posix.html -.. _`wchar.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/wchar.h.7posix.html -.. _`wchgat(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wchgat.3ncurses.html -.. _`wclear(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wclear.3ncurses.html -.. _`wclrtobot(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wclrtobot.3ncurses.html -.. _`wclrtoeol(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wclrtoeol.3ncurses.html -.. _`wcolor_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcolor_set.3ncurses.html -.. _`wcpcpy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcpcpy.3.html -.. _`wcpncpy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcpncpy.3.html -.. _`wcrtomb(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcrtomb.3.html -.. _`wcrtomb(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcrtomb.3posix.html -.. _`wcscasecmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcscasecmp.3.html -.. _`wcscat(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcscat.3.html -.. _`wcscat(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcscat.3posix.html -.. _`wcschr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcschr.3.html -.. _`wcschr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcschr.3posix.html -.. _`wcscmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcscmp.3.html -.. _`wcscmp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcscmp.3posix.html -.. _`wcscoll(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcscoll.3posix.html -.. _`wcscpy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcscpy.3.html -.. _`wcscpy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcscpy.3posix.html -.. _`wcscspn(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcscspn.3.html -.. _`wcscspn(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcscspn.3posix.html -.. _`wcsdup(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsdup.3.html -.. _`wcsftime(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsftime.3posix.html -.. _`wcslen(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcslen.3.html -.. _`wcslen(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcslen.3posix.html -.. _`wcsncasecmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsncasecmp.3.html -.. _`wcsncat(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsncat.3.html -.. _`wcsncat(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsncat.3posix.html -.. _`wcsncmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsncmp.3.html -.. _`wcsncmp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsncmp.3posix.html -.. _`wcsncpy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsncpy.3.html -.. _`wcsncpy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsncpy.3posix.html -.. _`wcsnlen(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsnlen.3.html -.. _`wcsnrtombs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsnrtombs.3.html -.. _`wcspbrk(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcspbrk.3.html -.. _`wcspbrk(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcspbrk.3posix.html -.. _`wcsrchr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsrchr.3.html -.. _`wcsrchr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsrchr.3posix.html -.. _`wcsrtombs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsrtombs.3.html -.. _`wcsrtombs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsrtombs.3posix.html -.. _`wcsspn(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsspn.3.html -.. _`wcsspn(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsspn.3posix.html -.. _`wcsstr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsstr.3.html -.. _`wcsstr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsstr.3posix.html -.. _`wcstod(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcstod.3posix.html -.. _`wcstof(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcstof.3posix.html -.. _`wcstoimax(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcstoimax.3.html -.. _`wcstoimax(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcstoimax.3posix.html -.. _`wcstok(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcstok.3.html -.. _`wcstok(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcstok.3posix.html -.. _`wcstol(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcstol.3posix.html -.. _`wcstold(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcstold.3posix.html -.. _`wcstoll(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcstoll.3posix.html -.. _`wcstombs(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcstombs.3.html -.. _`wcstombs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcstombs.3posix.html -.. _`wcstoul(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcstoul.3posix.html -.. _`wcstoull(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcstoull.3posix.html -.. _`wcstoumax(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcstoumax.3.html -.. _`wcstoumax(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcstoumax.3posix.html -.. _`wcswcs(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcswcs.3posix.html -.. _`wcswidth(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcswidth.3.html -.. _`wcswidth(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcswidth.3posix.html -.. _`wcsxfrm(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcsxfrm.3posix.html -.. _`wctob(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wctob.3.html -.. _`wctob(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wctob.3posix.html -.. _`wctomb(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wctomb.3.html -.. _`wctomb(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wctomb.3posix.html -.. _`wctrans(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wctrans.3.html -.. _`wctrans(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wctrans.3posix.html -.. _`wctype(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wctype.3.html -.. _`wctype(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wctype.3posix.html -.. _`wctype.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/wctype.h.7posix.html -.. _`wcursyncup(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcursyncup.3ncurses.html -.. _`wcwidth(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcwidth.3.html -.. _`wcwidth(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wcwidth.3posix.html -.. _`wdelch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wdelch.3ncurses.html -.. _`wdeleteln(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wdeleteln.3ncurses.html -.. _`wechochar(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wechochar.3ncurses.html -.. _`wecho_wchar(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wecho_wchar.3ncurses.html -.. _`wenclose(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wenclose.3ncurses.html -.. _`werase(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/werase.3ncurses.html -.. _`wget(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/wget.1.html -.. _`wgetbkgrnd(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wgetbkgrnd.3ncurses.html -.. _`wgetch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wgetch.3ncurses.html -.. _`wgetnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wgetnstr.3ncurses.html -.. _`wgetn_wstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wgetn_wstr.3ncurses.html -.. _`wgetparent(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wgetparent.3ncurses.html -.. _`wgetscrreg(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wgetscrreg.3ncurses.html -.. _`wgetstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wgetstr.3ncurses.html -.. _`wget_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wget_wch.3ncurses.html -.. _`wget_wstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wget_wstr.3ncurses.html -.. _`what(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/what.1posix.html -.. _`whatis(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/whatis.1.html -.. _`whereis(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/whereis.1.html -.. _`which(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/which.1.html -.. _`whiptail(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/whiptail.1.html -.. _`whline(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/whline.3ncurses.html -.. _`whline_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/whline_set.3ncurses.html -.. _`who(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/who.1.html -.. _`who(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/who.1posix.html -.. _`whoami(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/whoami.1.html -.. _`win(3form)` : http://sites.uclouvain.be/SystInfo/manpages/man3/win.3form.html -.. _`win(3menu)` : http://sites.uclouvain.be/SystInfo/manpages/man3/win.3menu.html -.. _`winch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/winch.3ncurses.html -.. _`winchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/winchnstr.3ncurses.html -.. _`winchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/winchstr.3ncurses.html -.. _`windmc(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/windmc.1.html -.. _`window(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/window.3ncurses.html -.. _`winnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/winnstr.3ncurses.html -.. _`winnwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/winnwstr.3ncurses.html -.. _`winsch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/winsch.3ncurses.html -.. _`winsdelln(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/winsdelln.3ncurses.html -.. _`winsertln(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/winsertln.3ncurses.html -.. _`winsnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/winsnstr.3ncurses.html -.. _`wins_nwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wins_nwstr.3ncurses.html -.. _`winsstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/winsstr.3ncurses.html -.. _`winstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/winstr.3ncurses.html -.. _`wins_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wins_wch.3ncurses.html -.. _`wins_wstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wins_wstr.3ncurses.html -.. _`win_wch(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/win_wch.3ncurses.html -.. _`win_wchnstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/win_wchnstr.3ncurses.html -.. _`win_wchstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/win_wchstr.3ncurses.html -.. _`winwstr(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/winwstr.3ncurses.html -.. _`wipefs(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/wipefs.8.html -.. _`wmemchr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wmemchr.3.html -.. _`wmemchr(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wmemchr.3posix.html -.. _`wmemcmp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wmemcmp.3.html -.. _`wmemcmp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wmemcmp.3posix.html -.. _`wmemcpy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wmemcpy.3.html -.. _`wmemcpy(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wmemcpy.3posix.html -.. _`wmemmove(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wmemmove.3.html -.. _`wmemmove(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wmemmove.3posix.html -.. _`wmempcpy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wmempcpy.3.html -.. _`wmemset(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wmemset.3.html -.. _`wmemset(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wmemset.3posix.html -.. _`wmouse_trafo(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wmouse_trafo.3ncurses.html -.. _`wmove(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wmove.3ncurses.html -.. _`wnoutrefresh(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wnoutrefresh.3ncurses.html -.. _`wordexp(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wordexp.3.html -.. _`wordexp(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wordexp.3posix.html -.. _`wordexp.h(7posix)` : http://sites.uclouvain.be/SystInfo/manpages/man7/wordexp.h.7posix.html -.. _`wordfree(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wordfree.3.html -.. _`wordfree(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wordfree.3posix.html -.. _`wprintf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wprintf.3.html -.. _`wprintf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wprintf.3posix.html -.. _`wprintw(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wprintw.3ncurses.html -.. _`w.procps(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/w.procps.1.html -.. _`wredrawln(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wredrawln.3ncurses.html -.. _`wrefresh(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wrefresh.3ncurses.html -.. _`wresize(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wresize.3ncurses.html -.. _`write(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/write.1.html -.. _`write(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/write.1posix.html -.. _`write(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/write.2.html -.. _`write(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/write.3posix.html -.. _`writev(2)` : http://sites.uclouvain.be/SystInfo/manpages/man2/writev.2.html -.. _`writev(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/writev.3posix.html -.. _`wscanf(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wscanf.3posix.html -.. _`wscanw(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wscanw.3ncurses.html -.. _`wscrl(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wscrl.3ncurses.html -.. _`wsetscrreg(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wsetscrreg.3ncurses.html -.. _`wstandend(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wstandend.3ncurses.html -.. _`wstandout(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wstandout.3ncurses.html -.. _`wsyncdown(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wsyncdown.3ncurses.html -.. _`wsyncup(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wsyncup.3ncurses.html -.. _`wtimeout(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wtimeout.3ncurses.html -.. _`wtmp(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/wtmp.5.html -.. _`wtouchln(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wtouchln.3ncurses.html -.. _`wunctrl(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wunctrl.3ncurses.html -.. _`wvline(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wvline.3ncurses.html -.. _`wvline_set(3ncurses)` : http://sites.uclouvain.be/SystInfo/manpages/man3/wvline_set.3ncurses.html -.. _`x25(7)` : http://sites.uclouvain.be/SystInfo/manpages/man7/x25.7.html -.. _`x509(1ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man1/x509.1ssl.html -.. _`x509v3_config(5ssl)` : http://sites.uclouvain.be/SystInfo/manpages/man5/x509v3_config.5ssl.html -.. _`x86_64(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/x86_64.8.html -.. _`xargs(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/xargs.1.html -.. _`xargs(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/xargs.1posix.html -.. _`xauth(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/xauth.1.html -.. _`xcompose(5)` : http://sites.uclouvain.be/SystInfo/manpages/man5/xcompose.5.html -.. _`xcrypt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xcrypt.3.html -.. _`xdecrypt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdecrypt.3.html -.. _`xdr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr.3.html -.. _`xdr_accepted_reply(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_accepted_reply.3.html -.. _`xdr_array(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_array.3.html -.. _`xdr_authunix_parms(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_authunix_parms.3.html -.. _`xdr_bool(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_bool.3.html -.. _`xdr_bytes(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_bytes.3.html -.. _`xdr_callhdr(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_callhdr.3.html -.. _`xdr_callmsg(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_callmsg.3.html -.. _`xdr_char(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_char.3.html -.. _`xdr_destroy(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_destroy.3.html -.. _`xdr_double(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_double.3.html -.. _`xdr_enum(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_enum.3.html -.. _`xdr_float(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_float.3.html -.. _`xdr_free(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_free.3.html -.. _`xdr_getpos(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_getpos.3.html -.. _`xdr_inline(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_inline.3.html -.. _`xdr_int(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_int.3.html -.. _`xdr_long(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_long.3.html -.. _`xdrmem_create(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdrmem_create.3.html -.. _`xdr_opaque(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_opaque.3.html -.. _`xdr_opaque_auth(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_opaque_auth.3.html -.. _`xdr_pmap(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_pmap.3.html -.. _`xdr_pmaplist(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_pmaplist.3.html -.. _`xdr_pointer(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_pointer.3.html -.. _`xdrrec_create(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdrrec_create.3.html -.. _`xdrrec_endofrecord(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdrrec_endofrecord.3.html -.. _`xdrrec_eof(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdrrec_eof.3.html -.. _`xdrrec_skiprecord(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdrrec_skiprecord.3.html -.. _`xdr_reference(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_reference.3.html -.. _`xdr_rejected_reply(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_rejected_reply.3.html -.. _`xdr_replymsg(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_replymsg.3.html -.. _`xdr_setpos(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_setpos.3.html -.. _`xdr_short(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_short.3.html -.. _`xdrstdio_create(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdrstdio_create.3.html -.. _`xdr_string(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_string.3.html -.. _`xdr_u_char(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_u_char.3.html -.. _`xdr_u_int(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_u_int.3.html -.. _`xdr_u_long(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_u_long.3.html -.. _`xdr_union(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_union.3.html -.. _`xdr_u_short(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_u_short.3.html -.. _`xdr_vector(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_vector.3.html -.. _`xdr_void(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_void.3.html -.. _`xdr_wrapstring(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xdr_wrapstring.3.html -.. _`xencrypt(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xencrypt.3.html -.. _`xprt_register(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xprt_register.3.html -.. _`xprt_unregister(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/xprt_unregister.3.html -.. _`xsubpp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/xsubpp.1.html -.. _`xxd(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/xxd.1.html -.. _`xz(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/xz.1.html -.. _`xzcat(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/xzcat.1.html -.. _`xzcmp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/xzcmp.1.html -.. _`xzdiff(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/xzdiff.1.html -.. _`xzegrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/xzegrep.1.html -.. _`xzfgrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/xzfgrep.1.html -.. _`xzgrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/xzgrep.1.html -.. _`xzless(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/xzless.1.html -.. _`xzmore(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/xzmore.1.html -.. _`y0(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/y0.3.html -.. _`y0(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/y0.3posix.html -.. _`y0f(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/y0f.3.html -.. _`y0l(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/y0l.3.html -.. _`y1(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/y1.3.html -.. _`y1(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/y1.3posix.html -.. _`y1f(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/y1f.3.html -.. _`y1l(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/y1l.3.html -.. _`yacc(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/yacc.1.html -.. _`yacc(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/yacc.1posix.html -.. _`yes(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/yes.1.html -.. _`yn(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/yn.3.html -.. _`yn(3posix)` : http://sites.uclouvain.be/SystInfo/manpages/man3/yn.3posix.html -.. _`ynf(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ynf.3.html -.. _`ynl(3)` : http://sites.uclouvain.be/SystInfo/manpages/man3/ynl.3.html -.. _`ypdomainname(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/ypdomainname.1.html -.. _`zcat(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zcat.1.html -.. _`zcat(1posix)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zcat.1posix.html -.. _`zcmp(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zcmp.1.html -.. _`zdiff(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zdiff.1.html -.. _`zdump(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zdump.1.html -.. _`zegrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zegrep.1.html -.. _`zero(4)` : http://sites.uclouvain.be/SystInfo/manpages/man4/zero.4.html -.. _`zfgrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zfgrep.1.html -.. _`zforce(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zforce.1.html -.. _`zgrep(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zgrep.1.html -.. _`zic(8)` : http://sites.uclouvain.be/SystInfo/manpages/man8/zic.8.html -.. _`zless(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zless.1.html -.. _`zmore(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zmore.1.html -.. _`znew(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/znew.1.html -.. _`zsh(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zsh.1.html -.. _`zsh4(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zsh4.1.html -.. _`zshall(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshall.1.html -.. _`zshbuiltins(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshbuiltins.1.html -.. _`zshcalsys(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshcalsys.1.html -.. _`zshcompctl(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshcompctl.1.html -.. _`zshcompsys(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshcompsys.1.html -.. _`zshcompwid(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshcompwid.1.html -.. _`zshcontrib(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshcontrib.1.html -.. _`zshexpn(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshexpn.1.html -.. _`zshmisc(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshmisc.1.html -.. _`zshmodules(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshmodules.1.html -.. _`zshoptions(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshoptions.1.html -.. _`zshparam(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshparam.1.html -.. _`zshroadmap(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshroadmap.1.html -.. _`zshtcpsys(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshtcpsys.1.html -.. _`zshzftpsys(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshzftpsys.1.html -.. _`zshzle(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zshzle.1.html -.. _`zsoelim(1)` : http://sites.uclouvain.be/SystInfo/manpages/man1/zsoelim.1.html diff --git a/Theorie/src/args.out b/Theorie/src/args.out deleted file mode 100644 index a6518fd1b51fad21b9536524e2e82871ed25567e..0000000000000000000000000000000000000000 --- a/Theorie/src/args.out +++ /dev/null @@ -1,3 +0,0 @@ -Vous avez passe 2 arguments -Le premier argument est : SINF -Liste des arguments : SINF 1252 diff --git a/Theorie/src/args.sh b/Theorie/src/args.sh deleted file mode 100644 index 567eff0f37b89bd682f308503a9ee92bd5859bb5..0000000000000000000000000000000000000000 --- a/Theorie/src/args.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -# $# nombre d'arguments -# $1 $2 $3 ... arguments -echo "Vous avez passe" $# "arguments" -echo "Le premier argument est :" $1 -echo "Liste des arguments :" $@ diff --git a/Theorie/src/args.sh.out b/Theorie/src/args.sh.out deleted file mode 100644 index a6518fd1b51fad21b9536524e2e82871ed25567e..0000000000000000000000000000000000000000 --- a/Theorie/src/args.sh.out +++ /dev/null @@ -1,3 +0,0 @@ -Vous avez passe 2 arguments -Le premier argument est : SINF -Liste des arguments : SINF 1252 diff --git a/Theorie/src/cmdline.c b/Theorie/src/cmdline.c deleted file mode 100644 index 7cbb9da14e0bf329cbae8ea36ab2d691d659e19e..0000000000000000000000000000000000000000 --- a/Theorie/src/cmdline.c +++ /dev/null @@ -1,19 +0,0 @@ -/************************************** - * cmdline.c - * - * Programme affichant ses arguments - * sur la sortie standard - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main( int argc, char *argv[] ) { - int i; - printf("Ce programme a %d argument(s)\n",argc); - for( i=0; i < argc; i++ ) { - printf("argument[%d] : %s\n",i, argv[i] ); - } - return(EXIT_SUCCESS); -} diff --git a/Theorie/src/cmdline.out b/Theorie/src/cmdline.out deleted file mode 100644 index 90ce18288d15f0de91ab646132fd7b5b5da9c186..0000000000000000000000000000000000000000 --- a/Theorie/src/cmdline.out +++ /dev/null @@ -1,6 +0,0 @@ -Ce programme a 5 argument(s) -argument[0] : ./cmdline -argument[1] : 1 -argument[2] : -list -argument[3] : abcdef -argument[4] : sinf1252 diff --git a/Theorie/src/eq.sh b/Theorie/src/eq.sh deleted file mode 100644 index 84e5053119802631463d456931215e9d2ef116cd..0000000000000000000000000000000000000000 --- a/Theorie/src/eq.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -# Vérifie si les deux nombres passés en arguments sont égaux -if [ $# -ne 2 ]; then - echo "Erreur, deux arguments sont nécessaires" > /dev/stderr - exit 2 -fi -if [ $1 -eq $2 ]; then - echo "Nombres égaux" -else - echo "Nombres différents" -fi -exit 0 diff --git a/Theorie/src/exemple.out b/Theorie/src/exemple.out deleted file mode 100644 index f9341a29754ae30325984caa166c04bfb53b188d..0000000000000000000000000000000000000000 --- a/Theorie/src/exemple.out +++ /dev/null @@ -1,10 +0,0 @@ -$ cat exemple.txt -Un simple fichier de textes -aaaaaaaaaa bbbbbb -bbbbb ccccccccccc -eeeee fffffffff -aaaaaaaaaa bbbbbb -$ grep fichier exemple.txt -Un simple fichier de textes -$ wc exemple.txt - 5 13 98 exemple.txt diff --git a/Theorie/src/exemple2.out b/Theorie/src/exemple2.out deleted file mode 100644 index 33eb83c432f9c505db3048cfd2c9a5ec3f38645c..0000000000000000000000000000000000000000 --- a/Theorie/src/exemple2.out +++ /dev/null @@ -1,6 +0,0 @@ -$ echo "Un petit fichier de textes" > file.txt -$ echo "aaaaa bbbbb" >> file.txt -$ echo "bbbb ccc" >> file.txt -$ grep -v bbbb < file.txt > file.out -$ cat file.out -Un petit fichier de textes diff --git a/Theorie/src/exemple3.out b/Theorie/src/exemple3.out deleted file mode 100644 index f4b0395ae1a6477cc617639a185ed5259e9eeeaf..0000000000000000000000000000000000000000 --- a/Theorie/src/exemple3.out +++ /dev/null @@ -1,12 +0,0 @@ -$ echo "Un petit texte" | wc -c - 15 -$ echo "bbbb ccc" >> file.txt -$ echo "aaaaa bbbbb" >> file.txt -$ echo "bbbb ccc" >> file.txt -$ cat file.txt -bbbb ccc -aaaaa bbbbb -bbbb ccc -$ cat file.txt | sort | uniq -aaaaa bbbbb -bbbb ccc diff --git a/Theorie/src/failure.c b/Theorie/src/failure.c deleted file mode 100644 index 4f271da7c702b1ac21ad6d10233fdc3a2e7c5856..0000000000000000000000000000000000000000 --- a/Theorie/src/failure.c +++ /dev/null @@ -1,10 +0,0 @@ -/************************************** - * failure.c - * - * Programme minimal qui échoue toujours - * - **************************************/ -#include <stdlib.h> -int main( int argc, char *argv[] ) { - return(EXIT_FAILURE); -} diff --git a/Theorie/src/filterdigit.c b/Theorie/src/filterdigit.c deleted file mode 100644 index b699830085356e156ad54c5763814c912a11943b..0000000000000000000000000000000000000000 --- a/Theorie/src/filterdigit.c +++ /dev/null @@ -1,36 +0,0 @@ -/************************************** - * filterdigit.c - * - * Programme qui extrait de l'entrée - * standard les caractères représentant - * des chiffres - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -// retourne vrai si c est un chiffre, faux sinon -int digit(char c) { - return ( (c >='0')&&(c<='9') ); -} -// affiche un message d'erreur -void usage() -{ - fprintf(stderr,"Ce programme ne prend pas d'argument\n"); - exit(EXIT_FAILURE); -} -int main( int argc, char *argv[] ) { - char c; - - if (argc>1) { - usage(); - } - - while ((c = getchar()) != EOF) { - if(digit(c)) { - putchar(c); - } - } - return(EXIT_SUCCESS); -} - diff --git a/Theorie/src/hello.c b/Theorie/src/hello.c deleted file mode 100644 index 85d3653ab5ff6fd8c164e0a052b8262d1db5a9e3..0000000000000000000000000000000000000000 --- a/Theorie/src/hello.c +++ /dev/null @@ -1,17 +0,0 @@ -/************************************** - * Hello.c - * - * Programme affichant sur la sortie - * standard le message "Hello, world!" - * - **************************************/ - -#include <stdio.h> -#include <stdlib.h> - -int main(int argc, char *argv[]) { - // affiche sur la sortie standard - printf("Hello, world!\n"); - - return(EXIT_SUCCESS); -} diff --git a/Theorie/src/hello.sh b/Theorie/src/hello.sh deleted file mode 100644 index 6312616983212acbba595c19b450f07e1df925c9..0000000000000000000000000000000000000000 --- a/Theorie/src/hello.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -echo "Hello, world" diff --git a/Theorie/src/hello.sh.out b/Theorie/src/hello.sh.out deleted file mode 100644 index a5c19667710254f835085b99726e523457150e03..0000000000000000000000000000000000000000 --- a/Theorie/src/hello.sh.out +++ /dev/null @@ -1 +0,0 @@ -Hello, world diff --git a/Theorie/src/hellovar.sh b/Theorie/src/hellovar.sh deleted file mode 100644 index d68fbf249667e1e4b3769c9cc24bdcb6fabc6771..0000000000000000000000000000000000000000 --- a/Theorie/src/hellovar.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -PROG="SINF" -COURS=1252 -echo $PROG$COURS diff --git a/Theorie/src/printf.c b/Theorie/src/printf.c deleted file mode 100644 index 42d2d8abe8182e558d47188c8386d2b4a63a3e2c..0000000000000000000000000000000000000000 --- a/Theorie/src/printf.c +++ /dev/null @@ -1,29 +0,0 @@ -/************************************** - * printf.c - * - * Exemples d'utilisation de printfProgramme qui a réussi - * - **************************************/ -#include <stdlib.h> -#include <stdio.h> -#include <math.h> -int main( int argc, char *argv[] ) { - ///AAA - char weekday[]="Monday"; - char month[]="April"; - int day=1; - int hour=12; - int min=42; - char str[]="SINF1252"; - int i; - // affichage de la date et l'heure - printf("%s, %s %d, %d:%d\n", weekday, month, day, hour, min); - // affichage de la valeur de PI - printf("PI = %f\n", 4 * atan(1.0)); - // affichage d'un caractère par ligne - for(i=0; str[i]!='\0';i++) { - printf("%c\n",str[i]); - } - ///BBB - return(EXIT_SUCCESS); -} diff --git a/Theorie/src/printf.out b/Theorie/src/printf.out deleted file mode 100644 index 52d6f66f96fec16dcee9f506fd22d0dfbc4dfa1f..0000000000000000000000000000000000000000 --- a/Theorie/src/printf.out +++ /dev/null @@ -1,10 +0,0 @@ -Monday, April 1, 12:42 -PI = 3.141593 -S -I -N -F -1 -2 -5 -2 diff --git a/Theorie/src/wordin.sh b/Theorie/src/wordin.sh deleted file mode 100644 index 413163e906b58bc08858f9f491a5c7698c8f3959..0000000000000000000000000000000000000000 --- a/Theorie/src/wordin.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash -# wordin.sh -# Vérifie si le mot passé en premier argument est présent -# dans le fichier passé comme second argument -if [ $# -ne 2 ]; then - echo "Erreur, deux arguments sont nécessaires" > /dev/stderr - exit 2 -fi -grep $1 $2 >/dev/null -# $? contient la valeur de retour de grep -if [ $? -eq 0 ]; then - echo "Présent" - exit 0 -else - echo "Absent" - exit 1 -fi diff --git a/empty.rst b/empty.rst deleted file mode 100644 index 83fd7527f8d701145e03fc451250910e72c1278e..0000000000000000000000000000000000000000 --- a/empty.rst +++ /dev/null @@ -1,4 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Copyright |copy| 2012 by `Olivier Bonaventure <http://inl.info.ucl.ac.be/obo>`_, Christoph Paasch et Grégory Detal -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - diff --git a/qcmMalloc.rst b/qcmMalloc.rst deleted file mode 100644 index 136d2270d9139c02d5b9b1c0925c748960892f35..0000000000000000000000000000000000000000 --- a/qcmMalloc.rst +++ /dev/null @@ -1,344 +0,0 @@ -.. -*- coding: utf-8 -*- -.. Ce fichier est distribué sous une licence `creative commons <http://creativecommons.org/licenses/by-sa/3.0/>`_ - - -.. sectionauthor:: Aurélie Massart <aurelie.massart@student.uclouvain.be> - -Questions à choix multiples -=========================== - -:task_id: sinf1252-revision - - -Question 1. Structure et allocation de mémoire avec `malloc(3)`_ ----------------------------------------------------------------- - -Dans le langage C, l'allocation de zone mémoire se fait souvent avec `malloc(3)`_ -Pour une structure chainée définie comme suit : - -.. code-block:: c - - - struct list { - int value; - struct list *next; - }; - - -.. question:: revision-allocmemoire - :nb_prop: 3 - :nb_pos: 1 - - Quel fragment de code ci-dessous alloue correctement la zone mémoire pour une telle structure avec `malloc(3)`_ ? - - .. positive:: - - .. code-block:: c - - struct list *l = (struct list *)malloc (sizeof(struct list)); - if(l == NULL) - error("malloc"); - - .. positive:: - - .. code-block:: c - - struct list *l; - l = (struct list *)malloc(sizeof(struct list)); - if(l == NULL) - error("malloc"); - - - .. negative:: - - .. code-block:: c - - struct list *l = malloc(sizeof(list)); - if(l == NULL) - error("malloc"); - - .. comment:: La variable ``list`` est non déclarée. Pour référencer la structure, il faut faire appel à ``struct list`` et non à ``list``. De plus, `malloc(3)`_ retourne un pointeur de type ``void *`` qui doit donc être casté en pointeur de type ``struct list *``. - - - .. negative:: - - .. code-block:: c - - struct list *l = (struct list) malloc (sizeof(struct list )); - if(l == NULL) - error("malloc"); - - .. comment:: La variable ``l`` est de type ``struct list *`` et pas de type ``struct list``. - - .. negative:: - - .. code-block:: c - - struct list *l = malloc (struct list); - if(l == NULL) - error("malloc"); - - .. comment:: `malloc(3)`_ prend en argument la taille de la zone mémoire à allouer, et doit donc prendre en argument une expression commençant par ``sizeof``. - - -Question 2. Allocation et libération de mémoire sur une structure chainée -------------------------------------------------------------------------- - -Pour une structure chainée définie comme suit : - -.. code-block:: c - - - struct list { - int value; - struct list *next; - }; - - -.. question:: allocLib - :nb_prop: 3 - :nb_pos: 1 - - Un seul parmi les fragments de code ci-dessous est correct. Lequel ? - - .. positive:: - - .. code-block:: c - - - int main (int argc, char *argv[]) { - - struct list *node1 = (struct list *) malloc (sizeof (struct list)); - // premier noeud de la liste - if (node1 == NULL) - return (EXIT_FAILURE); - - - struct list *node2 = (struct list *) malloc (sizeof (struct list)); - // deuxieme noeud de la liste - if (node2 == NULL) - return (EXIT_FAILURE); - - node2->value = 5; - node2->next = NULL; - node1->value = 2; - node1->next = node2; - // initialisation des noeuds de la liste - - - while (node1 != NULL) - { - struct list *n = node1; - node1 = node1->next; - free (n); - n = NULL; - } - // liberation de la memoire allouee - - return (EXIT_SUCCESS); - } - - - - .. positive:: - - .. code-block:: c - - - int main (int argc, char *argv[]) { - - struct list *node1 = (struct list *) malloc (sizeof (struct list)); - // premier noeud de la liste - if (node1 == NULL) - return (EXIT_FAILURE); - - - struct list *node2 = (struct list *) malloc (sizeof (struct list)); - // deuxieme noeud de la liste - if (node2 == NULL) - return (EXIT_FAILURE); - - node1->value = 2; - node2->value = 5; - node2->next = NULL; - node1->next = node2; - // initialisation des noeuds de la liste - - - while (node1 != NULL) - { - struct list *n = node1; - node1 = node1->next; - free (n); - n = NULL; - } - // liberation de la memoire allouee - - return (EXIT_SUCCESS); - } - - - - .. negative:: - - .. code-block:: c - - - int main (int argc, char *argv[]) { - - struct list *node1 = (struct list *) malloc (sizeof (struct list)); - // premier noeud de la liste - if (node1 == NULL) - return (EXIT_FAILURE); - - - struct list *node2 = (struct list *) malloc (sizeof (struct list)); - // deuxieme noeud de la liste - if (node2 == NULL) - return (EXIT_FAILURE); - - - node2->value = 5; - node2->next = NULL; - node1->value = 2; - node1->next = node2; - // initialisation des noeuds de la liste - - - free(node1); - // liberation de la memoire allouee - - return (EXIT_SUCCESS); - - } - - - - .. comment:: La mémoire n'est pas bien libérée. L'appel à `free(3)`_ ne va libérer que la mémoire associée au premier noeud de la liste. - - .. negative:: - - .. code-block:: c - - - - int main (int argc, char *argv[]) { - - struct list *node1 = (struct list *) malloc (sizeof (struct list)); - // premier noeud de la liste - if (node1 == NULL) - return (EXIT_FAILURE); - - - struct list *node2 = (struct list *) malloc (sizeof (struct list)); - // deuxieme noeud de la liste - if (node2 == NULL) - return (EXIT_FAILURE); - - node2->value = 5; - node2->next = NULL; - node1->value = 2; - node1->next = node2; - // initialisation des noeuds de la liste - - - while (node1->next != NULL) - { - struct list *n = node1; - node1 = node1->next; - free (n); - n = NULL; - } - // liberation de la memoire allouee - - return (EXIT_SUCCESS); - } - - - - .. comment:: la mémoire n'est pas bien libérée. La boucle while se termine quand ``node->next`` vaut NULL et donc, la mémoire allouée pour le dernier élément de la liste ne sera pas libérée. - - .. negative:: - - .. code-block:: c - - - int main (int argc, char *argv[]) { - - struct list *node1 = (struct list *) malloc (sizeof (struct list)); - // premier noeud de la liste - - struct list *node2 = (struct list *) malloc (sizeof (struct list)); - // deuxieme noeud de la liste - - node2->value = 5; - node2->next = NULL; - node1->value = 2; - node1->next = node2; - // initialisation des noeuds de la liste - - - while (node1 != NULL) - { - struct list *n = node1; - node1 = node1->next; - free (n); - n = NULL; - } - // liberation de la memoire allouee - - return (EXIT_SUCCESS); - } - - .. comment:: les valeurs de retour des pointeurs alloués avec `malloc(3)`_ n'ont pas été vérifiées. - - .. negative:: - - .. code-block:: c - - - int main (int argc, char *argv[]) { - - struct list *node1 = (struct list *) malloc (sizeof (struct list)); - // premier noeud de la liste - if (node1 == NULL) - return (EXIT_FAILURE); - - - struct list *node2 = (struct list *) malloc (sizeof (struct list)); - // deuxieme noeud de la liste - if (node2 == NULL) - return (EXIT_FAILURE); - - node2->value = 5; - node2->next = NULL; - node1->value = 2; - node1->next = node2; - // initialisation des noeuds de la liste - - - while (node1 != NULL) - { - struct list n = node1; - free (n); - n = NULL; - node1 = node1->next; - } - // liberation de la memoire allouee - - return (EXIT_SUCCESS); - } - - - - .. comment:: la variable ``n`` est de type ``struct list`` et ne peut donc pas être assignée à la valeur de la variable ``node1`` qui n'est pas du même type - - - - - -.. include:: ../../../links.rst -.. include:: ../../../man_links.rst -.. include:: ../../../incl_links.rst - -