Formation Unix/Linux

Programming, Unix, C Language · course

Voir tous les documents en systèmes d'exploitation et cloud

Formation Unix/Linux (9)

Introduction à la programmation C sous Unix

Olivier BOEBION

Mars 2004

1 Le langage C

Introduire un langage de développement dans des travaux pratiques sur un système d’ex-

ploitation peut vous paraˆıtre curieux. Si vous devez travailler sur des systèmes utilisant UNIX

ou Linux, vous constaterez que le langage C est incontournable. Le noyau, les différents in-

terpréteurs de commande (csh, bash...), les commandes du système d’exploitation (ls, cp, rm ...)

sont écrits avec le langage C. Si vous voulez enrichir le système avec une application nouvelle,

celle-ci sera le plus souvent écrite avec ce langage et vous devrez parfois savoir la compiler.

Le langage C est un langage d’intérêt général et il est portable. Il n’est pas affecté à un type

de programmation comme, par exemple, le Cobol pour les bases de donnée ou encore le For-

tran pour le calcul. Il offre la possibilité d’effectuer des opérations de bas niveaux, opérations qui

permettent l’écriture de systemes d’exploitation. Il possede un jeu d’instructions limité enrichie

par de nombreuses librairies. La grande majorité des systèmes d’exploitation ont un compilateur

C et un effort de normalisation a été effectué à travers la norme ANSI.

Le compilateur Gnu C est intégré dans toutes les distributions Linux. C’est avec celui-ci

que nous allons travailler.

2 Construction d’un programme C

2.1 Déroulement d’une compilation

L’écriture d’un programme C donne lieu à la création d’un ou plusieurs fichiers sources

(extension .c) contenant les éléments du langage. La création de fichiers header personnels

(extension .h) permet de définir les fonctions créées par l’utilisateur. Une fois ces fichiers prêts,

l’appel aux compilateur peut se faire. Avec Gnu C, la ligne de commande minimale sera :

Cette ligne de commande crée un fichier exécutable a.out. Pour nommer précisément le

binaire, l’option -o du compilateur suivi du nom est utilisée :

gcc source.c

gcc -o binaire source.c

1

La création d’un fichier exécutable a partir de fichiers sources en C fait appel a plusieurs

programmes comme le montre la figure 1.

Fig. 1 – Déroulement d’une compilation

Le précompilateur (cpp) est d’abord lancé. Il supprime les commentaires et interpréte les

directives de compilations qui se trouvent dans les fichiers header ou sources.

L’appel au compilateur (cc ou gcc) permet en une ou deux passes de générer du code en

assembleur.

L’assembleur (as) crée un fichier objet correspondant au fichier source qui sera traité ensuite

par l’éditeur de lien (ld). Cette dernière opération produit l’exécutable final en réunissant les

fichiers objets de l’utilisateur et tous les fichiers objet des librairies nécessaires.

2

2.2 Les options du compilateur

Nous venons de voir une première option (-o) du compilateur. Il en existe de nombreuses

(voir le manuel en ligne). Le tableau 1 vous présente quelques unes de ces options.

Options Caractéristiques

-v

-c

-o

-S

-L

-l

-I

Visualise toutes les actions effectuées lors d’une compilation.

Publicité

Supprime l’édition de lien. Seul le(s) fichier(s) .o est (sont) généré(s).

Spécifie le nom de l’exécutable à générer.

Ne génère pas le fichier exécutable et crée un fichier .s contenant le programme

en assembleur.

Indique un chemin de recherche supplémentaire à l’éditeur de liens pour d’autres

librairies.

Indique une nouvelle librairie à charger.

Indique un chemin de recherche supplémentaire pour des fichiers de définition

(.h)

Tab. 1 – Quelques options du compilateur C

2.3 Exercice

Créez le fichier source bonjour.c qui contient les instructions C suivantes :

include <stdio.h>

int main(void)

{

printf("bonjour\n");

exit(0);

}

Compilez-le pour créer l’exécutable bonjour et testez-le. Recompilez ce programme en

spécifiant l’option -v et commentez ce qui s’affiche.

Trouvez l’option pour ne générer que le fichier assembleur puis objet de votre source.

3

3 Construction de librairie

Il est intéressant de se construire des librairies contenant les fonctions les plus fréquemment

utilisées plutôt que de les réécrire à chaque projet. Il suffit ensuite d’indiquer vos librairies au

moment de la compilation. Pour cela, les options -L et -l permettent respectivement d’inclure

un nouveau chemin de recherche pour l’éditeur de lien et d’indiquer le nom de librairie.

3.1 Exercice : Création d’une librairie

Vous trouverez ci-dessous 2 fonctions qui affichent ”Bonjour” et ”Au revoir” autant de fois

que le nombre passé en argument :

void bonjour(int nbre)

{

int i;

for(i=0;i<nbre;i++) printf("Bonjour ...\n");

return;

}

void revoir(int nbre)

{

int i;

for(i=0;i<nbre;i++) printf("Au revoir ...\n");

return;

}

Placez ces fonctions dans des fichiers nommés bonjour.c et revoir.c. Compilez ces fichiers

afin de générer les fichiers objet :

gcc -c bonjour.c revoir.c.

Créez la librairie libsalut.a à l’aide de la commande ar :

ar r libsalut.a bonjour.o revoir.o

Vous pouvez vérifier le contenu de votre librairie en tapant :

ar t libsalut.a

4

3.2 Exercice : Utilisation de la librairie

A partir de cette étape, vous pouvez déjà utiliser ces fonctions en respectant quelques condi-

tions. La premiere de celles-ci est de placer libsalut.a dans le répertoire ou vous effectuez votre

Publicité

compilation. La seconde est de compiler votre programme en spécifiant le nom de la librairie.

