Skip to content
Extraits de code Groupes Projets
Valider 0d41ae45 rédigé par Olivier Bonaventure's avatar Olivier Bonaventure
Parcourir les fichiers

Merge branch 'master' of github.com:obonaventure/SystemesInformatiques

parents 373ea062 cfb9a797
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
......@@ -183,7 +183,7 @@ Considérons le fragment de programme ci-dessous.
}
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 ?
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
......
......@@ -21,7 +21,7 @@ La matière couverte cette semaine porte sur le système de fichiers et sa manip
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 :
Les bits de permissions permettent de contrôler l'accès aux fichiers. Considérons le répertoire ci-dessous :
.. code-block:: console
......@@ -481,7 +481,7 @@ Après exécution de ces commandes, un seul des groupes d'affirmations suivant e
.. class:: negative
-
- les fichiers ``a`` et ``c`` ont des `inode` différents
- 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
......
.. 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
.. |fsf| replace:: Free Software Foundation (FSF - http://www.fsf.org)
.. |gnu| replace:: GNU is Not Unix (GNU - http://www.gnu.org)
......@@ -111,12 +111,12 @@ 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.
.. 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 ``calc``. 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``.
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
......@@ -130,7 +130,9 @@ Premier programme
.. 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é à 0 par défault, 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.
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 :
......@@ -154,7 +156,7 @@ Premier programme
Deuxième programme
^^^^^^^^^^^^^^^^^^
Le deuxième programme est appelé ``recursive``. 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.
Le deuxième programme est appelé :download:`src/recursive.s`. 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
......@@ -174,7 +176,7 @@ Deuxième programme
Troisième programme
^^^^^^^^^^^^^^^^^^^
Le troisième programme est ``tab``. 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.
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
......
......@@ -37,7 +37,7 @@ Ce programme peut être compilé avec `gcc(1)`_ pour produire un exécutable.
-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 auxquels 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.
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
......@@ -59,7 +59,7 @@ L'interpréteur de commande `bash(1)`_ permet lancer plusieurs processus en tâc
[1] 10975
$ Processus : 10975
[pid=10975] Sleep : 30 secondes
./getpid &
$ ./getpid &
[2] 10976
$ Processus : 10976
[pid=10976] Sleep : 30 secondes
......@@ -68,7 +68,7 @@ L'interpréteur de commande `bash(1)`_ permet lancer plusieurs processus en tâc
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=10975] Fin du processus
[pid=10976] Fin du processus
[1]- Done ./getpid
[2]+ Done ./getpid
......
......@@ -73,7 +73,7 @@ Il est possible de changer le répertoire courant du processus ou du shell en ut
- `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 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 `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 :
......@@ -233,7 +233,7 @@ Extraction de données
zorro,01,20
zorro,5,4
$ cat file.txt | sort -t; -k2n
$ cat file.txt | sort -t, -k2n
zorro,01,20
pcr,01,3
pcr,1,3
......@@ -660,7 +660,7 @@ Exemples :
$ 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 set remix en route
#yes s'est remis en route
$ jobs
#nous vérifions le statut de yes avec jobs
......@@ -682,7 +682,7 @@ Exemples :
$ jobs
#nous vérifions les jobs
[1]+ Terminated: 15 yes > \dev\null
#yes set marqué Terminated
#yes est marqué Terminated
$ jobs
#un deuxième appel à jobs nous affiche une liste vide
......@@ -705,7 +705,7 @@ Modification d'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 : I faut mieux encadrer la commande avec des ' ou des "
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 :
......@@ -900,7 +900,7 @@ Après il ne reste plus qu'à l'exécuter et observer le résultat.
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é, des Int ou des 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>`_
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
......@@ -942,7 +942,7 @@ Dans le but de tester ces boucles nous utiliserons un petit programme en C, `ret
#!/bin/bash
if ./return 0; then
#la valeur de renvoi sera 0 quand la boucle est exécutée
#la valeur de renvoi sera 0 quand la boucle aura été exécutée
echo "Hello"
fi
......
Fichier déplacé
Systèmes Informatiques
======================
Ce repository git est destiné à contenir les notes et exercices du cours de [Systèmes informatiques 1](http://www.uclouvain.be/cours-2014-LSINF1252) (C, Unix/Linux, ...) donné en deuxième année aux étudiants ingénieurs option informatique et aux étudiants en sciences informatiques de l'[UCL](http://www.uclouvain.be). Il sera mis régulièrement à jour et les étudiants sont encouragés à soumettre des bugs reports, envoyer des patches ( notamment pour la section relative aux outils) ou proposer de nouvelles questions à choix multiples.
[![Build Status](https://travis-ci.com/obonaventure/SystemesInformatiques.svg?branch=master)](https://travis-ci.com/obonaventure/SystemesInformatiques)
Ce repository git est destiné à contenir les notes et exercices du cours de [Systèmes informatiques 1](https://uclouvain.be/cours-2018-lsinf1252) (C, Unix/Linux, ...) donné en deuxième année aux étudiants ingénieurs option informatique et aux étudiants en sciences informatiques de l'[UCL](https://www.uclouvain.be). Il sera mis régulièrement à jour et les étudiants sont encouragés à soumettre des bugs reports, envoyer des patches ( notamment pour la section relative aux outils) ou proposer de nouvelles questions à choix multiples.
Ce cours est écrit en restructured text et est distribué sous une licence creative commons
http://creativecommons.org/licenses/by-sa/3.0/fr/
https://creativecommons.org/licenses/by-sa/3.0/fr/
Des versions HTML, pdf et epub sont disponibles via http://sites.uclouvain.be/SystInfo
Des versions HTML, pdf et epub sont disponibles via https://sites.uclouvain.be/SystInfo
Compilation
-----------
Les notes sont écrites en [restructured text](http://docutils.sourceforge.net/rst.html) et peuvent être transformées en un document au format HTML, epub ou PDF en utilisant le logiciel [sphinx](http://sphinx-doc.org). Pour faciliter cette compilation, une configuration [vagrant](https://www.vagrantup.com) est reprise dans le fichier [Vagrantfile](https://github.com/obonaventure/SystemesInformatiques/tree/master/Vagrantfile) se trouvant à la racine du projet. [Vagrant](https://www.vagrantup.com) est un logiciel fonctionnant sur Linux, Windows et MacOS qui permet d'automatiser et de faciliter la création de machines virtuelles supportées notamment par [Virtualbox](https://www.virtualbox.org).
Les notes sont écrites en [restructured text](http://docutils.sourceforge.net/rst.html) et peuvent être transformées en un document au format HTML, epub ou PDF en utilisant le logiciel [sphinx](https://sphinx-doc.org). Pour faciliter cette compilation, une configuration [vagrant](https://www.vagrantup.com) est reprise dans le fichier [Vagrantfile](https://github.com/obonaventure/SystemesInformatiques/tree/master/Vagrantfile) se trouvant à la racine du projet. [Vagrant](https://www.vagrantup.com) est un logiciel fonctionnant sur Linux, Windows et MacOS qui permet d'automatiser et de faciliter la création de machines virtuelles supportées notamment par [Virtualbox](https://www.virtualbox.org).
Pour démarrer votre environnement [Vagrant](https://www.vagrantup.com), commencez par installer [Vagrant](https://www.vagrantup.com) et [Virtualbox](https://www.virtualbox.org). [Vagrant](https://www.vagrantup.com) utilise le [Vagrantfile](https://github.com/obonaventure/SystemesInformatiques/tree/master/Vagrantfile) pour créer les machines virtuelles. Ce dernier marque le dossier racine du projet et décrit le type de machine ainsi que les dépendances logicielles nécessaires au projet.
......@@ -28,7 +31,7 @@ Finalement, lorsque que vous avez terminé de travailler sur le projet, vous pou
Comment créer de nouvelles questions à choix multiples
------------------------------------------------------
Une des améliorations récentes aux notes du cours reprises sur ce repository git est le support de questions à choix multiples. Ces questions à choix multiples sont écrites grâce à une petite extension à [http://www.sphinx-doc.org](sphinx) qui est intégrée au projet. Plusieurs dizaines de questions à choix multiples ont déjà étés écrites et les étudiants sont invités à proposer de nouvelles questions en s'appuyant sur les difficultés qu'ils ont rencontré en préparant les travaux pratiques du cours ou en révisant la théorie.
Une des améliorations récentes aux notes du cours reprises sur ce repository git est le support de questions à choix multiples. Ces questions à choix multiples sont écrites grâce à une petite extension à [https://www.sphinx-doc.org](sphinx) qui est intégrée au projet. Plusieurs dizaines de questions à choix multiples ont déjà étés écrites et les étudiants sont invités à proposer de nouvelles questions en s'appuyant sur les difficultés qu'ils ont rencontré en préparant les travaux pratiques du cours ou en révisant la théorie.
Une bonne question à choix multiples doit répondre à plusieurs critères :
......
......@@ -80,7 +80,7 @@ Un autre exemple d'utilisation de pointeurs vers des pointeurs est la fonction `
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 savoir quelle partie de la chaîne de caractères passée en argument était en erreur.
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.
......@@ -95,7 +95,7 @@ Lors de son exécution, ce programme affiche la sortie suivante.
: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 la 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.
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.
......@@ -246,6 +246,8 @@ A titre d'exemple, le programme ci-dessous utilise `strerror(3)`_ pour afficher
.. rubric:: Footnotes
.. [#frestrict] La qualificateur ``restrict`` est également parfois utilisé pour indiquer des contraintes sur les pointeurs passés en argument à une fonction [Walls2006]_.
......@@ -46,7 +46,7 @@ Avant d'analyser en détails le fonctionnement des appels systèmes `signal(2)`_
- ``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, le 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é.
......
......@@ -260,7 +260,7 @@ Une première solution à ce problème est d'utiliser un mutex et un sémaphore
sem_init(&db, NULL, 1).
La solution utilise une variable partagée : ``readcount``. L'accès à cette variable est protégé par ``mutex``. Le sémaphore ``db`` sert à réguler l'accès des `writers` à la base de données. Le mutex est initiliasé comme d'habitude par la fonction `pthread_mutex_init(3posix)`_. Le sémaphore ``db`` est initialisé à la valeur ``1``. Le `writer` est assez simple :
La solution utilise une variable partagée : ``readcount``. L'accès à cette variable est protégé par ``mutex``. Le sémaphore ``db`` sert à réguler l'accès des `writers` à la base de données. Le mutex est initialisé comme d'habitude par la fonction `pthread_mutex_init(3posix)`_. Le sémaphore ``db`` est initialisé à la valeur ``1``. Le `writer` est assez simple :
.. code-block:: c
......@@ -469,7 +469,7 @@ Dans un programme C séquentiel, on doit souvent combiner les variables globales
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 libraire 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.
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``.
......
......@@ -15,8 +15,8 @@ echo "**** Outils ****"
sphinx-build -nWNT --keep-going -b html . /tmp
cd ../Exercices
echo "**** Exercices ****"
sphinx-build -nWNT --keep-going -b html . /tmp
#sphinx-build -nWNT --keep-going -b html . /tmp
cd QCM
echo "**** QCM ****"
make
#make
cd ../..
\ No newline at end of file
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter