Aller au contenu

processus pere et fils qui affiche un morceau de..


Angelseb

Messages recommandés

J'ai un pb que je ne sais pas bien gérer, et déterminer ce qu'il faut que j'utilise.

En fait j'ai un fichier qui contient le message suivant "123456789COUCOULESPETITSAMIS". Je dois écrire deux processus qui affichent alternativement un message lu à partir de ce fichier.

Je vous file la trace de l'exécution :

Hello père; mon message est : 1234

Hello fils; mon message est : 5678

Hello père; mon message est : 9COU

Hello fils; mon message est : COUL

Hello père; mon message est : ESPE

Hello fils; mon message est : TITS

Hello père; mon message est : AMIS

Voici déjà un bout de mon code:

Code :

#include <stdio.h> 

int main(){ 
   char buffer[29],tampon[4],tampon2[4]; 
   int fils,i,k,l,m,n,p,q;
   FILE* file;

   file = fopen("fichier.txt","r"); 

   fgets(buffer,sizeof(buffer),file); 

   printf("le message est : %s et la taille de la chaine est de %d caracteres\n",buffer,strlen(buffer)); 

   fclose(file); 

   k = 0; 
   l = k + 4; 

   p = 4; 
   q = p + 4; 

   if((fils=fork()==0){ 
       m = 0; 
        
       for(i = k; i < l; i++){ 
           tampon[m] = buffer[i]; 
           m++; 
       } 
        
       k = l + 4; 
       l = k + 4; 

       tampon[m]='\0'; 
       printf("Hello pere; mon message est : %s",tampon); 
   } 
   else 
   { 
       n = 0; 

       for(i = p; i < q; i++){ 
           tampon2[n] = buffer[i]; 
           n++; 
       } 
        
       p = q + 4; 
       q = p + 4; 

       tampon[n]='\0'; 
       printf("Hello fils; mon message est : %s",tampon2); 
   } 
       printf("l vaut %d et q vaut %d\n",l,q); 
} 

Ce programme m'affiche pour l'instant :

Hello père; mon message est : 1234

l vaut 12 et q vaut 8

Hello fils; mon message est : 5678

l vaut 4 et q vaut 16

1ère question :

Faut-il utiliser des pipes pour synchroniser le pere et le fils pour qu'entre chaque calcul, l'un affiche sa partie, puis que l'autre processus affiche la sienne et ainsi de suite?

2ème question :

Pourquoi la phrase "l vaut x et q vaut y" s'affiche 2 fois alors qu'elle est située après le if?

PS: dsl d'être si nul :francais:

Lien vers le commentaire
Partager sur d’autres sites

d'une part, où j'ai de la merde dans les yeux, ou tu n'as pas déclaré file en tant que FILE*...

d'autre part, un systeme UNIX n'est pas temps réel, donc tu ne sait pas quand le scheduler va entrer en action. Ce qui veut dire que tu n'as aucune certitude quant-à l'ordre d'execution fils, pere, fils, pere...

Il se peut fortement que le quantum de temps attribué au fils soit suffisant pour qu'il en execute plus (reciproquement, le pere).

il faut donc les synchroniser.

Ici, tu as une ressource partagée (un buffer contenant du texte), tu devrait en toute rigueur proteger cette ressource par un semaphore...

pour ta troisieme question, c'est normal, ce qui est dans le if est executé par un processus, ce qui est dans le else par l'autre, et tout le reste par les deux...

Il ne faut pas oublier que le fork ne fait que dupliquer les segments de code, data, etc... donc chaque processus contient l'integralité du code. A toi de te demerder pour n'en faire executer qu'une partie.

Lien vers le commentaire
Partager sur d’autres sites

EDIT : au temps pour moi, j'ai de la merde dans les yeux, file est déclaré en tant qu'int. ce qui devrait convenir dans la majorité des compilateur, puisqu'étant le même format qu'un pointeur... mais caymal quand même...

Oups désolé! en copiant mon code, j'ai supprimé la ligne du FILE* file...

Voilà c'est rétabli dans le copier coller :chinois:

Lien vers le commentaire
Partager sur d’autres sites

d'une part, où j'ai de la merde dans les yeux, ou tu n'as pas déclaré file en tant que FILE*...

d'autre part, un systeme UNIX n'est pas temps réel, donc tu ne sait pas quand le scheduler va entrer en action. Ce qui veut dire que tu n'as aucune certitude quant-à l'ordre d'execution fils, pere, fils, pere...

Il se peut fortement que le quantum de temps attribué au fils soit suffisant pour qu'il en execute plus (reciproquement, le pere).

il faut donc les synchroniser.

Ici, tu as une ressource partagée (un buffer contenant du texte), tu devrait en toute rigueur proteger cette ressource par un semaphore...

pour ta troisieme question, c'est normal, ce qui est dans le if est executé par un processus, ce qui est dans le else par l'autre, et tout le reste par les deux...

Il ne faut pas oublier que le fork ne fait que dupliquer les segments de code, data, etc... donc chaque processus contient l'integralité du code. A toi de te demerder pour n'en faire executer qu'une partie.

Oki donc pour la synchro, tu me conseilles d'utiliser deux pipes?

Heu, dsl mais qu'est-ce qu'un sémaphore et à quoi cela sert? Si tu as un lien vers un site qui explique cela, je suis preneur :-) (de plus google est mon ami lol).

