Vous êtes sur la page 1sur 8

TRAVAUX PRATIQUES PROGRAMMATION

SYSTÈME SOUS C

28 février 2024

ENSEIGNANT : GHISLAIN PANDRY

TI C
E SA
Y/
DR
A N
in P
i s l a
G h

1
PRISE EN MAIN
Communications entre Processus
Communication par tubes.
Exemple 1:
On a deux processus Père/Fils. Le père envoi au fils un message dans un tube. Message envoyé
en bloc et lu caractère par caractère puis imprimé.

#include <unistd.h>
#include <stdio.h>
char message[25] = "Cela provient d'un tube";
main()
{
/*
T I C
* communication PERE --> FILS par pipe
*/
int p[2];

E SA
int pipe(int[2]);
if (pipe(p) == -1) {
fprintf(stderr, "erreur ouverture pipe\n");

Y/
}
exit(1);

if (fork() == 0){ /* fils */

D R
char c;
close(p[1]);

A N
while (read(p[0], &c, 1) != 0)

P
printf("%c", c);
close(p[0]);

in
exit(0);

a
}

h i s l
else { /* suite pere */
close(p[0]);
write(p[1], message, 24);
close(p[1]);

G }
}
exit(0);

Remarquer l'arrêt de read() sur valeur retour nulle. (Réalisé par close(p[1]); dans le processus
père).
Exercice: Faire un programme où ce sont deux fils qui communiquent, l'un écrivain et l'autre lecteur.

Exemple 2:
Considérons maintenant deux écrivains et un lecteur sur le même tube. Deux fils écrivent
respectivement les séquences "ABC...Z" et "abc...z" par blocs de trois caractères, et un
troisième fils lit dans le tube par blocs de 4 caractères.

#include <unistd.h>
#include <stdio.h>
/* Cummunication par pipe
* FILS1 et FILS2 Ecrivains
____________________________________________________________________________
1
* FILS3 lecteur, meme pipe
*/

void f1(), f2(),


f3(); /* les 3 fils */
void (*tab_fonct[3]) () = {f1, f2, f3};
int p[2];
char seq1[27] = "ABCDEFGHIJKILMOPQRSTUVWXYZ";
/* ecrite par FILS1 */
char seq2[27] = "abcdefghijklmnopqrstuvwxyz";
/* ecrite par FILS2 */
main()
{
int i;
int pipe();
if (pipe(p) == -1) {
fprintf(stderr, "erreur ouverture pipe\n");
exit(1);
}

C
for (i = 0; i < 3; i++)
switch (fork()) {
case 0: (*tab_fonct[i]) ();
exit(0);

T I
}
default:;
}
exit(0);

E SA
void f1() {

Y/
void f2() {

R
int i; int i;
close(p[0]); close(p[0]);
for (i = 0; i < 26; i += 3) {
write(p[1], &seq1[i], 3);

N
sleep(3);
D for (i = 0; i < 26; i += 3) {
write(p[1], &seq2[i], 3);
sleep(4);

}
}

PA
close(p[1]);
}
}
close(p[1]);

s l a in void f3(){
char s[5];

h i int nb_lu;
close(p[1]);
while ((nb_lu = read(p[0], s, 4)) > 0)

G }
printf("%s", s);
close(p[0]);
printf("\n");

Les appels sleep() entre chaque écriture des écrivains, sont là pour simuler d'autres traitements des
processus.

____________________________________________________________________________
Communications entre Processus.

Communication par tubes nommés (fifos).

Exemple de Programme

Voici deux programmes, serveur.c et client.c, qui communiquent par deux tubes nommés
cli2serv et serv2cli.

Deux Processus Communicants


Par Tubes nommés

I C
Le programme client.c envoie une requête de type a + b, dans le tube cli2serv, et le programme
lui
T
A
serveur.c
retourne la réponse dans le tube serv2cli. C'est le programme serveur.c qui crée les tubes (désignés par
les

E S
variables QUESTION et REPONSE) et qui les supprime en fin d'exécution. Il doit donc être lancé avant le
programme
/
qui doit se
RY
client qui suppose les tubes existants. Les deux programmes se synchronisent sur l'ouverture des tubes

message bye; le

N
serveur répond alors par ciao. D
faire dans le même ordre. L'arrêt de la communication se fait quand le programme client envoi le

programme serveur.c

PA
in
% cat serveur.c

a
/* Serveur: retourne resultat (requete a+b)

h i s l * Cree les fifos cli2serv et serv2cli


* LANCER LE SERVEUR D'ABORD (car il ecrase fifos)
*/

G #include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#define QUESTION "cli2serv"
#define REPONSE "serv2cli"

void trait(); /* traitement du serveur */

main()
{
int fdq, fdr;
unlink(QUESTION);
unlink(REPONSE);
/* Creation fifos */
if (mkfifo(QUESTION, 0644) == -1 ||
mkfifo(REPONSE, 0644) == -1) {
perror("Impossible creer fifos");
exit(2);
}
/* Attente des ouvertures Clients */
____________________________________________________________________________
fdq = open(QUESTION, O_RDONLY);
fdr = open(REPONSE, O_WRONLY);
trait(fdr, fdq);
close(fdq);
close(fdr);
unlink(QUESTION);
unlink(REPONSE);
exit(0);
}

void trait(fdr, fdq)


