Vous êtes sur la page 1sur 3

DMI Génie Logiciel - S5

C OURS DU S YST ÈME E MBARQU É ET T EMPS R ÉEL


Série de TD/TP N°1

Exercice 1 (Script Shell)


Pratiquer les bases de l’écriture de scripts shell
1. Écrire un programme shell qui affiche les arguments du programme, dans l’ordre d’apparition (1er argument en pre-
mier). Si le programme n’a aucun argument, afficher ”sans argument”
2. Écrire un programme shell qui affiche ligne par ligne le contenu d’un fichier dont le nom est fourni en paramètre.
3. Écrire un programme shell qui affiche tous les sous-répertoires du répertoire courant, en utilisant une boucle.
4. Que fait le programme shell suivant (remplacez les ’...’ par le texte adéquat) ?
#!/bin/sh
w=‘who | grep $1‘
if [ -z "$w" ]; then echo "$1 n’est pas ..."; fi
5. Les conditionnelles imbriquées
(a) Écrire un programme shell qui accepte 2 paramètres. Le premier paramètre est +r, -r, +w ou -w, et le deuxième
paramètre spécifie une extension de nom de fichiers. En fonction de la valeur du premier paramètre, le programme
modifiera les droits du groupe de tous les fichiers du répertoire courant dont l’extension est égale au deuxième
paramètre. Pour contrôle, avant chaque modification des droits sur un fichier, le programme affichera le nom du
fichier.
Exemple d’utilisation(le script s’appelle droitsfichiers) :
droitsfichiers +r .html
(b) Proposez une nouvelle version de ce programme capable d’accepter trois paramètres. Les trois paramètres spécifient
alors :
i. le répertoire dans lequel sont contenus les fichiers dont les droits seront modifiés,
ii. les modifications des droits pour le groupe,
iii. l’extension des fichiers concernés.
Exemple d’utilisation(le script s’appelle droitsfichiers) :
droitsfichiers .. -w .dat
droitsfichiers perso -r .txt
6. On voudrait écrire un script permettant de facilement changer de façon systématique l’extension d’une série de fichiers.
On souhaite par exemple renommer tous les fichiers .htm du répertoire courant en .html

Exercice 2 (Gestion des processus)


Manipuler des processus en langage C :
1. Création et synchronisation de processus fils
(a) Ecrire un programme C qui crée deux fils, l’un affichant les entiers de 1 à 50, l’autre de 51 à 100.
(b) Modifier le programme précédent pour que l’affichage soit 1 2 3 ...100.
2. Ecrire un programme C permettant de lancer la commande passée en argument.
Exemples d’exécution :
monexec ls -l /etc/httpd/conf.d/
total 36
-rw-r--r-- 1 root root 3424 Sep 2 2002 auth pgsql.conf
-rw-r--r-- 1 root root 814 Sep 3 2002 perl.conf
-rw-r--r-- 1 root root 459 Sep 3 2002 php.conf
-rw-r--r-- 1 root root 988 Sep 2 2002 python.conf
-rw-r--r-- 1 root root 180 Sep 4 2002 README
-rw-r--r-- 1 root root 251 Aug 6 2002 squirrelmail.conf
-rw-r--r-- 1 root root 11140 Sep 4 2002 ssl.conf

monexec echo a b

1
DMI Génie Logiciel - S5

a b
monexec
Usage: monexec commande [arg] [arg] ?
monexec toto titi
execvp: No such file or directory
3. Simultanéité vs. séquentialité
(a) Ecrire un programme C équivalent à la commande shell suivante :
who & ps & ls -l
(b) Ecrire un programme C équivalent à la commande shell suivante :
who ; ps ; ls -l

Exercice 3 (Gestion des threads)


Manipuler des threads en langage C :
1. Création et attente de threads. Écrivez un programme ayant le comportement suivant :
(a) Des threads sont créés (leur nombre étant passé en paramètre lors du lancement du programme) ;
(b) Chaque thread affiche un message (par example ”Hello World !”) ;
(c) Le thread ”principal” attend la terminaison des différents thread créés.
2. Identification des threads
(a) Modifiez le programme de la question précédente pour que chaque thread affiche :
son PID (avec getpid()) ;
La valeur opaque retournée par pthread self, par exemple avec :
printf("%p\n", (void *) pthread self());