Le fork duplique donc l'intégralité du code, donc après le processus fils, lorsque le processus père exécute aussi son code, il "repasse" tous les lignes de codes avant et apres le processus fils? C'est pour cela que la valeur l est réinitialisé à 4 au lieu de rester à 12?

Lien vers le commentaire
Partager sur d’autres sites

Il ne faut pas oublier que le fork ne fait que dupliquer les segments de code, data, etc...

euh dans mes souvenirs le segment .text (code si tu préfères) n'est pas dupliqué mais est 'shared' (et marqué read-only), il n'y a que le .data, le .heap (bon pour certains le .heap fait partie du .data mais c plus clair dit comme ça) et le .stack (ainsi que les descripteurs de fichiers) qui sont dupliqués.

D'ailleurs meme le .data et le .heap ne sont pas forcément dupliqués aussitôt, celà peut très bien n'intervenir uniquement lors de la prochaine opération d'écriture dans ces segments (ça peut varier d'une implémentation à une autre). Le fork étant un appel lourd pour le système ça permet d'économiser des ressources.

Sinon pour la synchro il peut utiliser les signaux s'il a déjà vu ça en cours (ou les pipe). Quand à buffer il n'a pas à etre protégé il n'y a que des opérations en lecture dessus, de plus ce n'est pas nécessaire puisque la pile du pere est dupliquée pour l'usage du fils donc les deux manipulent chacun une copie différente du buffer.

Sinon angelseb évites de donner à tes variables des noms du genre tampon et tampon2. tampon_pere et tampon_fils seraient plus adapté, ça a au moins l'avantage pour toi de repérer instantanément dans quelle portion du code (celle du fils ou celle du père) tu te trouves à la relecture.

Enfin pour stocker l'id du fils stp utilise pid_t et pas int. Je sais c normalement la meme chose mais méfies toi il faut très tôt prendre l'habitude de se blinder contre les différences d'implémentations d'un système à un autre en utilisant les outils posix de manière rigoureuse. Si le man de fork() te dit d'utiliser pid_t et pas int c'est qu'il faut le faire de plus ainsi ton code est lisible au premier coup d'oeil car il utilise un typage standard qui est parlant en soit et ne nécessite pas de commentaires superflus.

Lien vers le commentaire
Partager sur d’autres sites

tu as probablement raison. la solution avec les signaux est sans doute la plus jolie. :transpi:

Je viens de demander à mon prof, il m'a dit de ne pas utiliser des pipes mais des ""write". Je n'ai pas compris, cela siginifie-t-il kelke chose pour vous?

Sinon, pour la réinitialisation des variables au début du programme, à cause du fork(), il m'a dit d'utiliser une autre méthode :non:

Lien vers le commentaire
Partager sur d’autres sites

Je viens de demander à mon prof, il m'a dit de ne pas utiliser des pipes mais des ""write". Je n'ai pas compris, cela siginifie-t-il kelke chose pour vous?

Sinon, pour la réinitialisation des variables au début du programme, à cause du fork(), il m'a dit d'utiliser une autre méthode :francais:

Peut être veut il dire que tu peux utiliser un fichier d'échange entre les deux processus pour la synchro. Tu aurais alors un fichier texte qui contiendrait les infos de synchronisation entre les deux processus, et lorsqu'un processus voudrait indiquer à l'autre qu'il a fini son job il écrirait un indicateur jeton quelconque dans ce fichier. Le fichier jouerait un peu le rôle de sémaphore dans ce cas mais bon c pas la meilleur méthode.

M'enfin il a pas l'air bien malin ton prof, c'est quoi cette expression "faire un write" :byebye:

