Systèmes d’Exploitation Avancés – TP 1

Le but de ce TP est de vous configurer votre environnement de travail et vous familiariser avec les outils indispensables pour la suite des TPs Système. On profitera également pour faire quelques rappels basiques de votre cours Système d’Exploitation d’IATIC3.

Ce document est sous licence CC by-nc-sa. La partie I est inspirée du cours Gerez vos codes source avec git de Mathieu Nebra.

Partie I: Git

Utilisation de Git

Pour tous les TPs de système on utilisera git. Un dépôt git contient un projet en cours. Chaque dépôt git peut-être cloné sur différents ordinateurs locaux ou distants.

Présentation de Git

Si vous avez déjà travaillé sur un projet informatique, que ce soit un petit projet personnel ou un plus gros projet professionnel, vous avez certainement déjà rencontré un de ces problèmes :

Si ces problèmes là vous parlent, vous auriez dû utiliser un logiciel de gestion de versions. Ce type de logiciel est devenu indispensable lorsqu’on travaille à plusieurs sur un même projet et donc sur le même code source. Même si vous travaillez seuls, vous aurez intérêt à commencer à en utiliser un rapidement car il vous offrira de nombreux avantages, comme la conservation d’un historique de chaque modification des fichiers par exemple.

Il existe de nombreux logiciels de gestion de versions, comme SVN (Subversion), Mercurial et Git. Dans ce cours on utilisera Git (prononcez « guite ») qui est un des plus puissants logiciels de ce genre.

Git est capable de suivre l’évolution d’un fichier texte ligne de code par ligne de code et garde toutes les versions et tous les changements de votre code. Mais Git n’est pas seulement un outil de backup (sauvegarde), il propose de nombreuses fonctionnalités supplémentaires, par exemple

Git est un logiciel de gestion de version “distribué”. Chacun des développeurs participant à un même projet possède son propre dépot git. Les développeurs peuvent s’échanger des versions et des modifications (commits) dans un modèle pair à pair. Souvent un dépot central est crée sur un serveur. Le dépôt central sert de point de rencontre et facilite les échanges entre développeurs. Le serveur connaît l’historique des modifications et permet l’échange d’informations entre les développeurs, qui eux possèdent également l’historique des modifications.

C’est dans ce dernier mode que nous allons fonctionner avec Git.

Création d’un compte sur tahiti.prism.uvsq.fr

Pour sauvegarder et rendre votre travail nous allons utiliser le serveur gitlab tahiti.prism.uvsq.fr.

  1. Normalement vous avez reçu un mail sur votre adresse @isty.uvsq.fr (ou @ens.uvsq.fr) vous invitant à créer un compte sur tahiti.prism.uvsq.fr. Attention il est impératif d’utiliser cette même adresse mail et pas une adresse personnelle lors de la création du compte.

  2. Lorsque vous vous connectez sur le site, vous pourrez voir vos projets. Un projet sea20/prenom-nom a déjà été crée pour vous.

  3. (optionnel) Si vous souhaitez pouvoir cloner et pusher sur votre dépôt sans taper votre password à chaque fois, rajoutez une clé ssh sur votre compte. Cliquez sur le menu déroulant en haut à droite, choisissez “Settings”, puis sur la barre à droite choisissez “SSH Keys”.

Environnement de développement

Pour les TPs et projets de SEA il vous faut un environnement de développement Linux avec git, gcc ou clang, gdb, les bintools. Le Mini Projet 2 nécessite également un environnement LaTeX.

Vous avez plusieurs possibilités:

