Aller au contenu

processus pere et fils qui affiche un morceau de..


Angelseb

Messages recommandés

Pour la synchro, je pense qu'il veut pas se casser la tête, à mon avis un truc moche comme sleep fera l'affaire (le connaissant).

J'ai essayé de commencer un autre prog C avec lseek:

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>

int main(){
char tampon[4],tampon2[4];
int fils,file;

file = open("fichier.txt",O_RDONLY);

lseek(file,0,SEEK_SET);

if((fils=fork()==0){
 
 for(i = 0; i < 4; i++){
 	lseek(file,i*8,SEEK_CUR);
 	read(file,tampon,4);
 	printf("Hello pere; mon message est :  %s\n", tampon);
 	sleep(2);
 }
}
else
{
 for(i = 0; i < 3; i++){
 	lseek(file,i*8+4,SEEK_CUR);
 	read(file,tampon2,4);
 	printf("Hello fils; mon message est :  %s\n", tampon2);
 	sleep(2);  
 }
 
 
}
close(file);
}

Alors déjà, c'est "synchonisé" (à la façon de mon prof lol). Par contre j'affiche des bêtises à chaque ligne, apparemment je n'ai pas réussi à lire les 4 caractères :-(.

En tout cas, on approche!

angelseb,

si tu ne peux pas utiliser l'example utilisant les signaux comme le montre l'excellent example de lorinc alors il faut que tu comprenne bien ce que signifie synchroniser:

1 - rendre prédictif ce qui ne l'est pas

2 - rendre ordonnancé ce qui ne l'est pas

en clair et en décodé :

1 - pouvoir décider d'une manière ou d'une autre qui du père ou qui du fils va commencer à afficher son bout de chaîne

2 - définir de manière controlée l'ordre dans lequel le père et le fils vont alterner leur exécution.

Donc pour en revenir à la proposition donnée par ton prof :

1 - tu va utiliser ton fichier pour inclure une sorte de mutex (à la fin du fichier après la chaîne à afficher)

2 - ce mutex va être constitué d'un entier écrit dans le fichier qui définit quel est le prochain processus à afficher son bout de chaîne, example:

1 pour le père

2 pour le fils

Pour rendre prédictif l'ordre dans lequel va démarrer l'ordonnancement tu initialise avant même l'exécution du programme cette valeur à 1 par example (pour que le père commence)

3 - chacun des processus va lire à la fin du fichier (tu fais un seek pour te positionner au bon endroit lors de la lecture)

4 - si le père lit 1 il continue son parcours de la boucle

5 - si le fils lit 2 c'est lui qui doit continuer

6 - chaque test du mutex est fait en début de la boucle for qui gère l'affichage

7 - la boucle for doit se terminer par un sleep (200 millisecondes par example) afin de ne pas saturer le processeur

8 - à l'intérieur du for si un processus détecte que ce n'est pas à lui de s'exécuter il passe aussitôt au sleep (tu gère ça avec un if )

9 - lorsque l'un des processus à affiché son bout de chaîne il écrit à la fin du fichier texte (utilise le seek pour écrire au bon endroit) la valeur qui déclenchera l'affichage de la chaîne de l'autre processus:

A le fils vient d'afficher donc il écrit 1 (pour relancer le père)

B le père vient d'afficher donc il écrit 2 (pour relancer le fils)

Voilà en gros celà revient au même que d'utiliser les signaux sauf que en réalité le signal est transmis sous forme d'un entier dans le fichier texte. Donc le code qui attent l'arrivée du signal est en fait remplacer par la lecture du mutex dans le fichier texte et l'analyse de sa valeur.

voilà au moins celà rend ton programme prédictif car tu décides par l'initialisation du mutex dans le fichier qui du père ou du fils affiche sa chaîne en premier, et ensuite par l'alternance des valeurs du mutex tu définis à qui c'est le tour donc tu créé un ordonnancement.

Tout celà en n'utilisant uniquement la gestion de fichier.

Dis moi j'ai été suffisament clair.

Lien vers le commentaire
Partager sur d’autres sites

Merci de toutes tes précisions. En ce moment j'ai des pbs de santé (je viens d'aller chez le doc, juste 10 de tension), je ralentis mes recherches. J'ai tapé un peu vite fait (et surement comme d'hab la moitié ce sont des bêtises) d'après ce que tu m'as dis.

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>