Un conseil oublies ton prof et achètes toi un bon bouquin sur la prog système unix parcequ'avec un prof aussi pédagogue que le tiens c mal barré.

Lien vers le commentaire
Partager sur d’autres sites

fabrice.roge, tu l'écris quand? ( Je suis sûr qu'il serait excellent :mdr: )

:transpi:

Je suis pas sûr d'avoir les compétences pour écrire un bouquin sur la prog système Unix, pour être franc j'en fais très rarement est dans ce cas de figure c'est pour mon plaisir personnel. Mes connaissances remontent surtout à mes études.

Mais merci quand même :eeek2:

Lien vers le commentaire
Partager sur d’autres sites

Peut être veut il dire que tu peux utiliser un fichier d'échange entre les deux processus pour la synchro. Tu aurais alors un fichier texte qui contiendrait les infos de synchronisation entre les deux processus, et lorsqu'un processus voudrait indiquer à l'autre qu'il a fini son job il écrirait un indicateur jeton quelconque dans ce fichier. Le fichier jouerait un peu le rôle de sémaphore dans ce cas mais bon c pas la meilleur méthode.

M'enfin il a pas l'air bien malin ton prof, c'est quoi cette expression "faire un write" :eeek2:

Un conseil oublies ton prof et achètes toi un bon bouquin sur la prog système unix parcequ'avec un prof aussi pédagogue que le tiens c mal barré.

En fait, je crois que j'ai mal compris, un pote m'a dit que c'était peut être de faire un "wait". Dans ce cas là :

#include <wait.h>

...

int status;

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

...

}

else{

wait(&status);

...}

Pour que le père attend le fils. Mais je pense que dans ce cas là, le fils va d'abord afficher chaque ligne où il dit "Hello père" au lieu qu'une fois sur 2, il affiche le bout du mot.

Ensuite, le prof a également parlé de "mutex" pour protéger les variables initialisées en début de code, avant le "if".

Peut être que le prof voulait parler des FIFOs :

FIFOs

Lien vers le commentaire
Partager sur d’autres sites

En fait, je crois que j'ai mal compris, un pote m'a dit que c'était peut être de faire un "wait". Dans ce cas là :

#include <wait.h>

...

int status;

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

...

}

else{

wait(&status);

...}

Pour que le père attend le fils. Mais je pense que dans ce cas là, le fils va d'abord afficher chaque ligne où il dit "Hello père" au lieu qu'une fois sur 2, il affiche le bout du mot.

Ensuite, le prof a également parlé de "mutex" pour protéger les variables initialisées en début de code, avant le "if".

Peut être que le prof voulait parler des FIFOs :

FIFOs

ok pour les mutex si tu veux protéger des données contre les accès concurrents.

Mais je ne vois pas quelles variables tu veux protéger avant ton if puisque le fork a dupliqué le segment de données et la pile du père pour le fils.

A part le fichier fichier.txt lui même si tu fais des écritures dedans , il n'y a aucune donnée qui requiert une quelconque protection.

Mais bon là je vais commencer à douter moi si ton prof continue à te dire de protéger tes données :transpi:

Pour ce qui est du wait il ne te sera d'aucune utilité car cet appel met le père en attente de la terminaison du fils ce qui n'est pas franchement le but ici.

Lien vers le commentaire
Partager sur d’autres sites

bon, j'ai fais un truc en vitesse, chez moi ça marche. C'est pas super propre, mais ça donne une idée de comment on peut ynchroniser des processus a l'aide de signaux :

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>

#define SIZE_BUF sizeof(char)*5

void spsig(int sig)
{
/*
sert uniquement au déblocage
*/
/*
printf("j'ai reçu le signal\n");
*/
}