int fdr, fdq;
/* fdr et fdq descripteurs reponse/question */
{
int opd1, opd2, res;
char opr;
char quest[11];
char rep[11];

/* traitement serveur
* envoi reponse a question
* a + b venant de client.

T I C
*/
* arret question = "Ciao"

while (1) {

E SA
read(fdq, quest, 10);

Y/
sscanf(quest, "%d%1s%d", &opd1, &opr, &opd2);
if (strcmp(quest, "Ciao") == 0) {
strcpy(rep, "Bye");
write(fdr, rep, 10);
break;
D R
}

A N
res = opd1 + opd2;
sprintf(rep, "%d", res);

}
}

in P
write(fdr, rep, 10);

s l a
programme client.c

i
h
% cat client.c
/* Client: envoie expressions

G */
* Les fifos sont supposes crees
* par le serveur et sont cli2serv
* et serv2cli

#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#define QUESTION "cli2serv"
#define REPONSE "serv2cli"
void trait(); /* traitement client */
main()
{
int fdq, fdr;
fdq = open(QUESTION, O_WRONLY);
if (fdq == -1) {
fprintf(stderr, "Impossible ouvrire fifo %s\n", QUESTION);
fprintf(stderr, "Lancer serveur d\'abord?\n");
exit(2);
____________________________________________________________________________
4
}
fdr = open(REPONSE, O_RDONLY);
if (fdr == -1) {
fprintf(stderr, "Impossible ouvrire fifo %s\n", REPONSE);
fprintf(stderr, "Lancer serveur d\'abord?\n");
exit(2);
}
trait(fdr, fdq);
close(fdq);
close(fdr);
exit(0);
}

void trait(fdr, fdq)


int fdr, fdq;
/* fdr et fdq descripteurs reponse/question */
{
char rep[11];
char quest[10];
/* traitement client
* lecture expression a op b
* dans stdin et ecriture reponse
* dans stdout. Arret rep = "Bye"

T I C
*/
while (1) {
if (gets(quest) == NULL)
exit(2);

E SA
write(fdq, quest, 10);

Y/
printf("Client -> %s \n", quest);
read(fdr, rep, 10);

D
if (strcmp(rep, "Bye") == 0)
break; R
printf("Serveur -> %s \n", rep);

}
}

A N
in P
Script d'exécution
% ls cli_serv serv_cli

a
cli_serv not found

h i s lserv_cli not found


% client
Impossible ouvrire fifo cli_serv
Lancer serveur d'abord?

G % serveur &
[1] 21653

% client
2 +4
Client -> 2 +4
Serveur -> 6
3 + 7
Client -> 3 + 7
Serveur -> 10
Ciao
Client -> Ciao
Serveur -> Bye
[1] + Done serveur
Exercice 1

Écrire un programme qui crée un fils. Le père doit afficher “je suis le père” et le fils doit
afficher “je suis le fils”.

Exercice 2

Écrire un programme qui crée deux fils appelés fils 1 et fils 2. Le père doit afficher “je suis
le père” et le fils 1 doit afficher “je suis le fils 1”, et le fils 2 doit afficher “je suis le fils 2”.

Exercice 3

Écrire un programme qui crée 5 fils en utilisant une boucle for. On remarquera que pour que

fils.

TI C
le fils ne crée pas lui-même plusieurs fils, il faut interrompre la boucle par un break dans le

Exercice 4

E SA
Écrire un programme avec un processus père qui engendre 5 fils dans une bouble for. Les fils

suis le fils 2, et ainsi de suite.


Y/
sont nommés fils 1 à fils 5. Le fils 1 doit afficher “je suis le fils 1” et le fils 2 doit afficher je

R
Indication. on pourra utiliser une variable globale.

D
Exercice 5

A N
P
Écrire un programme qui crée deux fils appelés fils 1 et fils 2. Chaque fils doit attendre
un nombre de secondes aléatoire entre 1 et 10, en utilisant la fonction sleep. Le programme

in
attend que le fils le plus long se termine et affiche la durée totale. On pourra utiliser la fonction

i s l a
time de la bibliothèque time.h, qui retourne le nombre de secondes depuis le premier janvier
1970 à 0h (en temps universel).

G hExercice 6

Écrire un programme qui crée deux processus. Le processus père ouvre un fichier texte
en lecture. On suppose que le fichier est composé de mots formés de caractères alphabétiques
séparés par des espaces. Le processus fils saisit un mot au clavier. Le processus père recherche
le mot dans le fichier, et transmet au fils la valeur 1 si le mot est dans le fichier, et 0 sinon.
Le fils affiche le résultat.

Exercice 7

Écrire un programme qui crée un tube, crée un processus fils, puis, dans le fils, lance
par execv un autre programme, appelé programme fils. Le programme père transmets les
descripteurs de tubes au programmes fils en argument, et transmet un message au fils par le
tube. Le programme fils affiche le message.

Page 7
Exercice 8

Le but est de faire communiquer deux processus entre eux en utilisant les tubes anonymes.
Écrire un programme dans lequel :
— Le processus père crée un processus fils et lui envoie un message.
— Le processus fils lit le message et ensuite répond au processus père.
— Le processus père attend la réponse de son fils avant de se terminer.

Exercice 9

Le but est de faire communiquer le processus père avec ces deux processus fils.
1. Écrire un programme dans lequel :

I C
1. le processus père crée deux processus fils « pid1 » et « pid2 » et ensuite écrit dans

T
un tube les 26 lettres de l’alphabet (chaque lettre minuscule est suivie de la même
lettre majuscule : aAbBcC. . ..).

SA
2. les processus fils lisent les lettres une à une ensuite les affichent.

E
Y/
2. Modifier le programme pour synchroniser la lecture des processus fils.
1. Le processus fils « pid1 » lit les lettres minuscules.

R
2. Le processus fils « pid2 » lit les lettres majuscules.

D
A N
in P
i s l a
G h

Page 8

Vous aimerez peut-être aussi