int main(){
char tampon[4],tampon2[4];
int fils,file;
char test;

/*ouverture du fichier en lecture/écriture
file = open("fichier.txt",O_RDWR);

if((fils=fork())==0){
 for(i = 0; i < 4; i++){
 	lseek(file,0,SEEK_END);	/*je place le pointeur du fichier à la fin du fichier*/
 	read(file,test,1);	/*je lis le caractère (1 ou 2) qui m'indique si c'est au tour du père ou du fils d'exécuter l'affichage de la chaine*/
 	if(test=='2'){ /*si la variable test est égale à 2, alors c'est au tour du fils d'afficher*/
   lseek(file,0,SEEK_SET);  /*je replace le pointeur au début du fichier*/
   lseek(file,i*8,SEEK_CUR);	/*je place le pointeur à la bonne position pour lire la chaine*/
   read(file,tampon,4);  /* je lis la chaine de 4 caractères*/
   printf("Hello pere; mon message est :  %s\n", tampon);
   lseek(file,0,SEEK_END);  /*je replace le pointeur en fin de fichier*/
   write(file,"1",1);  /*j'écris à la suite le nouveau chiffre pour le père*/
 	}
 	else{
   sleep(1);
 	}
 }
}
else
{
 for(i = 0; i < 3; i++){
 	lseek(file,0,SEEK_END);
 	read(file,test,1);
 	if(test=='1'){
   lseek(file,0,SEEK_SET);
   lseek(file,i*8+4,SEEK_CUR);
   read(file,tampon2,4);
   printf("Hello fils; mon message est :  %s\n", tampon2);
   lseek(file,0,SEEK_END);
   write(file,"2",1);
 	}
 	else{
   sleep(1);
 	}
 }	
}
close(file);
}

J'ai déjà un problème au niveau de la variable test. J'ai 2 fois ce message d'erreur :

"warning: passing arg 2 of 'read' makes pointer from integer without a cast"

Merci en tout cas pour votre aide, à force de faire autant d'erreurs et avec vos conseils, je vais bien finir par progresser.

Lien vers le commentaire
Partager sur d’autres sites

ssize_t read(int fd, void *buf, size_t count);

donc, il faut que tu donne obligatoirement une adresse (un pointeur) en argument 2, sinon la fonction read aura du mal à écrire à l'adresse que tu lui a donné.

d'autre part, le & ou le 4 est un peu hasardeux en argument 3, il faut être sûr de la taille à lire : sizeof(char)*4 (reciproquement 1)

apres, le reste, j'ai pas tout lu, si tu pouvais éditer entre balises CODE ou QUOTE, histoire d'avoir des indentation, ce serait sympa;)

Lien vers le commentaire
Partager sur d’autres sites

ssize_t read(int fd, void *buf, size_t count);

donc, il faut que tu donne obligatoirement une adresse (un pointeur) en argument 2, sinon la fonction read aura du mal à écrire à l'adresse que tu lui a donné.

d'autre part, le & ou le 4 est un peu hasardeux en argument 3, il faut être sûr de la taille à lire : sizeof(char)*4 (reciproquement 1)

apres, le reste, j'ai pas tout lu, si tu pouvais éditer entre balises CODE ou QUOTE, histoire d'avoir des indentation, ce serait sympa;)

Donner une adresse en argument 2? C'est à dire? Je ne sais plus comment on fait déjà :-( (mon niveau en C est déplorable).

Lien vers le commentaire
Partager sur d’autres sites

oula, reprenont depuis le début.

un pointeur, c'est une adresse de memoire qui peut contenir quelque chose (un entier, un char, plein de trucs...)

quand tu passe un parametre à une fonction, tu recopies sa valeur en pile. Donc si cette valeur est une adresse, la fonction peut faire ce qu'elle veut avec cette adresse : lire son contenu et le modifier.