int main(int argc, char ** argv)
{
pid_t pidfils;
int  k;
char * buf;
/* on suppose que le message contient moins de 24 caracteres */
char message[25];

FILE * fichier;

/* ouverture en lecture seule du fichier contenant le texte */
if ( (fichier=fopen("toto", "r")) == NULL )
{
 printf("erreur ouverture fichier\n");
 exit(1);
}

/* lecture du fichier contenant le texte */
fgets( message, sizeof(message), fichier);

/* on alloue la memoire du buffer */
buf = (char *) malloc(SIZE_BUF);
 

if ( (pidfils=fork() ) == 0)
/*code du fils */
{
 /* on force l'execution du pere, histoire qu'il soit en attente d'un signal */
 sleep(1);
 for (k = 0; k < 3; k++)
 {
 	/* mise en place d'une fonction de reception */
 	signal(SIGUSR1, spsig);
 	/* affichage des caracteres */
 	snprintf(buf, SIZE_BUF, "%s", message + k*8);
 	printf("%s\n", buf);
 	/* envoie du signal pour donner la main au pere */
 	kill(getppid(), SIGUSR1);
 	pause();
 }
 
}
else
/* code du pere */
{
 for (k = 0; k < 3; k++)
 {
 	/* mise en place d'une fonction de reception */
 	signal(SIGUSR1, spsig);
 	pause();
 	/* affichage des caracteres */
 	snprintf(buf, SIZE_BUF, "%s", message + k*8 + 4);
 	printf("%s\n", buf);
 	/* envoie du signal pour donner la main au pere */
 	kill(pidfils, SIGUSR1);
 	
 }
}

return 0;
}

voilou (en esperant ne pas me faire trop taper sur les doigts :keskidit: )

Lien vers le commentaire
Partager sur d’autres sites

bon, j'ai fais un truc en vitesse, chez moi ça marche. C'est pas super propre, mais ça donne une idée de comment on peut ynchroniser des processus a l'aide de signaux :

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>

#define SIZE_BUF sizeof(char)*5

void spsig(int sig)
{
/*
sert uniquement au déblocage
*/
/*
printf("j'ai reçu le signal\n");
*/
}

int main(int argc, char ** argv)
{
pid_t pidfils;
int  k;
char * buf;
/* on suppose que le message contient moins de 24 caracteres */
char message[25];

FILE * fichier;

/* ouverture en lecture seule du fichier contenant le texte */
if ( (fichier=fopen("toto", "r")) == NULL )
{
 printf("erreur ouverture fichier\n");
 exit(1);
}

/* lecture du fichier contenant le texte */
fgets( message, sizeof(message), fichier);

/* on alloue la memoire du buffer */
buf = (char *) malloc(SIZE_BUF);
 

if ( (pidfils=fork() ) == 0)
/*code du fils */
{
 /* on force l'execution du pere, histoire qu'il soit en attente d'un signal */
 sleep(1);
 for (k = 0; k < 3; k++)
 {
 	/* mise en place d'une fonction de reception */
 	signal(SIGUSR1, spsig);
 	/* affichage des caracteres */
 	snprintf(buf, SIZE_BUF, "%s", message + k*8);
 	printf("%s\n", buf);
 	/* envoie du signal pour donner la main au pere */
 	kill(getppid(), SIGUSR1);
 	pause();
 }
 
}
else
/* code du pere */
{
 for (k = 0; k < 3; k++)
 {
 	/* mise en place d'une fonction de reception */
 	signal(SIGUSR1, spsig);
 	pause();
 	/* affichage des caracteres */
 	snprintf(buf, SIZE_BUF, "%s", message + k*8 + 4);
 	printf("%s\n", buf);
 	/* envoie du signal pour donner la main au pere */
 	kill(pidfils, SIGUSR1);
 	
 }
}

return 0;
}

voilou (en esperant ne pas me faire trop taper sur les doigts :mdr: )

J'ai testé ton code, ça marche impeccable :)

Mais je pense que mon prof va me dire qu'il veut une solution plus simple... :mdr:

En fait j'ai trouvé les cours de gestion de fichier qu'il nous a fait. Il utilise des fonctions assez basiques comme open, read et write (bas niveau). Il y aussi la fonction lseek pour repositionner le pointeur, avec les paramètres seek_set (déplacement à partir du début), seek_cur (déplacement à partir de la valeur courante) et seek_end (déplacement à partir de la fin).

Je pense qu'il veut qu'on utilise tout ça. Pensez-vous que cela soit possible avec ces fonctions?

Lien vers le commentaire
Partager sur d’autres sites

ben comme je l'ai dit la premiere fois, sur un systeme UNIX, tu n'es pas sûr du moment où le scheduler entre en action, donc il faut synchroniser les deux processus d'une maniere ou d'une autre... (soit avec des signaux, soit avec un sleep(5) entre chque lecture :mdr: , soit avec des IPC, etc...)

Lien vers le commentaire
Partager sur d’autres sites

ben comme je l'ai dit la premiere fois, sur un systeme UNIX, tu n'es pas sûr du moment où le scheduler entre en action, donc il faut synchroniser les deux processus d'une maniere ou d'une autre... (soit avec des signaux, soit avec un sleep(5) entre chque lecture :francais: , soit avec des IPC, etc...)

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!

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...