A voir également:
- Synchronisation entre processus peres et fils
- Synchroniser agenda google et outlook - Guide
- Processus hôte windows (rundll32) ✓ - Forum Windows
- Branchement prise téléphone adsl 4 fils ✓ - Forum câblage
- A quoi servent les 8 fils rj45 - Forum câblage
- Schéma branchement autoradio couleur fils ✓ - Forum Autoradio
3 réponses
kilian
Messages postés
8731
Date d'inscription
vendredi 19 septembre 2003
Statut
Modérateur
Dernière intervention
20 août 2016
1 526
16 févr. 2009 à 00:37
16 févr. 2009 à 00:37
Salut,
Fondamentalement, le gros problème c'est ta boucle infinie avec pause().
En fait les main() de Bob et Charlie ont un soucis:
Ca donnes: tu ouvres le fichier, installe ton handler de signal puis tu compares avec 0 une valeur d'un tableau qui n'a jamais été initialisé.
Enfin tu tournes dans une boucle infinie.
Dans cette boucle, tu dors une première fois. Tu reçois SIGUSR1, donc tu te réveilles et tu vas dans lect(), ici ton handler n'est plus attaché à ce signal (utilise sigaction pour installer un handler persistant), ensuite tu retournes en boucle dans un pause() continuel qui fera que tu dormiras, tu va te réveiller, tu dormiras.... etc.. d'ou l'interblocage.
Ya aussi des petits trucs dangeureux:
Là tu débordes largement dans la mémoire :-)
Fondamentalement, le gros problème c'est ta boucle infinie avec pause().
En fait les main() de Bob et Charlie ont un soucis:
int main(void) { //ouverture d'un pipe en lecture p1=open("pipe",O_RDONLY); if (p1==-1) erreur("pb d'ouverture en lecture\n"); // on se prepare au signal signal(SIGUSR1,lect); // on verifie si le signal de fin a ete envoyé char fin; fin='!'; if (strcmp(&tab[10][i],&fin)==0) envoyer(); // on attend le signal for(;;) { pause(); } }
Ca donnes: tu ouvres le fichier, installe ton handler de signal puis tu compares avec 0 une valeur d'un tableau qui n'a jamais été initialisé.
Enfin tu tournes dans une boucle infinie.
Dans cette boucle, tu dors une première fois. Tu reçois SIGUSR1, donc tu te réveilles et tu vas dans lect(), ici ton handler n'est plus attaché à ce signal (utilise sigaction pour installer un handler persistant), ensuite tu retournes en boucle dans un pause() continuel qui fera que tu dormiras, tu va te réveiller, tu dormiras.... etc.. d'ou l'interblocage.
Ya aussi des petits trucs dangeureux:
// on envoie le message de fin de l'ecriture qui est "!" char fin; fin='!'; write(p1,&fin,sizeof(car));
Là tu débordes largement dans la mémoire :-)
Simplement quelques remarques à ajouter:
1) Pourquoi 2 programmes 'bob' et 'charly'? Ils font la même chose (du moins je n'y vois pas de différence; il faut dire qu'avec leur programme non indenté, j'ai bien du mal à lire... quand ça ne me décourage pas!). De toute façon on peut, lors du lancement, envoyer un paramètre différent à l'un et à l'autre.
2) On traite les erreurs du style 'if (p1==-1) erreur("pb d'ouverture en ...ture\n");'... mais pas complètement puisqu'on va continuer à lire ou à écrire dans ce fichier .
3) Dans le traitement de la fonction 'lect', tu fermes le pipe à la fin, donc quand tu reviendras dans cette fonction pour un autre 'read'... problème assuré! Et puis il y a un autre problème caché qui va survenir dès que la fonction 'lect' aura été exécutée dans les 2 programmes (bot et charly)... suspense... quel est le problème caché? Et bien le pipe n'aura plus d'extrémité d'ouverte en lecture et, par conséquent, l'extrémité en écriture sera bloquée (à moins de l'ouvrir en mode O_NONBLOCK, ce qui n'est pas le cas) et 'arnaud' ne peut plus écrire.
4) Mais on en sort comment des programmes 'fils'; il faut lâchement les tuer! Pas très correct. Bon d'accord il s'agit d'un exercice.
5) Si la fonction 'envoyer' n'a pas été appelée dans les conditions douteuses indiquées par kilian, elle ne le sera plus jamais; en effet, une fois dans la boucle infinie, on ne reviendra pas en arrière.
Bon j'arrête et bon courage pour tout ce qu'il reste à faire.
1) Pourquoi 2 programmes 'bob' et 'charly'? Ils font la même chose (du moins je n'y vois pas de différence; il faut dire qu'avec leur programme non indenté, j'ai bien du mal à lire... quand ça ne me décourage pas!). De toute façon on peut, lors du lancement, envoyer un paramètre différent à l'un et à l'autre.
2) On traite les erreurs du style 'if (p1==-1) erreur("pb d'ouverture en ...ture\n");'... mais pas complètement puisqu'on va continuer à lire ou à écrire dans ce fichier .
3) Dans le traitement de la fonction 'lect', tu fermes le pipe à la fin, donc quand tu reviendras dans cette fonction pour un autre 'read'... problème assuré! Et puis il y a un autre problème caché qui va survenir dès que la fonction 'lect' aura été exécutée dans les 2 programmes (bot et charly)... suspense... quel est le problème caché? Et bien le pipe n'aura plus d'extrémité d'ouverte en lecture et, par conséquent, l'extrémité en écriture sera bloquée (à moins de l'ouvrir en mode O_NONBLOCK, ce qui n'est pas le cas) et 'arnaud' ne peut plus écrire.
4) Mais on en sort comment des programmes 'fils'; il faut lâchement les tuer! Pas très correct. Bon d'accord il s'agit d'un exercice.
5) Si la fonction 'envoyer' n'a pas été appelée dans les conditions douteuses indiquées par kilian, elle ne le sera plus jamais; en effet, une fois dans la boucle infinie, on ne reviendra pas en arrière.
Bon j'arrête et bon courage pour tout ce qu'il reste à faire.
Merci de vos conseils !
Effectivement la difference entre Bob et Charlie est minime... masi c'était juste pour essayer de travailler avec 2 processus "freres"
Je ne comprneds pas bien vos remarque sur la boucle infinie : est ce que la fonction signal(SIGUSR1,lect) n'est "valable" qu'une seule fois et qu'ensuite, quand je recois un deuxième signal je ne vais pas a la fonction lect() ? (mais alors si je ne suis plus préparé au signal ,, le fils devrait mourir ??) enfin bref, je n'ai pas tres vbien compris quel ets le probleme de la boucle infinie : est ce que je recois les signaux ou non ?
merci encore (et désolé pour l'indentation.... le copier/coller me l'a supprimé)
Effectivement la difference entre Bob et Charlie est minime... masi c'était juste pour essayer de travailler avec 2 processus "freres"
Je ne comprneds pas bien vos remarque sur la boucle infinie : est ce que la fonction signal(SIGUSR1,lect) n'est "valable" qu'une seule fois et qu'ensuite, quand je recois un deuxième signal je ne vais pas a la fonction lect() ? (mais alors si je ne suis plus préparé au signal ,, le fils devrait mourir ??) enfin bref, je n'ai pas tres vbien compris quel ets le probleme de la boucle infinie : est ce que je recois les signaux ou non ?
merci encore (et désolé pour l'indentation.... le copier/coller me l'a supprimé)
Non, ce n'est pas le copier-coller qui a supprimé les indentations, mais c'est que tu n'as pas utilisé les balises <codes> (il y a les balises Gras Italique Souligne Code Lien).
Une fois dans ta boucle infinie, à chaque signal reçu tu iras exécuter le sous-programme prévu par le signal (soit lect) mais ensuite tu reviendras dans ta boucle infinie.
Comme l'a dit kilian, le comportement classique de signal est qu'une fois exécuté, le handler original est remis, ce qui n'est pas vrai sous Linux; le comportement est donc différent suivant le système d'exploitation et c'est pour cela qu'il a indiqué qu'il valait mieux utiliser 'sigaction' qui garantit, dans la norme, que le handler restera installé.
Quant aux deux processus frères, on peut très bien lancer deux fois le même programme!
Une fois dans ta boucle infinie, à chaque signal reçu tu iras exécuter le sous-programme prévu par le signal (soit lect) mais ensuite tu reviendras dans ta boucle infinie.
Comme l'a dit kilian, le comportement classique de signal est qu'une fois exécuté, le handler original est remis, ce qui n'est pas vrai sous Linux; le comportement est donc différent suivant le système d'exploitation et c'est pour cela qu'il a indiqué qu'il valait mieux utiliser 'sigaction' qui garantit, dans la norme, que le handler restera installé.
Quant aux deux processus frères, on peut très bien lancer deux fois le même programme!
Heu, j'ai oublié de répondre à la question:
mais alors si je ne suis plus préparé au signal ,, le fils devrait mourir ??
Non il n'y a aucune raison; quand tu n'es plus préparé au signal comme tu dis, cela signifie que le signal qui te serait envoyé n'arriverait pas , c'est tout, et qu'en conséquence, ton programme continue normalement... dans ta boucle!
Ceci dit même après réception d'un signal, tu resteras préparé parce que tu es sous Linux mais ce n'est pas certain sous un autre SE (donc vaut mieux utiliser 'sigaction').
mais alors si je ne suis plus préparé au signal ,, le fils devrait mourir ??
Non il n'y a aucune raison; quand tu n'es plus préparé au signal comme tu dis, cela signifie que le signal qui te serait envoyé n'arriverait pas , c'est tout, et qu'en conséquence, ton programme continue normalement... dans ta boucle!
Ceci dit même après réception d'un signal, tu resteras préparé parce que tu es sous Linux mais ce n'est pas certain sous un autre SE (donc vaut mieux utiliser 'sigaction').