Outils pour utilisateurs

Outils du site


exercices:debut

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
exercices:debut [10/10/2019 07:11] – [TP5] webmestreexercices:debut [30/09/2021 10:18] (Version actuelle) – [TP4] webmestre
Ligne 1: Ligne 1:
 +Voici les données initiales pour réaliser les TP M3101.
 +
 +====== TP1 ======
 +
 +Voici les codes fourni en TD1 :
 +  * {{:exercices:td1-pid.sh|}}
 +  * {{:exercices:td1-logique.sh|}}
 +  * {{:exercices:td1-zombie.sh|}}
 +  * {{:exercices:td1-pipe.sh|}}
 +  * {{:exercices:td1-exit.sh|}}
 +  * {{:exercices:td1-mutex.sh|}}
 +  * {{:exercices:td1-limit.sh|}}
 +  * {{:exercices:td1-rdv.sh|}}
 +  * {{:exercices:td1-turn.sh|}}
 +  * {{:exercices:td1-prod.sh|}}
 +  * {{:exercices:td1-rw.sh|}}
 +
 +Pour la question "Mise en place des sémaphores", utilisez les [[:codes:]] fournis dans le cours pour les programmes : mknamedsem.c, namedsemp.c, namedsemv.c et rmnamedsem.c.
 +
 +<WRAP center round tip 60%>
 +Les question "Application au carrousel" et "Application lecteur/écrivains" ne seront pas notés.
 +
 +Pour visualiser une trotteuse, utilisez l'option "-update 1" de xclock.
 +</WRAP>
 +
 +====== TP2 ======
 +
 +Utilisez les entêtes :
 +
 +<code python>
 +#!/usr/bin/python
 +# -*- coding: utf-8 -*-
 +
 +import sys
 +import struct
 +import time
 +import datetime
 +import locale
 +</code>
 +
 +Exemple de switch. La commande switch n'existe pas, mais on peut utiliser un tableau qui associe un mot à un identifiant de fonction.
 +<code python>
 +def f1 ():
 +  print "appel de f1"
 +
 +def f2 ():
 +  print "appel de f2"
 +
 +var="f1"
 +
 +monSwitch = {
 +    'f1': f1,
 +    'f2': f2
 +}
 +
 +monSwitch [var] ()
 +</code>
 +
 +On peut passer des arguments à un programme python.
 +<code python>
 +#!/usr/bin/python
 +# -*- coding: utf-8 -*-
 +import sys
 +
 +def f1 ():
 +  print "appel de f1"
 +
 +def f2 ():
 +  print "appel de f2"
 +
 +monSwitch = {
 +    'f1': f1,
 +    'f2': f2
 +}
 +
 +monSwitch [sys.argv[1]] ()
 +</code>
 +
 +L'appel en bash se fait de la façon suivante
 +<code bash>
 +$ chmod a+x monProgrammePython.py
 +$ ./monProgrammePython.py f1
 +</code>
 +
 +Pour l'affichage du mode nous devons découper l'entier et isoler des sous-ensembles de bits.
 +Par exemple on peut vouloir découper 0x41ED en 0X4 d'un côté et 0x1ED de l'autre.
 +
 +<code python>
 +fMode = 0x41ED // <=> mode = 040755 <=> mode = 16877
 +fType = mode >> 12 // => 4
 +ugo = fMode & 0xFFF // => 0x1ED (héxa) = 0755 (octal) = 493 (décimal)
 +</code>
 +
 +Les droits "ugo" devraient être découpé en "u" (utilisateur) "g" (groupe) et "o" (autres).
 +De façon optionnel nous pouvons traiter les bits "sst". Il n'y aura pas de tels fichiers dans le système fournit en exemple.
 +
 +<code python>
 +ugo = 00755
 +sst = ugo >> 9 & 7 // => 0
 +u = ugo >> 6 & 7 // => 7
 +g = ugo >> 3 & 7 // => 5
 +o = ugo >> 0 & 7 // <=> o = ugo & 7 => 5
 +</code>
 +
 +Voici quelques fonctions utiles
 +  * str (i) => traduit un entier en une chaîne de caractère représentant une valeur décimal
 +  * oct (i) => traduit un entier en une chaîne de caractère représentant une valeur octal
 +  * hex (i) => traduit un entier en une chaîne de caractère représentant une valeur héxadécimal
 +
 +<code python>
 +i = 0x41ED
 +s = "hex: "+hex (i)+" oct: "+oct (i)+" dec: "+str (i)
 +// => hex: 0x41ed oct: 040755 dec: 16877
 +</code>
 +<WRAP center round important 60%>
 +Il y a une erreur dans le support de cours page 49 (listing 35).
 +
 +<code bash>
 +$ ./testInode.py  propMode
 + 00775  =>  prwxrwxr-x
 + 07775  =>  prwsrwsr-t
 + 00664  =>  prw-rw-r--
 + 07664  =>  prwSrwSr-T
 + 0x41ed =>  drwxr-xr-x
 + 0x81b4 =>  -rw-rw-r--
 +</code>
 +</WRAP>
 +
 +
 +
 +Nous utiliserons les fonctions de lecture de fichiers
 +
 +<code python>
 + fs = open ("td2.MinixFS", "rb")
 + fs.seek (addr, 0)
 + bytes = fs.read (len)
 +</code>
 +
 +Où 
 +  * open est la fonction qui ouvre un fichier ("rb" veut dire en lecture et en binaire)
 +  * seek est la fonction qui positionne le pointeur de lecture dans le fichier une adresse particulière (addr)
 +  * read est la fonction qui lit un nombre d'octets indiqué et retourne un tableau
 +
 +
 +{{:exercices:td2.minixfs.zip|td2.minixfs.zip}}
 +
 +Pour voir le fichier en hexadécimal utilisez emacs et la commande : M-x hexl-mode //(Esc-x suivi de hexl-mode)// ou "od -x td2.MinixFS" ou "xxd td2.MinixFS"
 +
 +
 +Voici la structure inode en C
 +<code c>
 + struct minix_inode {
 +   __u16 i_mode;
 +   __u16 i_uid;
 +   __u32 i_size;
 +   __u32 i_time;
 +   __u8 i_gid;
 +   __u8 i_nlinks;
 +   __u16 i_zone [9];
 + };
 +</code>
 +
 +Voici comment on peut la lire en python
 +<code python>
 +import struct
 +inode_fmt = '<HHIIbb9H'
 +inode_len = struct.calcsize (inode_fmt)
 +inode_unpack = struct.Struct (inode_fmt).unpack_from
 +</code>
 +
 +Où 
 +  * inode_fmt est la définition correspondant à la structure C
 +    * < veut dire little endianess
 +    * H veut dire entier non signé sur 2 octets
 +    * I veut dire entier non signé sur 4 octets
 +    * b veut dire octet nonsigné
 +    * 9* veut dire 9 fois le type qui suit
 +
 +Voici un exemple d'utilisation
 +<code python>
 +fs = open ("td2.MinixFS", "rb"
 +fs.seek (i2addr (2), 0)
 +data = fs.read (inode_len)
 +inode = inode_unpack (data)
 +
 +print inodeEntry
 +  => (16893, 66, 160, 1407002500, 67, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0)
 +
 +print hex (inodeEntry[0])
 +  => 0x41fd
 +  
 +iMode = inodeEntry [0]
 +iUser = inodeEntry [1]
 +iSize = inodeEntry [2]
 +iTime = inodeEntry [3]
 +iGroup = inodeEntry [4]
 +iLinks = inodeEntry [5]
 +iZone = inodeEntry[6:]
 +
 +print "%s %d u:%d g:%d %5d %s" % \
 +      (propMode2str (iMode), iLink, iUser, iGroup, iSize, date2str (iDate))
 +</code>
 +
 +Voici la structure des entrée de répertoire C
 +<code C>
 + struct minix_dir_entry {
 +   __u16 inode ;
 +   char name [30];
 + };
 +</code>
 +
 +Voici comment on peut la lire en python
 +<code python>
 +import struct
 +dirEntry_fmt = '<H30s'
 +dirEntry_len = struct.calcsize (dirEntry_fmt)
 +dirEntry_unpack = struct.Struct (dirEntry_fmt).unpack_from
 +</code>
 +
 +
 +  * inode_fmt est la définition correspondant à la structure C
 +  * < veut dire little endianess
 +  * H veut dire entier non signé sur 2 octets
 +  * s est un caractère
 +  * 30* veut dire 30 fois le type qui suit
 +
 +Voici un exemple d'utilisation 
 +<code python>
 +fs = open ("td2.MinixFS", "rb"
 +fs.seek (ua2addr (5), 0)
 +data = fs.read (dir_len)
 +dirEntry = dir_unpack (data)
 +
 +print dirEntry [0], dirEntry[1].rstrip ('\x00')
 +</code>
 +
 +===== Mise au point de code C =====
 +
 +Il existe un outil de mise au point des programmes écrits en C ou C++ : **gdb**.
 +
 +Il faut au préalable avoir compilé le vôtre avec l’option “**-g**”. Au moment de l’exécution, faîtes précéder la commande shell de “gdb - -args”.
 +<code bash>
 +gdb --args ./a.out A B C D
 +
 +</code>
 +
 +Voici quelques commandes :
 +
 +  * Vous pouvez placer un point d'arrêt avec "**break**  args.cpp:6"
 +  * Attendre le prompt gdb et saisissez “**run**”.
 +  * La commande “**where**” permet de savoir où l’on se trouve dans la pile d’exécution.
 +  * La commande “**frame**  n” permet de se placer dans la pile d’exécution.
 +  * Il est possible d’afficher des valeurs des variables avec la commande “**print**”.
 +
 +<WRAP center round tip 60%> Toutes ces actions peuvent être réalisées sous emacs:
 +
 +  * M-x shell : ouvre un terminal
 +  * M-x compile : lance une compilation avec un lien direct avec les erreurs
 +  * M-x gdb : lance la mise au point et l'observation d'un programme
 +
 +</WRAP>
 +
 +
 +
 +====== TP4 ======
 +
 +Exemple de code pour dessiner dans un JPanel.
 +
 +<code java>
 +public class Panneau extends JPanel {
 +  public Panneau (int width, int height) {
 +    this.width = width;
 +    this.height = height;
 +    Dimension size = new Dimension (width, height);
 +    setMinimumSize (size);
 +    setPreferredSize (size);
 +    setDoubleBuffered (true);
 +  }
 +
 +  public synchronized void update () {
 +    repaint ();
 +  }
 +
 +  public void paint (Graphics g) {
 +    Toolkit.getDefaultToolkit ().sync ();
 +    Graphics2D g2 = (Graphics2D) g;
 +    g2.setBackground (Color.WHITE);
 +    g2.clearRect (0, 0, width, height);
 +
 +    g2.setColor (Color.GREEN);
 +    g2.fillRect (10, 10, 100, 100);
 +
 +    // ...
 +    //g2.setColor (rectangle.color);
 +    //g2.fillRect (rectangle.x, rectangle.y, rectangle.width, rectangle.height);
 +  }
 +}
 +</code>
 +
 +Exemple de code pour tester un objet graphique.
 +
 +<code java>
 +public static final void testComponent (final String title, final Component component) {
 +  SwingUtilities.invokeLater (new Runnable () {
 +    public void run () {
 +      JFrame jFrame = new JFrame (title);
 +      jFrame.addWindowListener (new WindowAdapter () {
 +        public void windowClosing (WindowEvent e) {
 +          System.exit (0);
 +        }
 +      });
 +      jFrame.getContentPane ().add (component, BorderLayout.CENTER);
 +      jFrame.pack ();
 +      Dimension screenSize = Toolkit.getDefaultToolkit ().getScreenSize ();
 +      Dimension size = jFrame.getSize ();
 +      jFrame.setLocation ((screenSize.width - size.width)/4, (screenSize.height - size.height)/4);
 +      jFrame.setVisible (true);
 +    }
 +  });
 +}
 +</code>
 +
 +Il y a 2 possibilités
 +  * soit faire un thread qui redessine le Panneau toutes les secondes et 1 thread par Rectangle à afficher
 +  * soit faire que les Rectangle soit des objet graphique et donc 1 thread par Rectangle qui vont faire une demande de rafraîchissement.
 +Pour la solution objets graphique on pourra utiliser le code suivant :
 +<code java>
 +  invalidate ();
 +  objetGraphiqueADeplacer.setLocation (x, y);
 +  validate ();
 +</code>
 +
 +====== TP5 ======
 +
 +Pour le TP, vous devez télécharger {{ :exercices:20171012-tp5.zip |tp5.zip}}
 +
 +Après décompression de l'archive vous obtenez :
 +
 +Classes utiles pour le TP5 :
 +<code bash>
 +tp5/
 +├── jar
 +│   └── tp5.jar (Game.class Letter.class Player.class TestParse.class)
 +├── src
 +│   └── tp5
 +│       └── GameNetParse.java
 +└── ws
 +    ├── compile.sh
 +    └── launch.sh
 +</code>
 +
 +Vous devez modifier la classe **GameNetParse.java**.
 +Pour compiler et tester, placez vous dans ws.
 +
 +
 +Le lancement du programme consiste dans le test suivant (inclue dans le jar) :
 +<code java>
 +public class TestParse {
 +
 +    static String[] msgs = {
 + "140824 07:09:30 alice: guest bob", // execGuestArg
 + "140824 07:09:31 alice: guest grpA:bob", // execGuestArg
 + "140824 07:09:32 alice: guest grpA:", // execGuestArg
 + "140824 07:09:33 bob: welcome alice@10.0.0.1:8080", // execWelcomeArg
 + "140824 07:09:34 alice: welcome bob@10.0.0.2:8081 chalie@10.0.0.1:8082", // execWelcomeArg
 + "140824 07:09:35 alice: send 10.0.0.1:8080-A", // execLetterArg
 + "140824 07:09:36 alice: answer 10.0.0.1:8082-C", // execLetterArg
 + "140824 07:09:37 alice: reject 10.0.0.1:8080-A", // execLetterArg
 + "140824 07:09:38 alice: close", // execNoArg
 + "140824 07:09:39 bob: full", // execNoArg
 + "140824 07:09:40 bob: done 10.0.0.2:8081-[ACD] 10.0.0.2:8082-[BD] 10.0.0.2:8083-F" // execLettersArg
 +    };
 +
 +    static public void main (String[] arg) {
 + Game game = new Game ();
 + GameNetParse gnp = new GameNetParse (game);
 + for (String msg : msgs) {
 +     gnp.parse (msg);
 +     System.err.println ();
 + }
 +    }
 +}
 +</code>
 +
 +L'objectif du TP est de réaliser l'analyse des lignes précédentes et d'appeler la classe Game (inclue dans le jar) :
 +<code java>
 +public class Game {
 +    public void netClose (String sender) {
 + System.err.println (">close from "+sender);
 +    }
 +    public void netFull (String sender) {
 + System.err.println (">full from "+sender);
 +    }
 +    public void netGuest (String sender, String guest) {
 + System.err.println (">guest from "+sender+" to "+guest);
 +    }
 +    public void netWelcome (String sender, List<Player> players) {
 + System.err.print (">welcome from "+sender);
 + for (Player player : players)
 +     System.err.print (" "+player);
 + System.err.println ();
 +    }
 +    public void netSend (String sender, Letter letter) {
 + System.err.println (">send from "+sender+" with "+letter);
 +    }
 +    public void netAnswer (String sender, Letter letter) {
 + System.err.println (">answer from "+sender+" with "+letter);
 +    }
 +    public void netReject (String sender, Letter letter) {
 + System.err.println (">reject from "+sender+" with "+letter);
 +    }
 +    public void netDone (String sender, List<Letter> letters) {
 + System.err.println (">done from "+sender+" with "+Letter.toString (letters));
 +    }
 +}
 +</code>
 +
 +Vous disposez des autres classes dans le jar.
 +<code java>
 +package tp5;
 +public class Player {
 +    public String name;
 +    public String ip;
 +    public int port;
 +
 +    public Player (String name, String ip, String port) {
 + this.name = name;
 + this.ip = ip;
 + this.port = Integer.parseInt (port);
 +    }
 +
 +    public String toString () { return name+"@"+ip+":"+port; }
 +}
 +
 +public class Letter {
 +    public String alpha;
 +    public String ip;
 +    public int port;
 +
 +    public Letter (String alpha, String ip, String port) {
 + this.alpha = alpha;
 + this.ip = ip;
 + this.port = Integer.parseInt (port);
 +    }
 +}
 +</code>
 +
 +
 +====== TP6 ======
 +
 +Pour le TP, vous devez télécharger {{ :exercices:20170919-tp6.zip |tp6.zip}}
 +
 +Après décompression de l'archive vous obtenez :
 +
 +<code bash>
 +tp6/
 +├── jar
 +│   └── tp6.jar
 +├── src
 +│   └── tp6
 +│       └── model
 +│           └── NetCom.java
 +└── ws
 +    ├── compile.sh
 +    ├── playNet2.sh
 +    ├── playNet.sh
 +    ├── playTxt2.sh
 +    └── playTxt.sh
 +</code>
 +
 +La commande playTxt.sh vous permet de tester en mode texte.
 +
 +
 +Vous devez écrire la classe Java **NetCom.java** pour pouvoir lancer la commande playNet.sh.
 +
 +Pour cela vous pouvez reprendre la classe recvdata.java (voir le bas de la rubrique [[codes:debut|Ressources]]).
 +
 +Pour retrouver es information IP et port des joueurs, il existe des accesseurs dans deux classes suivantes :
 +<code java>
 +public class Player implements Comparable<Player> {
 +
 +    public String getName () { return name; }
 +    public String getIp () { return ip; }
 +    public int getPort () { return port; }
 +}
 +</code>
 +<code java>
 +public class Game extends StateNotifier implements IGame {
 +    public Player getOwner () { return owner;}
 +}
 +</code>
 +La classe Packet quand à elle est définie dans l'interface ICom comme suit :
 +<code java>
 +    public class Packet {
 + String ip;
 + int port;
 + String msg;
 + public Packet (String ip, int port, String msg) {
 +     this.ip = ip;
 +     this.port = port;
 +     this.msg = msg;
 + }
 +    }
 +
 +</code>
 +
 +
 +<WRAP center round important 60%>
 +Si vous votre adresse est un IPV6 par défaut ajoutez "-Djava.net.preferIPv4Stack=true"
 +</WRAP>
  

Outils de la page