Initialization du dépôt

  1. Pour pouvoir commencer à travailler sur votre dépôt git, il va falloir le cloner. Pour cela allez sur tahiti.prism.uvsq.fr et récupérez l’adresse du dépôt. D’abord choisissez le type d’adresse HTTP ou SSH sur le menu déroulant au centre de l’interface (ne choisissez SSH que si vous avez rajouté une clé SSH sur votre profil). Puis copiez l’adresse qui se trouve juste à côté.

  2. Allez maintenant sur un terminal et tapez les commande suivantes:

    # Attention: les commandes seront différentes pour vous selon votre nom et prénom :-)

    # clonez le dépôt
    $ git clone http://tahiti.prism.uvsq.fr/sea/pablo-oliveira.git 
    warning: You appear to have cloned an empty repository.
    Checking connectivity... done.

    # Allez à l'intérieur du dépôt cloné en local
    $ cd pablo-oliveira/

    # Créez maintenant un répertoire TP1 dans votre dépôt
    $ mkdir TP1
    $ cd TP1

Si vous souhaitez cloner ce dépôt sur d’autres machines; la procédure est la même. Les commandes git vous permettent de synchroniser les différentes instances de dépôt entre elles.

Dans la suite du TP, vous travaillerez sur le répertoire TP1 que vous venez de créer. À chaque question où l’on vous demande de créer un modifier des fichiers, vous committerez vos modifications.

Création d’un dépôt git et ajout de fichiers

Tout d’abord il faut configurer git avec vos informations personnelles (remplacez avec votre nom et mail)

$ git config --global user.name "Pablo Oliveira"
$ git config --global user.email "pablo.oliveira@uvsq.fr"

Maintenant écrivez un programme test.c pour afficher “Hello World!” sur la sortie standard et un fichier Makefile pour le compiler avec gcc.

La commande git status vous permet de voir ce qui est nouveau depuis la dernière sauvegarde (ou commit) dans le dépôt:

$ git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    Makefile
    test.c

Pour commiter les fichier il faut d’abord les ajouter dans git avec

$ git add Makefile test.c
$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   Makefile
    new file:   test.c

Maintenant git status nous indique que les deux fichiers sont prets à être committés.

La commande git commit ouvre un editeur qui vous permet de taper un message indiquant à quoi correspondent les fichier ajoutés ou modifiés.

Pour les messages de commit utilise la convention suivante,

Par exemple:

    TP1 (exo1): implement basic input/output for the shell

    An infinite loop reads a full input line from the user
    and echoes it back. On CTRL+D the program quits.

Voici une bonne référence sur la manière de rédiger vos messages de commit.

Enregistrer des modifications sous git

Maintenant vous pouvez modifier votre programme. Faites en sorte que le programme fasse une faute de segmentation. Comment faire ? Soyez créatifs.

Puis tapez git diff pour voir vos changements:

git diff
diff --git a/test.c b/test.c
index 69899ec..ad7f9c6 100644
--- a/test.c
+++ b/test.c
@@ -1,4 +1,5 @@
 #include <stdio.h>
 int main(void) {
-    printf("Hello World!\n");
+    do_segmentation_fault();
 }

Maintenant commitez vos changements avec git add test.c suivi de git commit.

Vous pouvez consulter le journal des modifications avec git log

$ git log
commit 66ea53ab301045fc5a990fac3672f842dc75b2e8
Author: Pablo Oliveira <pablo.oliveira@uvsq.fr>
Date:   Thu Sep 11 22:59:15 2014 +0200

    Harmless modification that makes the program segfault

commit b35c2b6551d4b3738170637634702ed4d82aa501
Author: Pablo Oliveira <pablo.oliveira@uvsq.fr>
Date:   Thu Sep 11 22:55:05 2014 +0200

    Initial commit: Hello World program

Chaque commit est suivi d’un code hexadecimal unique qui l’identifie. Vous pouvez visualiser les changements entre deux versions avec git diff b35c2b6 66ea53a, ce n’est pas la peine de taper tous les chiffres, les premiers suffisent (sauf en cas de conflit). Essayez !

Les différentes versions forment un “fil” ou branche de versions. Dans git la branche principale s’appelle d’habitude master.

Git permet de travailler sur plusieurs branches en même temps, mais cela dépasse le cadre de cette introduction.