Alors que si tu passe le contenu en parametre (et donc que l'adresse reste inconue de la fonction), la fonction ne va pas pouvoir modifier le contenu de l'adresse du parametre.

ça devrait te dire des choses, normalement.

je te donne un exemple :


void change(int tmp)
{
   tmp++;
}

int main()
{
  int a = 4;
  change(a);

  printf("%d\n", a);

  return 0;
}

a ton avis, quelle valeur s'affiche à l'écran?

C'est normal, a n'a jamais pu être modifié. a possède une certaine adresse, et son contenu est décris à cette adresse. Puisque tu n'a jamais donné cette adresse nulle part, a n'a pas pu être modifié.

la même avec des pointeurs:

void change(int * tmp)
{
  *tmp=5;

}

int main()
{
   /* le pointeur == l'adresse */
   int * a;
   /* et ce qu'il y a à cette adresse */
  *a = 4;

  change( a );

   printf("%d\n", *a);

   return 0;
}

là, puisqu'on passe l'adresse de notre variable a, on est à même de modifier son contenu.

dans ton code, il faut donc que tu donnes un pointeur vers la zone de memoire qui doit recevoir ce qui est lu...

Lien vers le commentaire
Partager sur d’autres sites

oula, reprenont depuis le début.

un pointeur, c'est une adresse de memoire qui peut contenir quelque chose (un entier, un char, plein de trucs...)

quand tu passe un parametre à une fonction, tu recopies sa valeur en pile. Donc si cette valeur est une adresse, la fonction peut faire ce qu'elle veut avec cette adresse : lire son contenu et le modifier.

Alors que si tu passe le contenu en parametre (et donc que l'adresse reste inconue de la fonction), la fonction ne va pas pouvoir modifier le contenu de l'adresse du parametre.

ça devrait te dire des choses, normalement.

je te donne un exemple :


void change(int tmp)
{
   tmp++;
}

int main()
{
  int a = 4;
  change(a);

  printf("%d\n", a);

  return 0;
}

a ton avis, quelle valeur s'affiche à l'écran?

C'est normal, a n'a jamais pu être modifié. a possède une certaine adresse, et son contenu est décris à cette adresse. Puisque tu n'a jamais donné cette adresse nulle part, a n'a pas pu être modifié.

la même avec des pointeurs:

void change(int * tmp)
{
  *tmp=5;

}

int main()
{
   /* le pointeur == l'adresse */
   int * a;
   /* et ce qu'il y a à cette adresse */
  *a = 4;

  change( a );

   printf("%d\n", *a);

   return 0;
}

là, puisqu'on passe l'adresse de notre variable a, on est à même de modifier son contenu.

dans ton code, il faut donc que tu donnes un pointeur vers la zone de memoire qui doit recevoir ce qui est lu...

J'ai fais selon ce que tu m'as dis mais j'ai tjs les mêmes erreurs:

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>

int main(){
char tampon[4],tampon2[4];
int fils,file;
char * test;

/*ouverture du fichier en lecture/écriture
file = open("fichier.txt",O_RDWR);

if((fils=fork())==0){
 for(i = 0; i < 4; i++){
 	lseek(file,0,SEEK_END);	/*je place le pointeur du fichier à la fin du fichier*/
 	read(file,*test,1);	/*je lis le caractère (1 ou 2) qui m'indique si c'est au tour du père ou du fils d'exécuter l'affichage de la chaine*/
 	if(*test=='2'){ /*si la variable test est égale à 2, alors c'est au tour du fils d'afficher*/
   lseek(file,0,SEEK_SET);  /*je replace le pointeur au début du fichier*/
   lseek(file,i*8,SEEK_CUR);	/*je place le pointeur à la bonne position pour lire la chaine*/
   read(file,tampon,4);  /* je lis la chaine de 4 caractères*/
   printf("Hello pere; mon message est :  %s\n", tampon);
   lseek(file,0,SEEK_END);  /*je replace le pointeur en fin de fichier*/
   write(file,"1",1);  /*j'écris à la suite le nouveau chiffre pour le père*/
 	}
 	else{
   sleep(1);
 	}
 }
}
else
{
 for(i = 0; i < 3; i++){
 	lseek(file,0,SEEK_END);
 	read(file,*test,1);
 	if(*test=='1'){
   lseek(file,0,SEEK_SET);
   lseek(file,i*8+4,SEEK_CUR);
   read(file,tampon2,4);
   printf("Hello fils; mon message est :  %s\n", tampon2);
   lseek(file,0,SEEK_END);
   write(file,"2",1);
 	}
 	else{
   sleep(1);
 	}
 }	
}
close(file);
}

Lien vers le commentaire
Partager sur d’autres sites

Archivé

Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.

×
×
  • Créer...