Tapez le programme suivant dans le fichier exemple2.c :

#include <stdio.h>

void main(void)

{

int a=0;

while (a<l||a>5)

{

printf("Donnez un nombre entre 1 et 5 compris: ");

scanf("%d",&a);

printf("\n");

}

bonjour(a);

revoir(--a);

exit(0);

}

Compilez ce programme en exécutant la ligne suivante :

gcc -o exemple exemple2.c libsalut.a

Vous pouvez ensuite placer toutes vos librairies dans un de vos répertoires (par exemple,

∼/librairies). Vous lancerez alors votre compilation de la manière suivante :

gcc -o exemple exemple2.c -L∼/librairies -lsalut

4 Compilation séparée

4.1 Présentation

Lorsque vous réalisez de gros projets, vous devez découper ceux-ci en plusieurs programmes

sources. L’avantage est un gain de temps au moment de la compilation. Si une application est

constituée des 3 fichiers sources source1.c, sourc2.c et sourc3.c la compilation d’un exécutable

nommé exec est effectuée par la ligne suivante :

gcc -o exec sourc1.c sourc2.c sourc3.c

Nous connaissons l’option -c du compilateur qui permet de générer des fichiers objets sans

effectuer une édition de lien. Si vous modifiez un des fichiers source (par exemple, sourc3.c),

nous utilisons cette option pour ne compiler que le fichier modifié :

gcc -c sourc3.c

gcc -o exec sourc3.o sourc1.o sourc2.o

5

4.2 Exercices

Sur ”http ://www.obs-vlfr.fr/∼boebion/Unix”, télécharger les fichiers menu.c, header.h,

date.c et fichier.c. Ces 4 fichiers compose une application qui permet d’afficher la date locale

du systeme et demande un nom de fichier pour indiquer la date de sa derniere modification.

Compilez cette application avec comme nom d’exécutable prog et vérifiez son bon fonction-

nement. Ajoutez ensuite la ligne suivante a la neuvieme ligne de fichier.c :

printf("Affichage de la date de modification d’un fichier.\n");

Qu’effectuez-vous comme compilations pour prendre en compte ce changement ?

5 Les fichiers make

5.1 Intérêt et syntaxe

Lorsqu’on réalise un projet en le découpant en plusieurs modules, vous constatez qu’il est

difficile de se rappeler ce qu’il faut recompiler après une modification.

La commande make permet de maintenir un programme automatiquement. Pour cela, elle

utilisera un fichier de description nommé en général makefile ou Makefile qui contient des

dépendances et les actions à mettre en oeuvre pour maintenir le programme.

La syntaxe de la commande make est la suivante :

make [-f nom fichier] [-arg optionnels] [ref..]

L’option -f indique le nom du fichier de description. En général, la commande est lancée

sans argument. Dans ce cas, elle recherche un fichier de description sur le répertoire courant.

Publicité

Parmi les arguments optionnels, vous trouverez :

– -s (mode silencieux) : pas d’affichage des commandes avant exécution ;

– -n : l’ensemble des commandes à effectuer est affiché mais non exécuté ;

– -d (mode debug) : le maximum d’informations est affiché.

5.2 Contenu d’un fichier Makefile

Un fichier Makefile contient :

– les dépendances entre les fichiers sources composant votre application ;

– les actions lancées suivant la modification d’un de ces fichiers sources ;

– des variables qui permettent de fixer des chemins, des noms d’exécutable etc...

6

5.3 Description du fichier Makefile

On écrit un fichier Makefile en plaçant d’abord les variables générales. Les dépendances de

l’exécutable suivent ensuite avec l’action associée. Si ce n’est pas le cas, vous devrez spécifier le

nom du programme a générer comme parametre de la commande make. On termine enfin le

fichier en déclarant toutes les autres dépendances.

Il est conseillé d’utiliser la tabulation lorsqu’on sépare un champs d’un autre. La commande

make gère difficilement les espaces. Le fichier Makefile suivant permet de maintenir le projet

prog :

OBJS=menu.o fichier.o date.o

EXEC=prog

INSTALLDIR=.

LIBS=~/librairie

CC=gcc

prog: $(OBJS)

$(CC) $(OBJS) -o $(EXEC)

date.o: date.c header.h

$(CC) -c date.c

menu.o: menu.c header.h

$(CC) -c menu.c

fichier.o: fichier.c header.h

$(CC) -c fichier.c

install:

cp $(EXEC) $(INSTALLDIR)/prog2

clean:

rm *.o prog

EXEC est une variable contenant le nom de l’exécutable à générer. OBJS est une variable

contenant tous les fichiers objets nécessaires à la construction de prog. Ce qui suit est la liste

des dépendances et les actions associées. Le ou les fichiers qui dépendent d’autres fichiers sont

précédés du caractere :. On peut interpréter de la maniere suivante :

– le fichier prog doit être compilé si on modifie date.c, menu.c ou fichier.c. On peut

indiquer directement les fichiers objets .o car la commande make sait de manière implicite

qu’un fichier .o dépend directement d’un fichier .c. La modification d’un fichier .c lancera

donc automatiquement sa compilation en .o et la compilation de prog par la commande

qui suit cette ligne.

– les fichiers menu.o, fichier.o et date.o dépendent d’une modification de header.h. Si

ce dernier est modifié, une compilation complète pour générer prog sera effectuée.

– Les lignes clean et install ne possèdent pas de dépendances. Seules des actions sont

définies. En faisant make clean, vous supprimerez les fichiers prog et .o.

5.4 Exercices

Créez ce fichier Makefile. Supprimez tous les fichiers objets de votre répertoire et lancez la

commande make. Modifiez les différents fichiers sources et relancez de nouveau make.

7