Exercice 4 (EX/Cond/BFR/LF)
Passage des paramètre et exclusion mutuelle
1. Modifiez le programme de la question précédente pour passer son numéro d’ordre à chaque thread. Chaque thread doit
ensuite l’afficher. Vérifiez que le numéro d’ordre affiché par chaque thread est bien différent.
2. Déclarez une variable globale somme initialisée à 0. Chaque thread doit, dans une boucle, ajouter 1 000 000 fois son
numéro d’ordre à cette variable globale (on veut bien faire 1 000 000 additions par thread, pas juste une). Affichez la
valeur obtenue après la terminaison de tous les threads.
3. Avec 5 threads (numérotés de 0 à 4), on devrait obtenir (0+1+2+3+4)*1 000 000 = 10 000 000. Corrigez votre pro-
gramme s’il n’affiche pas systématiquement ce résultat.
4. Modifiez votre programme pour ne plus utiliser de variables globales. Il faut donc passer les adresses des différentes
variables nécessaires en argument en thread , dans une structure.

Exercice 5 (Communication inter processus - Pipes)


Communication par tubes (Pipe)
Travail à effectuer : Rappelons que la fonction read sur l’extrémité d’un pipe est bloquante jusqu’à ce que l’autre extrémité
soit fermée à l’aide d’un close. Soit le programme suivant :
# include < s t d i o . h>
# include < u n i s t d . h>
# include <c t y p e . h>
i n t main ( void )
{
char c ;
i n t fd [ 2 ] ;
pipe ( fd ) ;
i f (! fork ( ) )
{
w h i l e ( r e a d ( 0 , &c , 1) >0)
w r i t e ( f d [ 1 ] , &c , 1 ) ;
f p r i n t f ( s t d e r r , ” e c r i v a i n f i n \n ” ) ;
DMI Génie Logiciel - S5

}
else
{
close ( fd [ 1 ] ) ;
w h i l e ( r e a d ( f d [ 0 ] , &c , 1) >0)
{
c = toupper ( c ) ;
sleep (1);
w r i t e ( 1 , &c , 1 ) ;
}
f p r i n t f ( s t d e r r , ” l e c t e u r f i n \n ” ) ;
}
return 0;
}

1. Lisez et comprenez le code. Lancez le programme et testez-le en tapant une chaı̂ne de caractères suivie de  Return 
puis de  Control − d  (marque de fin de fichier sous UNIX : l’utilisateur ferme le flux de lecture de l’interpréteur).
Que se passe-t-il lorsqu’on enlève la ligne close(fd[1]) ? Pourquoi ?
2. Faites en sorte que le père soit l’écrivain.
3. Remplacez le code du lecteur (lignes 18 à 24) par un appel à execl. Vous écrirez pour cela un petit programme
indépendant qui jouera le rôle de ce lecteur.

Remarque :même après un appel à exec, les numéros des descripteurs de fichiers font toujours référence aux mêmes fichiers.

Exercice 6 (Communication inter processus - Signaux)


Envoi et réception de signaux entre processus
Travail à effectuer : Le but de cet exercice est de mettre en pratique le mécanisme d’envoi de signaux entre processus dans
Unix. Reprendre le cours et regarder dans le manuel les spécifications des fonctions signal() et kill() de manipulation des
signaux.
1. Ecrire le programme ci-dessous et faites le tourner. Le signal SIGINT correspond à l’interruption du terminal (CTRL-
C). Son action par défaut est la terminaison.
# i n c l u d e < s t d i o . h>
# i n c l u d e < s i g n a l . h>
v o i d handINT ( i n t s i g n o ) {
s i g n a l ( SIGINT , handINT ) ;
p r i n t f ( ” r e c e p t i o n d ’ un s i g n a l SIGINT\ n ” ) ;
}
v o i d main ( ) {
s i g n a l ( SIGINT , handINT ) ;
p r i n t f ( ” p r o c e s s u s : %d \n ” , g e t p i d ( ) ) ;
while (1) ;
}

2. Ecrire un programme C dont le comportement est une boucle infinie et qui écrit à l’écran ” BONJOUR ” lorsqu’il
reçoit le signal SIGUSR1 et ” BONSOIR ” lorsqu’il reçoit le signal SIGUSR2. Ce programme ne doit réagir qu’une
seule fois au signal SIGUSR1. Par contre il doit réagir autant de fois que le signal SIGUSR2 lui arrive.

Indice : Regarder la fonction pause() dans le manuel. Attention l’action par défaut des signaux SIGUSR1 et SIGUSR2
est la terminaison.
3. Ecrire un programme dans lequel un processus crée un fils et initialise un handler (afficher ” BONJOUR ”) sur
SIGUSR1. Le fils affiche des informations à l’écran puis envoie le signal SIGUSR1 à son père. Attention le programme
fils doit se terminer avant le processus père.

Exercice 7 (Communication inter processus - Sockets)

Voir le DL Numéro 1

Vous aimerez peut-être aussi