TP3 - Environnement de travail et Compilateur C
Instructions
- On rappelle que dans tous les exercices le
$
en début de commande représente le prompt, il n'est pas à saisir lorsque vous écrivez une ligne de commande. - Pour chaque nouvelle commande, n'hésitez pas à consulter sa page de manuel avec la commande
man
, ou à utiliser l'option--help
(si elle est disponible) pour savoir ce qu'elle fait.
Les variables du shell
Définition et utilisation
Une variable est un nom qui est associé à une valeur. En shell, les variables sont des chaînes de caractères. Le développement d’une variable est le remplacement du nom de la variable par sa valeur.
Par exemple, la variable PS1
est la variable qui contient le prompt du shell. Lors des TP précédents, quand vous tapiez
la commande PS1='$ '
, vous avez affecté la chaîne $<space>
à la variable PS1
. Lorsque le shell affiche le prompt, il développe la variable PS1
et affiche la chaîne $<space>
.
Les variables du shell sont des variables d’environnement. Elles sont accessibles à tous les processus lancés par le shell. On peut les lister avec la commande env
ou printenv
. On peut également les lister avec la commande set
qui liste également les variables internes du shell (voir la page de manuel de set
pour plus de détails).
Exercice 1 : Les variables du Shell
- Tapez les commandes suivantes dans un terminal:
- Rappelez ce que fait la commande
echo
. À votre avis, à quoi sert le caractère$
devant le nom de la variablenom_fich
? - Que se passe-t-il si on demande au shell d'afficher le contenu d'une variable qui n'existe pas?
- Que se passe-t-il si vous mettez un espace entre le nom de la variable et le signe égal
=
? Et entre le signe égal et la valeur? - Entrez les commandes suivantes et essayez de commenter leur effet:
Caractères spéciaux et inhibitions
Caractères spéciaux du shell
Certains caractères ont une signification particulière pour le shell : on dit qu’ils sont spéciaux. À l’inverse, on dit d’un caractère qui n’a pas d’autre signification que lui-même, qu’il a son sens littéral. Nous listons ci-dessous les caractères spéciaux ; la plupart d’entre eux seront vus en détail plus tard dans le cours.
; <newline> | &
ils mettent fin à la commande qui les précède. On a utilisé<newline>
pour représenter le caractère nouvelle ligne qu’on saisit avec la touche Entrée. Le caractère spécial|
est saisi avec la combinaison de touchesAlt Gr-6
(Option-Shift-l
sous mac), on l’appelle pipe ou conduite. Le caractère spécial&
est saisi avec la combinaison de touchesAlt Gr-8
et sert à lancer des commandes en arrière-plan.< >
appelés chevrons, ils permettent les redirections.( )
pour regrouper des commandes et les lancer dans un sous-shell.$
pour le développement de variables, le développement arithmétique et la substitution de commande.`
l’accent grave (en anglais, backtick ou backquote) pour la substitution de commandes (ancienne syntaxe). Il est saisi au clavier avec la combinaison de touchesAlt Gr-7
suivie d’un espace.<space> <tab>
délimitent les noms de commandes et arguments.\ ' "
la contre-oblique (aussi appelée backslash ou antislash), l’apostrophe (en anglais single quote) et le guillemet anglais (en anglais double quote) qui permettent justement d’inhiber les caractères spéciaux, c’est-à-dire leur rendre leur sens littéral.
Enfin, les caractères suivants ont une signification particulière dans certains contextes et doivent donc parfois être inhibés:
* ? ]
Pour le développement de noms de chemins.#
Pour écrire des commentaires (sauf s’il est au milieu d’un mot).~
Pour le développement du tilde (répertoire personnel).=
Pour l’affectation de variables.%
Pour le contrôle des tâches (job control).
Exercice 2 : Inhibition de caractères spéciaux (la contre-oblique \
)
- Testez les commandes suivantes.
- En vous référent aux questions précédentes, répondez aux questions ci dessous:
- Que fait le caractère
\
devant un autre caractère que<newline>
(on rappelle que le caractère<newline>
est celui qui résulte de l'appui de la touche Entrée du clavier) ? - À quoi sert la chaîne de caractères
\<newline>
? - Comment peut-on obtenir un caractère
\
littéral ? Comment afficher\\
à l'aide de la commandeecho
?
- Que fait le caractère
Exercice 3 : L’inhibition des caractères spéciaux (l'apostrophe '
)
Remarque
L'option -i
de la commande rm
permet de demander une confirmation avant la suppression.
-
Tester les commandes suivantes :
où$ touch 'ceci est un horrible nom de fichier' $ rm -i ceci est un horrible nom de fichier $ rm -i 'ceci est un horrible nom de fichier' $ touch p; echo le caractère * est-il spécial ? et ? $ echo 'le caractère * est-il spécial ? et ?' $ echo 'en fait, même la fin de ligne<newline>est un caractère normal entre<newline>apostrophes' $ echo 'le seul caractère spécial entre apostrophes n'est-il pas apostrophe ?'
<newline>
sera à taper avec la touche Entrée de votre clavier. -
Au vu des expériences précédentes (et d’autres à inventer si nécessaire), répondre aux questions suivantes :
- Quels sont les caractères qui sont spéciaux entre apostrophes ?
- Comment obtenir une apostrophe dans une chaîne entre apostrophes (question piège) ?
- Comment, avec une combinaison de chaînes entre apostrophes et d’une inhibition par contre-oblique, obtenir avec
echo
l’affichage suivant ?
Exercice 4 : L’inhibition des caractères spéciaux (les guillemets anglais "
)
- Tester les commandes suivantes et notez vos observation:
$ echo "? * et [ sont utilisés pour le développement de chemins" $ echo "~ provoque un développement du tilde" $ echo " Entre \" , on peut aussi <newline>écrire sur plusieurs<newline> lignes" $ nom=Alice $ echo '$nom scripte en shell' $ echo "$nom scripte en shell" $ echo "\$nom scripte en shell" $ echo "le chemin absolu du répertoire courant est `pwd`" $ echo "le chemin absolu du répertoire courant est \`pwd\`" $ echo "le chemin absolu du répertoire courant est $(pwd)" $ echo "le chemin absolu du répertoire courant est \$(pwd)" $ echo "Aussi sûr que 2 et 2 font $((2 + 2))" $ echo "Aussi sûr que 2 et 2 font \$((2 + 2))" $ echo "\\\\\"\$\`\*\'"
- Testez les commande suivantes et notez vos observations:
- Au vu des expériences précédentes (et d’autres à inventer si nécessaire), répondre aux questions suivantes :
- Quels sont les caractères qui sont spéciaux entre guillemets anglais ?
- Quel est le rôle du caractère
\
entre guillemets anglais ? Dans quel contexte est-il spécial, littéral ? - Quels sont les développements qui n’ont jamais lieu entre guillemets anglais ?
- Selon vous, pourquoi avoir créé plusieurs mécanismes d’inhibition ?
Extensions de chemins
Extension de chemins
Lorsqu’on saisit un chemin contenant des wildcards ou caractères joker (Ref. dernier exo du TP1), le shell le développe en remplaçant les caractères spéciaux *
, ?
et [
par les noms des fichiers qui correspondent à l’expression régulière qui résulte de l’extension du chemin. On appelle ce mécanisme l’extension de chemin.
Par exemple, si le répertoire courant contient les fichiers a
, b
, c
, d
et e
, alors le chemin a*
est développé en a
, le chemin ?
en a b c d e
et le chemin [a-c]
en a b c
.
L’extension de chemin est effectuée par le shell, avant que la commande ne soit exécutée. Si aucun fichier ne correspond à l’expression régulière, le shell laisse le chemin tel quel.
Exercice 5 : Des fichiers et des images
- Créer un répertoire
dir
et y créer les fichiers videsfile-1.txt
,file-2.txt
,file-3.txt
,file-4.txt
,file-5.txt
,file-6.txt
,file-7.txt
,file-8.txt
,file-9.txt
,config-a.txt
,file-b.txt
. - Créer également dans
dir
les fichiers vides suivantsimg-1.png
,img-2.png
,img-3.png
,img-4.png
,img-5.png
,img-6.png
,img-7.png
,img-8.png
,img-9.png
. - Créer ensuite dans
dir
deux sous-répertoiresfiles
etimgs
. - En vous aidant de l'extension de chemin et de la commande
mv
, déplacer les fichiers.txt
dans le répertoirefiles
. Faîtes de même pour les fichiers.png
dans le répertoireimgs
. - Donnez l'expression qui reconnais les fichiers
config-a.txt
etfile-b.txt
. Puis supprimez les fichiers correspondants à cette expression. (Grâce à l'extension de chemin, vous pouvez le faire en une seule commande). - Supprimez le répertoire
dir
et son contenu.
Exercice 6 : Extension de l'accolade
- Testez les commandes suivantes
- Que fait la commande
echo {a..d}
? Quel est le rôle de la virgule,
dans l'extension de l'accolade ? - Que fait la commande
echo {a..d..2}
? Quel est le rôle du2
dans l'extension de l'accolade ? - Testez les commandes suivantes, et observez leur résultats.
- Créer un répertoire
dir
. Déplacez-vous y. En utilisant l'extension de l'accolade, en une seule commande, créer les fichiers videsfile-1.txt
,file-2.txt
,file-3.txt
,file-4.txt
,file-5.txt
,file-6.txt
,file-7.txt
,file-8.txt
,file-9.txt
. - Déplacez tous les fichiers
.txt
dans un répertoiredir/files
. - Créer un répertoire
dir/imgs
. Déplacez-vous y. En utilisant l'extension de l'accolade, en une seule commande, crééer les fichiers videsimg001.png
,img002.png
,img003.png
,img004.png
,img005.png
,img006.png
,img007.png
,img008.png
,img009.png
. - Supprimez le répertoire
dir
et tout son contenu.
Substitution de commande
Substitution de commande
La substitution de commanande est un mécanisme qui permet d’insérer le résultat d’une commande dans une chaîne de caractères.
La substitution de commandes dans une chaîne de caractères est une autre facilité offerte par le shell. Elle permet de capturer la sortie d'une commande et de l'assigner à une variable ou de l'utiliser comme un argument d'une autre commande. Comme beaucoup de commandes Linux génèrent une sortie, la substitution de commandes peut être très intéressante.
Il existe deux syntaxes pour la substitution de commande : la syntaxe ancienne avec les accents graves (`
) et la syntaxe moderne avec les parenthèses $(...)
. L'ancienne syntaxe est déconseillée car elle ne permet pas d’imbriquer les substitutions de commande. Nous ne la présenterons donc pas ici.
Exercice 7 : Substitution de commande simple
- Testez les commandes suivantes et observez leur résultat:
- Que fait la commande
echo $(date)
? Quel est le rôle du$
devant la parenthèse ouvrante(
? - Tapez ensuite les commandes suivantes et observez leur résultat:
- Pouvez-vous déduire le rôle des guillemets anglais dans la substitution de commande ?
- Quelle est la différence entre
$(...)
et${...}
?
Exercice 8 : Substitution de commande imbriquée
- Testez les commandes suivantes et observez leur résultat:
- Testez ensuite la commande suivante: Sans exécuter la commande qui suit saurez vous prédire son résultat ?
Compilation de programme C
Le compilateur C de Linux
gcc
est le compilateur C de Linux. Il permet de compiler du code C. Il est très utilisé par les développeurs. Il est très complet et possède de nombreuses fonctionnalités. Nous allons voir un aperçu de son utilisation.
La compilation d'un programme en C passe par plusieurs étapes, qui sont essentiellement les suivantes:
- La précompilation : elle permet de transformer le code source en un code intermédiaire.
- La compilation : elle permet de transformer le code intermédiaire en code machine.
- L'édition des liens : elle permet de lier le code machine avec les bibliothèques utilisées.
- La création de l'exécutable : elle permet de créer l'exécutable.
Exercice 9 - Le compilateur gcc
- Créer un fichier
hello.c
dont le contenu est le suivant: -
Placez-vous ensuite dans le répertoire contenant votre fichier
hello.c
et tapez la commandegcc hello.c
. Cette commande va compiler votre programme et créer un fichiera.out
qui est l'exécutable de votre programme. Tapez enfin la commande./a.out
pour exécuter votre programme.Attention
- Si vous avez déjà un fichier
a.out
dans votre répertoire, il sera écrasé par la commandegcc hello.c
. a.out
est le nom par défaut de l'exécutable créé pargcc
. Vous pouvez changer ce nom en utilisant l'option-o
degcc
. Par exemple,gcc hello.c -o hello
va créer un exécutablehello
au lieu dea.out
.
- Si vous avez déjà un fichier
-
Récupérez ensuite cette archive hello.tar.gz.
- Extraire les fichiers de cet archive et déplacez vos dans le répertoire
hello
qui en sera extrait. Vous pouvez le faire grace à la commande suivate: - Tapez la commande
pour compiler votre programme. Cette commande va compiler votre programme et créer un fichier
run
qui est l'exécutable de votre programme. Exécutez enfin votre programme avec la commande./run
. - Supprimer le fichier
run
et modifier ensuite le fichierhello.c
de tel sorte à avoir volontairement une erreur : supprimer l'accolade fermante de la fonctionvoid hello()
. Réexécutez ensuite les commandes de la question 5. Que remarquez-vous ? - Remodifier ensuite le fichier
hello.c
en remettant l'accolade fermante mais rajouter unreturn 1
dans la définition de la fonction (avant l'accolade fermante). Réexécutez ensuite les commandes de la question 5. Que remarquez-vous ? - Conclure sur la gestion des erreurs et des warnings sur
gcc
.
Exercice 10 - Compilation séparée et édition des liens
Tip
Pour compiler un programme en C, il est possible de le faire en plusieurs étapes. On peut d'abord compiler chaque fichier source en un fichier objet, puis éditer les liens pour créer l'exécutable. Cela permet de gagner du temps lors de la compilation de gros projets.
En effet si un seul fichier source est modifié, il n'est pas nécessaire de recompiler tous les fichiers sources. Il suffit de recompiler le fichier source modifié et de rééditer les liens.
- L'option
-c
degcc
permet de compiler un fichier source en un fichier objet. L'option-o
permet de spécifier le nom du fichier objet à créer. - L'édition des liens se fait avec la commande
gcc
en spécifiant les fichiers objets à lier. L'option-o
permet de spécifier le nom de l'exécutable à créer.
Dans cette configuration, imaginons que nous avons un fichier main.c
qui contient la fonction main
et un fichier hello.c
qui contient la fonction hello
. Pour compiler ces deux fichiers en un exécutable run
, on peut procéder comme suit:
- Dans le répertoire
hello
, de l'exercice précédent, créer deux fichiersbye.c
etbye.h
, en utilisant l'extension de l'accolade, dont les contenus sont les suivants:bye.h
:bye.c
:
- Toujours en utilisant l'extension de l'accolade, compiler les deux fichiers
hello.c
etbye.c
en deux fichiers objetshello.o
etbye.o
. Assurez-vous que le compilateur ne renvoie pas d'erreurs. (Par défaut si on ne spécifie pas le nom du fichier de sortie, les fichiers.c
sont compilés en des fichiers objets de même nom) - Modifier ensuite le fichier
main.c
pour afin d'inclure le fichierbye.h
et appeler la fonctionbye
à la fin de la fonctionmain
. Le contenu du fichiermain.c
doit être le suivant: - Compiler le fichier
main.c
en un fichier objetmain.o
. Assurez-vous que le compilateur ne renvoie pas d'erreurs. - En utilisant l'extention de chemin avec le caractère
*
, éditer les liens pour tous vos fichiers objets afin créer l'exécutablerun
. Exécutez ensuite votre programme avec la commande./run
.