Académique Documents
Professionnel Documents
Culture Documents
Programmation Système
Langage C / Système UNIX.
2e année Génie Informatique
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 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.
Exemple de Programme
Voici deux programmes, serveur.c et client.c, qui communiquent par deux tubes nommés
cli2serv et serv2cli.
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#define QUESTION "cli2serv"
#define REPONSE "serv2cli"
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);
}
/* 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);
}
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
____________________________________________________________________________
Najib TOUNSI 5
Projet Mini Shell
Najib Tounsi
Squelette initial
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[] */
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