Vous êtes sur la page 1sur 7

TRAVAUX PRATIQUES

Programmation Système
Langage C / Système UNIX.
2e année Génie Informatique

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()
{
/*
* communication PERE --> FILS par pipe
*/
int p[2];
int pipe(int[2]);
if (pipe(p) == -1) {
fprintf(stderr, "erreur ouverture pipe\n");
exit(1);
}
if (fork() == 0){ /* fils */
char c;
close(p[1]);
while (read(p[0], &c, 1) != 0)
printf("%c", c);
close(p[0]);
exit(0);
}
else { /* suite pere */
close(p[0]);
write(p[1], message, 24);
close(p[1]);
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
____________________________________________________________________________
Najib TOUNSI 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);
}
for (i = 0; i < 3; i++)
switch (fork()) {
case 0: (*tab_fonct[i]) ();
exit(0);
default:;
}
exit(0);
}

void f1() { void f2() {


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

void f3(){
char s[5];
int nb_lu;
close(p[1]);
while ((nb_lu = read(p[0], s, 4)) > 0)
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.

____________________________________________________________________________
Najib TOUNSI 2
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
Le programme client.c envoie une requête de type a + b, dans le tube cli2serv, et le programme
serveur.c lui
retourne la réponse dans le tube serv2cli. C'est le programme serveur.c qui crée les tubes (désignés par
les
variables QUESTION et REPONSE) et qui les supprime en fin d'exécution. Il doit donc être lancé avant le
programme
client qui suppose les tubes existants. Les deux programmes se synchronisent sur l'ouverture des tubes
qui doit se
faire dans le même ordre. L'arrêt de la communication se fait quand le programme client envoi le
message bye; le
serveur répond alors par ciao.
programme serveur.c
% cat serveur.c
/* Serveur: retourne resultat (requete a+b)
* Cree les fifos cli2serv et serv2cli
* LANCER LE SERVEUR D'ABORD (car il ecrase fifos)
*/

#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 */
____________________________________________________________________________
Najib TOUNSI 3
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.
* arret question = "Ciao"
*/

while (1) {
read(fdq, quest, 10);
sscanf(quest, "%d%1s%d", &opd1, &opr, &opd2);
if (strcmp(quest, "Ciao") == 0) {
strcpy(rep, "Bye");
write(fdr, rep, 10);
break;
}
res = opd1 + opd2;
sprintf(rep, "%d", res);
write(fdr, rep, 10);
}
}

programme client.c
% cat client.c
/* Client: envoie expressions
* 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);
____________________________________________________________________________
Najib TOUNSI 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"
*/
while (1) {
if (gets(quest) == NULL)
exit(2);
write(fdq, quest, 10);
printf("Client -> %s \n", quest);
read(fdr, rep, 10);
printf("Serveur -> %s \n", rep);
if (strcmp(rep, "Bye") == 0)
break;
}
}

Script d'exécution
% ls cli_serv serv_cli
cli_serv not found
serv_cli not found
% client
Impossible ouvrire fifo cli_serv
Lancer serveur d'abord?

% 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

PS: Bravo et félicitations pour votre patience...

____________________________________________________________________________
Najib TOUNSI 5
Projet Mini Shell
Najib Tounsi
Squelette initial

- Faire le programme suivant:


[tounsi@genux C]$ cat miniShell2.c
#include<stdio.h>
#include<string.h>
#define L 80
#define W 20
char ligne[L];
/* Ligne commande */

char mot[W][L];
/* Les mots de la ligne commande */

void LireLigneCom();
void TraitLigneCom();
int ExecuterCom();

main(){
int pid, i, j, s;
LireLigneCom();
TraitLigneCom();
while (strcmp(mot[0], "logout") != 0) {
s = ExecuterCom();
printf("%d\n", s);
LireLigneCom();
TraitLigneCom();
}
}

void LireLigneCom(){
char prompt[20] = "MiniShell OK>";
printf("%s", prompt);
fgets(ligne, L + 1, stdin); /* gets() deconseillee */
/* On lit une ligne commande de 80 caracteres */
}

void TraitLigneCom(){
/* Selectionne les mots de la ligne commande et
les place dans la tableau mot[] */

sscanf(ligne, "%s", mot[0]);


/* Test: on commence par le 1er mot qui est la commande */
}

int ExecuterCom(){
/* Sera developpe' dans le cadre de ce TP */
int pid, status;
if (strlen(mot[0]) == 0) /* pas de commande */
return 0;
/* On lance un fils qui va executer la commande */
switch (pid = fork()) {
case -1:
return -1; /* pas de fork */
case 0:
if (execlp(mot[0], mot[0], mot[1], NULL) == -1)
____________________________________________________________________________
Najib TOUNSI 6
/* exec echoue */ exit(2) ;
default:
/* le minishell attend la fin de la commande */
if (wait(&status)==-1)
return -1 ;
}
return status/256;
}

/* NB. le NULL dans execlp devra être remplacé par les autres mots de la ligne
commande */
1) Tester le programme sur des fichiers exécutables de votre choix.
2) Développer ce programme pour:
- Tenir compte des paramètres de la commande à exécuter (Remplir le tableau mot[][])
- Lancement de la commande en background (utiliser waitpid() )
- Tenir compte d'un tube entre deux commandes sans paramètres

NB. Faire man execl, man wait, etc ... pour en savoir plus.

____________________________________________________________________________
Najib TOUNSI 7

Vous aimerez peut-être aussi