Visiter une version précédente

Git sauvegarde toutes les versions et permets de revenir à une version précédente.

Par exemple pour revenir à la version de base vous pouvez taper:

 $ git checkout b35c2b6

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at b35c2b6... Initial commit: Hello World program

git nous previens que nous ne sommes plus en tête de la branche master ce qui est normal vu que nous sommes revenus à une vieille version.

Pour revenir à la dernière version vous pouvez taper:

$ git checkout master
Previous HEAD position was b35c2b6... Initial commit: Hello World program
Switched to branch 'master'

Annuler les changements non commités

Parfois vous avez fait des modifications sur un fichier et vous voulez les annuler et revenir à la dernière version commitée.

Pour cela vous pouvez utiliser git checkout comme sur l’exemple suivant

$ rm hello.c

# Ooops j'ai effacé hello.c

$ git checkout hello.c

# tout va bien !

Essayez.

Revenir à une ancienne version définitivement

Parfois on veut revenir à une ancienne version pour de bon. La commande suivante vous le permet:

$ git reset --hard b35c2b6

Essayez de revenir à la version sans segfault.

Partager votre code avec les autres

Pour partager votre code avec un autre dépot, git propose deux commandes:

Comme vous avez cloné votre dépôt depuis tahiti.prism.uvsq.fr; ce serveur est déja configuré comme serveur push par défaut.

Pour envoyer vos changements sur tahiti faites:

    $ git push origin master

    Counting objects: 3, done.
    Delta compression using up to 8 threads.
    Compressing objects: 100% (2/2), done.
    Writing objects: 100% (3/3), 271 bytes | 0 bytes/s, done.
    Total 3 (delta 0), reused 0 (delta 0)
    To http://pablo-oliveira@tahiti.prism.uvsq.fr/sea20/pablo-oliveira.git
    * [new branch]      master -> master

Partie II: Appels Système

Le but de cette partie est de manipuler les appels systèmes basiques: fork, wait, open, etc. Si vous voulez consulter la documentation d’une appel système, par exemple fork vous pouvez utiliser la commande man 2 fork. Cette partie est adapté à partir d’exercices proposés par Juliusz Chroboczek et Khouloud Zine Elabidine.

Utilisez git pour commiter les programmes que vous aurez à écrire. Faites au moins un commit par question.

Si vous avez besoin de gdb vous pouvez l’installer avec

  $ sudo apt-get update
  $ sudo apt-get install gdb
  1. Écrivez un programme qui crée deux processus, un père qui affiche à l’aide de l’appel système write la chaîne "Je suis le père\n", et un fils qui affiche la chaîne "Je suis le fils\n". (Vous n’omettrez pas d’attendre la mort du fils à l’aide de wait.) Quel est l’ordre des chaînes affichées ? Un autre résultat est-il possible ?

  2. Écrivez un programme qui crée deux processus, un père qui affiche à l’aide de l’appel système write la chaîne “a” 10 000 fois, et un fils qui affiche la chaîne “b” 10 000 fois. (Comme d’habitude, pensez à wait.) Que constatez-vous ?

  3. Combien de processus existent au maximun durant l’exécution du programme suivant ?

int main(int argc, char *argv[]) {
    fork();
    fork();
    fork();
    sleep(10);
    exit(0);
}

Dessinez l’arbre des processus crées. Vérifiez votre hypothèse à l’aide de la commande pstree.

Calcul Parallèle

  1. Écrivez un programme qui génère un tableau de 10 000 entiers tirés au hasard entre 0 et 1000 puis affiche tous les indices des cases de ce tableau dont la valeur est 42. (Vous pouvez utiliser la fonction random.)
  2. Modifiez votre programme pour qu’il utilise deux processus, le père qui parcourt la première moitié du tableau, et le fils qui parcourt la seconde.
  3. Même question avec un nombre de processus donné sur la ligne de commande.