Programmation et Langages 1

Master 2 Pro CCI

 

But de la séance 2


Sauf indication contraire, tous les exercices doivent se faire dans votre répertoire PL1 créée lors de la séance 1.

EXERCICE (en préambule)
  1. copiez dans votre répertoire principal le fichier ~mounlaur/CCI_PL1/Rentree2/Rentree2.tar.gz
  2. Décompressez et de-archivez ce fichier (reportez-vous à la séance précédente si vous avez oublié comment faire)
  3. effacer le fichier Rentree2.tar.gz de votre répertoire principal


Dans la suite les parties écrites en vert peuvent être ignorées en première lecture (et traitées ensuite en fonction du temps disponible).

1- Manipulation de processus Unix

1.1 Notion de processus

Un processus est un programme qui est en cours d'exécution. A un instant donné, plusieurs processus peuvent s'exécuter sur un même ordinateur. Chaque processus est identifié par un numéro unique dans le système (pid, pour process id) et c'est au travers de cette identification qu'un utilisateur pourra agir sur le processus (l'arrêter, le redémarrer, etc).

1.2 Identification d'un processus

La commande ps permet de connaître les identifications des processus actifs (c.a.d en cours d'exécution) à l'instant courant. Il existe un grand nombre d'options associées à cette commande.  Par exemple,

ps -u nom-d'utilisateur         liste les processus s'exécutant pour un utilisateur donné
ps -ef                                             affiche la liste de tous les processus actifs du système.

 

1.3 Tâches de fond

Quand vous lancez un programme, vous perdez la main jusqu'à la fin de l'exécution du programme. Vous pouvez vous dégager d'une exécution en demandant que celle-ci soit transformée en tâche de fond. Pour cela, il faut faire suivre l'appel du programme par le symbole &.

Si vous avez déjà lancé un programme sans cette option et que vous souhaitez le faire passer en tâche de fond, vous devez interrompre votre programme avec Ctrl-z, puis taper bg (pour background). Par la suite, la commande fg (pour foreground) permettra de faire revenir votre programme en tâche normale, si vous le souhaitez, en tapant fg numéro-de-job, le numéro de job étant récupérable au travers de la commande jobs.

 
EXERCICE  
    a. Lancez le programme nedit, dont la fonction principale exécute une boucle infinie de traitement d'événements graphiques.  
    b. Arretez ce programme pour le faire passer en tâche de fond  
    c. Faites revenir ce programme en tâche normale

1.4 Ctrl-c et kill

Pour tuer un processus en cours d'exécution, il existe deux moyens. Le premier consiste à utiliser la commande kill suivie de l'option -9 puis de l'identification du processus à tuer. L'autre moyen, si ce programme n'est pas une tâche de fond, consiste à taper Ctrl-c dans la fenêtre dans laquelle il a été lancé.

 
EXERCICE  
    a. Relancez le programme nedit 
    b. Tuez le processus exécutant ce programme par Ctrl-c.   
    c. Relancez une exécution du programme en tâche de fond (en tapant nedit &)
    d. Tuez le nouveau processus par la commande kill.
 
 

2. Manipulation des commandes données au shell   

2.1 Historique
Le shell (ou interpréteur de commande) conserve un historique des commandes que vous lui avez données à exécuter.
Pour remonter dans la liste des commandes précédentes, vous pouvez utiliser Ctrl-P ou la flèche montante de votre clavier (Ctrl-N ou flèche descendante pour redescendre).
Pour visualiser l'historique, tapez history.
Pour ré-exécuter une commande donnée, tapez !<numéro de commande>.


2.2 Aliasing

Certaines commandes peuvent être longues à taper ; Il existe un moyen simple de " raccourcir " les commandes. Le mécanisme d'alias permet en effet de dire à l’interprète de commandes : considère que tel mot signifie telle commande. Par exemple :

alias ll='ls -l'             ll sera automatiquement associé à ls -l
unalias ll                   supprime l'alias
 
 
EXERCICE  
    Testez l'usage de l'historique et des alias:
    1. ré-exécutez la dernière commande ls que vous avez exécutée (sans la re-taper, en utilisant l'historique)
    2. avec la commande alias (sans arguments), consultez la liste des alias prédéfinis
    3. créez vous un alias de nom pere qui  vous fait remonter d'un répertoire dans l'arborescence (remplace le répertoire courant par le répertoire pere)
    4. Exécutez cet alias, puis détruisez-le. Que se passe t-il si vous exécutez maintenant la commande pere ?
    5. Créez un nouvel alias de nom ls qui exécute la commande date. Est-ce cet alias ou la commande ls classique qui est appelée lorsque vous tapez ls ? Détruisez cet alias.
 

3. Variables d'environnement
Lors de la connexion d'un utilisateur dans le système, ce dernier possède un environnement de travail. Comme vous avez pu le remarquer dans les sessions précédentes, cet environnement vous place automatiquement dans votre répertoire principal lors de la connexion. Il y a en fait beaucoup d'autres actions qui sont effectuées de manière implicite lors de cette connexion. Ces actions sont "programmées" dans différents fichiers de configuration, dont l'un s'appelle .cshrc (il s'agit en fait du fichier de configuration du shell csh). Le fichier .cshrc est "exécuté' à chaque lancement du shell (donc à chaque fois qu'un xterm est lancé).

Les actions effectuées dans un fichier de configuration consistent entres autres en :

Le shell est non seulement un langage de commande, mais également un langage de programmation. Pour cette raison, il introduit les notions de variables, de paramètre, de structures de contrôle (si, sinon, tant que, etc).  Certaines variables shell sont appelées variables d'environnement.  Elle sont identifiées par un nom. L'affectation d'une valeur à une variable d'environnement permet de configurer son propre environnement de travail. Par exemple : La valeur d'une variable d'environnement peut être consultée par la commande echo $nom_variable. Les valeurs de l'ensemble des variables d'environnement sont données par la commande env.
 
EXERCICE  

    a. Exécutez la commande env et essayez de deviner le rôle de certaines variables d'environnement (d’après leur  nom et leur valeur)
    b. Lorsque vous vous connectez, le système vérifie s'il existe un fichier .cshrc personnel dans votre répertoire principal et l’exécute dans l'affirmative. Cela permet de personnaliser le fonctionnement du shell. Avec nedit, créez dans votre répertoire principal un fichier de nom .cshrc (le point n'est pas une erreur de frappe !). Ecrivez dans ce fichier la ligne suivante :
            alias pere "cd .."
    c. "ré-exécutez" votre fichier .cshrc en tapant la commande source .cshrc 
     
    d. Vérifiez que l'alias défini fonctionne bien ...

4. La variable path

On rappelle que la plupart des commandes Unix utilisées (ls, cd, cp, etc.) sont des programmes stockés sur le disque dur de la machine. La variable path est une variable d'environnement importante. Elle contient la liste des répertoires dans lesquels l’interprète de commande va aller chercher (dans cet ordre !) les programmes correspondant aux commandes que vous lui fournissez. La commande which permet de rechercher l'emplacement d'un programme. Lorsque vous tapez which nom_prog, le shell recherche un fichier exécutable de nom nom_prog. Il effectue sa recherche en parcourant  les répertoires définis dans la variable path (comme le ferait l’interprète de commande pour  exécuter mon_prog).
 
EXERCICE   
    a. Rechercher l'emplacement du programme date, qui donne la date courante.  
    b. Créez un répertoire ESSAI et copiez ce programme date dans ce répertoire sous le nom ls
    c. Placez-vous dans  le répertoire ESSAI

    d. Examinez le contenu de votre variable path (echo $path).  Quel programme sera exécuté si vous tapez ls ?
    e. Vérifiez-le en tapant ls
    f. Tapez maintenant ./ls et interprétez ce qu'il se passe.

 

EXERCICE    
    a. ouvrez un nouveau xterm avec la commande xterm et placez-vous dans ce nouvel xterm
    b. modifiez la commande path en ajoutant le répertoire ESSAI en tête de liste : set path=(~/PL1/Essai $path)
    c. vérifiez en tapant echo $path que la modification a bien eu lieu
    d. tapez ls
    e. placez-vous-vous dans votre répertoire principal et tapez ls
    f.
    détruisez le répertoire ESSAI et son contenu, et fermez ce xterm.


 5.  Premiers pas avec le langage C

L'objectif est ici d'examiner un premier programme C, de le compiler et de l’exécuter, puis de le modifier.
On considère pour cela le programme C suivant, qui est dans votre répertoire Rentree2/max.c

#include <stdio.h>

int main() {
    int x, y ;
   
    printf ("tapez deux entiers au clavier\n") ;
    scanf("%d", &x) ;
    scanf("%d", &y) ;

    if (x > y) {
        printf("le maximum des deux entiers est %d\n", x) ;
    } else {
       
printf("le maximum des deux entiers est %d\n", y) ;
    } ;

    return 0 ;
}



Ce fichier est un programme source. Il contient des instructions en C, facile à comprendre par une personne qui connaît ce langage,  mais pas exécutable tel quel par l'ordinateur. Pour produire un programme exécutable il faut donc d'abord traduire ce programme source en un fichier contenant des instructions exécutables par le processeur de la machine. On utilise pour cela un compilateur.

Pour exécuter une compilation C, nous utiliserons la commande gcc (sous une forme très simple dans cette séance) :

gcc -Wall -o pgm_executable pgm_source

EXERCICE  
  1. Placez-vous dans votre  répertoire Rentree2
  2. Tapez la commande suivante : gcc -Wall -o max max.c 
  3. Observer que le fichier max a été créé dans le repertoire courant (commande : ls ou ls -l,)
  4. Exécuter le programme max, en tapant le nom du fichier exécutable généré par le compilateur: ./max
  5. Et si vous tapez ./max.c ?
 


EXERCICE
  1. Toujours dans le répertoire Rentree2, copiez le fichier max.c en un fichier min.c
  2. Ouvrez le fichier min.c (avec nedit) et modifiez-le pour que le programme affiche maintenant le minimum des deux entiers
  3. Sauvegardez ce nouveau programme, et compilez-le en un programme exécutable de nom min
  4. Testez votre programme min

Dans la commande de compilation, l'option -Wall permet d'être informé sur l'ensemble des erreurs et avertissements (ou warnings) relevés par le compilateur sur la correction du programme source.  Tant qu'il subsiste des erreurs, le programme exécutable n'est pas produit. Si tous les warning ne sont pas éliminés le programme exécutable est tout de même produit ; mais pour éviter des mauvaises surprises, nous vous conseillons néanmoins de les corriger systématiquement (ils indiquent en général des problèmes potentiels à l'exécution). Si vous ne mentionnez pas l'option -Wall les warnings ne sont pas signalés.


6. Redirection des entrées-sorties d'un programme dans un fichier

Lorsqu'un programme s'exécute, tous ses affichages se font par défaut sur l'écran. Il existe un mécanisme qui permet de rediriger les affichages dans un fichier. Pour cela , il faut faire suivre l'appel du programme par le symbole > suivi du nom de fichier voulu (nom_prog > nom_fichier). Cette possibilité est intéressante lorsque le nombre d'affichage est important, et que l'on souhaite pouvoir vérifier la bonne exécution du programme en étudiant ses traces d'exécution.
Deux variantes utiles :

nom_prog > nom_fichier   crée (ou remplace) le fichier nom_fichier avec la sortie de nom_prog

nom_prog >> nom_fichier ajoute la sortie de nom_prog  à la fin du fichier nom_fichier 

Il est également possible de rediriger les entrées d'un programme, pour que celui-ci lise les données non pas au clavier mais depuis un fichier donné. Pour cela, il faut faire suivre l'appel du programme par le symbole < suivi du nom de fichier d'entrée.

 
EXERCICE  
    a. Redirigez les sorties de la commande ls dans un fichier ls_res.  
    b. Recommencez en ajoutant la nouvelle sortie de la commande ls au même fichier ls_res.   
    c. Que fait la commande suivante : cat ls_res > f
    d.
    Exécuter le programme max en redirigeant ses entrées depuis un fichier. Que faut-il écrire dans ce fichier pour que le programme fonctionne ?
 

7. Redirection de la sortie d'un programme vers l'entrée d'un autre

Il est possible de rediriger les sorties d'un programme de telle sorte que les données produites en sortie soient fournies en entrée à un deuxième programme, activé à la suite du premier programme.

 
EXERCICE 

Que fait la commande suivante : ls -l | wc -l      (utilisez man pour comprendre ce que fait wc).
 

8. Séquencement

L'opérateur de séquencement est le point virgule. Il permet d'exécuter plusieurs commandes en séquence.

Cde1 ; Cde2 ; Cde3 engendre l'exécution de Cde1, puis de Cde2, puis de Cde3.

EXERCICE 

Construire la commande composée de trois sous-commandes séquentielles, qui effectue l'équivalent de la commande donnée à l'exercice précédent en passant par un fichier intermédiaire :  

  1. le résultat de ls -l est placé dans un fichier f
  2. on comptabilise le nombre de lignes de f
  3. on détruit f


  9. Fichier de commande

Lorsqu'une suite de commande est souvent utilisée il est possible de la mémoriser dans un fichier de commande. En tapant le nom de ce fichier l’interpréteur exécutera alors chacune de ces commandes (ce qui nous évite de toutes les saisir à chaque fois). On donne ci-dessous un exemple de fichier de commande :

#!/bin/sh

cd

echo "le repertoire courant est"

pwd

cd PL1

mkdir TP1

cd TP1

echo "le repertoire courant est"

pwd



EXERCICE 
  1. Saisissez ces commandes dans un fichier de nom makeTP1.sh
  2. Exécutez la commande ./makeTP1.sh
  3. Donnez-vous les droits en exécution sur le fichier makeTP1.sh
  4. Exécutez la commande ./makeTP1.sh
  5. Examinez le fichier de commande exemple.sh dans votre répertoire Rentree2
  6. Exécutez les commandes suivantes :
    • ./exemple.sh
    • ./exemple.sh 42
    • ./exemple.sh septembre 2012
    • ./exemple.sh ab cd
  7. En vous inspirant de cet exemple, modifier makeTP1.sh en un fichier de commande makeTP.sh qui prend en paramètre le numéro du répertoire TP à créer.

  10. Exercice de synthèse

Écrire un fichier de commande qui prend deux fichiers en paramètres et affiche le nombre de ligne de celui qui en contient le plus
...