Angelseb Posté(e) le 23 novembre 2004 Partager Posté(e) le 23 novembre 2004 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 Lien vers le commentaire Partager sur d’autres sites More sharing options...
NiTrOuS Posté(e) le 23 novembre 2004 Partager Posté(e) le 23 novembre 2004 T es obligé de passer par un fichier ? Lien vers le commentaire Partager sur d’autres sites More sharing options...
Angelseb Posté(e) le 23 novembre 2004 Auteur Partager Posté(e) le 23 novembre 2004 T es obligé de passer par un fichier ? Ben oui :( C'est l'énoncé de l'exo. Lien vers le commentaire Partager sur d’autres sites More sharing options...
NiTrOuS Posté(e) le 23 novembre 2004 Partager Posté(e) le 23 novembre 2004 Et en utilisant la fonction fseek ca marche pas ? Lien vers le commentaire Partager sur d’autres sites More sharing options...
lorinc Posté(e) le 23 novembre 2004 Partager Posté(e) le 23 novembre 2004 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 More sharing options...
Angelseb Posté(e) le 23 novembre 2004 Auteur Partager Posté(e) le 23 novembre 2004 Et en utilisant la fonction fseek ca marche pas ? J'ai pas essayé. En tout cas, je suis obligé de passer par un processus père et son fils pour réaliser ce programme. Lien vers le commentaire Partager sur d’autres sites More sharing options...
lorinc Posté(e) le 23 novembre 2004 Partager Posté(e) le 23 novembre 2004 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... Lien vers le commentaire Partager sur d’autres sites More sharing options...
Angelseb Posté(e) le 23 novembre 2004 Auteur Partager Posté(e) le 23 novembre 2004 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 Lien vers le commentaire Partager sur d’autres sites More sharing options...
lorinc Posté(e) le 23 novembre 2004 Partager Posté(e) le 23 novembre 2004 j'ai vraiment de la merde dans les yeux : j'ai envoyé une remarque en confondant file et fils... faut que j'aille voir un medecin Lien vers le commentaire Partager sur d’autres sites More sharing options...
Angelseb Posté(e) le 23 novembre 2004 Auteur Partager Posté(e) le 23 novembre 2004 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 More sharing options...
lorinc Posté(e) le 23 novembre 2004 Partager Posté(e) le 23 novembre 2004 non, en fait, dans l'execution du pere, I n'a jamais été mis à 12, puisque c'est dans la partie qui ne s'execute pas par le pere... Lien vers le commentaire Partager sur d’autres sites More sharing options...
Angelseb Posté(e) le 23 novembre 2004 Auteur Partager Posté(e) le 23 novembre 2004 non, en fait, dans l'execution du pere, I n'a jamais été mis à 12, puisque c'est dans la partie qui ne s'execute pas par le pere... oki mais tu n'as pas répondu à toutes mes kestions au-desus stp :-) Lien vers le commentaire Partager sur d’autres sites More sharing options...
fabricer Posté(e) le 23 novembre 2004 Partager Posté(e) le 23 novembre 2004 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 More sharing options...
lorinc Posté(e) le 23 novembre 2004 Partager Posté(e) le 23 novembre 2004 tu as probablement raison. la solution avec les signaux est sans doute la plus jolie. Lien vers le commentaire Partager sur d’autres sites More sharing options...
Angelseb Posté(e) le 24 novembre 2004 Auteur Partager Posté(e) le 24 novembre 2004 tu as probablement raison. la solution avec les signaux est sans doute la plus jolie. 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 Lien vers le commentaire Partager sur d’autres sites More sharing options...
fabricer Posté(e) le 24 novembre 2004 Partager Posté(e) le 24 novembre 2004 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 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" 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 More sharing options...
ouragan Posté(e) le 24 novembre 2004 Partager Posté(e) le 24 novembre 2004 fabrice.roge, tu l'écris quand? ( Je suis sûr qu'il serait excellent ) Lien vers le commentaire Partager sur d’autres sites More sharing options...
fabricer Posté(e) le 24 novembre 2004 Partager Posté(e) le 24 novembre 2004 fabrice.roge, tu l'écris quand? ( Je suis sûr qu'il serait excellent ) 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 Lien vers le commentaire Partager sur d’autres sites More sharing options...
Angelseb Posté(e) le 24 novembre 2004 Auteur Partager Posté(e) le 24 novembre 2004 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" 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 More sharing options...
fabricer Posté(e) le 24 novembre 2004 Partager Posté(e) le 24 novembre 2004 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 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 More sharing options...
lorinc Posté(e) le 24 novembre 2004 Partager Posté(e) le 24 novembre 2004 ben ça peut être un moyen de synchro, même si c'est pas fait pour... nan, je pense que le plus élégant est comme tu le disais avec des signaux. Lien vers le commentaire Partager sur d’autres sites More sharing options...
lorinc Posté(e) le 24 novembre 2004 Partager Posté(e) le 24 novembre 2004 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 ) Lien vers le commentaire Partager sur d’autres sites More sharing options...
Angelseb Posté(e) le 24 novembre 2004 Auteur Partager Posté(e) le 24 novembre 2004 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 ) J'ai testé ton code, ça marche impeccable :) Mais je pense que mon prof va me dire qu'il veut une solution plus simple... 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 More sharing options...
lorinc Posté(e) le 24 novembre 2004 Partager Posté(e) le 24 novembre 2004 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 , soit avec des IPC, etc...) Lien vers le commentaire Partager sur d’autres sites More sharing options...
Angelseb Posté(e) le 24 novembre 2004 Auteur Partager Posté(e) le 24 novembre 2004 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 , 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 More sharing options...
Messages recommandés
Archivé
Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.