Communication par signaux entre thread

Communication par signaux entre thread - Programmation

Marsh Posté le 09-04-2002 à 21:49:40    

Bonjour
 
Pour un de mes tp, je dois faire communiquer des threads par des signaux. Cependant, mon tp m'oblige à utiliser le signal SIGCONT. Je m'explique.

Code :
  1. void Fonc_SIG_thread()
  2. {
  3. ...
  4. }
  5. void Fonc_SIG_main()
  6. {
  7. ...
  8. }
  9. void mon_thread()
  10. {
  11. signal(SIGCONT, Fonc_SIG_thread);
  12. ...
  13. kill(getppid(), SIGCONT);
  14. }
  15. void main(void)
  16. {
  17. ...
  18. signal(SIGCONT, Fonct_SIG_main);
  19. pthread tid1 ;
  20. ...
  21. pthread_create(&tid1, NULL, mon_thread, NULL);
  22. kill(&tid, SIGCONT) ;
  23. }


 
Donc en gros, je voudrais savoir si c'est possible d'utiliser une fonction avec SIGCONT du père vers le thread et une autre fonction avec SIGCONT du thread vers le père ?


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 09-04-2002 à 21:49:40   

Reply

Marsh Posté le 09-04-2002 à 22:40:50    

Beuark, quelle horreur, on n'utilise pas de signaux entre threads, ce n'est pas du tout portable, et rien ne dit que ça marchera dans une version prochaine de la glibc.
 
Essaye plutôt de voir du côté des conditions (pthread_cond_init) ou des mutex (pthread_mutex_init).


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 09-04-2002 à 22:52:24    

Je peux utiliser des processus plutot que des threads mais je dois utiliser des SIGNAUX.  
Par contre, comment je peux faire pour choisir quel processus je veux exécuter au moment X. Parce que ce que je dois faire, c'est un genre d'ordonnanceur et il faut donc que j'autorise l'exécution d'un seul processus à la fois et après un quantum de temps, je le mets en attente, je passe au suivant etc...


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 09-04-2002 à 23:00:10    

Matheo a écrit a écrit :

Je peux utiliser des processus plutot que des threads mais je dois utiliser des SIGNAUX.  
Par contre, comment je peux faire pour choisir quel processus je veux exécuter au moment X. Parce que ce que je dois faire, c'est un genre d'ordonnanceur et il faut donc que j'autorise l'exécution d'un seul processus à la fois et après un quantum de temps, je le mets en attente, je passe au suivant etc...


Je vois ça, justement les fonctions de style mutex, sémaphores et conditions des threads, ça sert à ça. Dans l'implémentation LinuxThreads, tout ça est fait à base de signaux, mais c'est assez compliqué (et c'est l'implémentation la plus crade des threads POSIX).
 
Bref, tout ça ne répond pas à ta question. Je pense que le plus simple, c'est de faire avec des bêtes fork. Avant de faire le fork, tu mets bien le pid du père dans une variable avec getpid, comme ça tu peux faire un kill dessus plus tard (ou alors tu utilises getppid). Le fork retournant au père le pid du fils, il peut lui envoyer un signal sans problème.

 

[jfdsdjhfuetppo]--Message édité par Jar Jar--[/jfdsdjhfuetppo]


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 09-04-2002 à 23:03:27    

Matheo a écrit a écrit :

signal(SIGCONT, Fonc_SIG_thread);
...
kill(getppid(), SIGCONT);
}
Donc en gros, je voudrais savoir si c'est possible d'utiliser une fonction avec SIGCONT du père vers le thread et une autre fonction avec SIGCONT du thread vers le père ?  



Tu es dans le même process. Ce n'est pas getppid (c'est bien le père :??: ) dont tu as besoin, mais le pid du process dans lequel tu te trouves.

Reply

Marsh Posté le 09-04-2002 à 23:11:56    

Je pensais que je pouvais éviter d'utiliser des fork() mais j'ai bien peur que ce ne soit pas possible. Il ne me reste plus qu'à me taper pas mal de code pour essayer de trouver un moyen de faire ce foutu tp.
C'est assez le bordel car j'ai des notions de processus, algorithmes de tri, lecture de fichier et répertoire, utilisation de tubes nommées, segment de données et tout ça en temps partagé ! La joie quoi !


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 09-04-2002 à 23:14:36    

Matheo a écrit a écrit :

Je pensais que je pouvais éviter d'utiliser des fork() mais j'ai bien peur que ce ne soit pas possible. Il ne me reste plus qu'à me taper pas mal de code pour essayer de trouver un moyen de faire ce foutu tp.
C'est assez le bordel car j'ai des notions de processus, algorithmes de tri, lecture de fichier et répertoire, utilisation de tubes nommées, segment de données et tout ça en temps partagé ! La joie quoi !


La vache ! C'est pas des TP de tapettes, qu'on vous fait faire ;)
 
En fait, le problème avec les threads et les signaux, c'est que la notion de signal n'a pas lieu d'être pour un thread, vu que dans la norme POSIX tous les threads sont des contextes d'exécution du même processus (avec donc le même pid).
Seule l'implémentation linux déroge à cette règle.


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 09-04-2002 à 23:28:44    

Jar Jar a écrit a écrit :

 
Seule l'implémentation linux déroge à cette règle.  




 
Donc si je suis sous Linux, ça pourrait marcher alors mon affaire de thread ?


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 09-04-2002 à 23:36:58    

Matheo a écrit a écrit :

Donc si je suis sous Linux, ça pourrait marcher alors mon affaire de thread ?


Ça pourrait marcher. Je ne te le conseille vraiment pas, parce que ça peut donner tout et n'importe quoi.
En particulier, rien ne te garantit que le thread que tu as lancé avec pthread_create sera effectivement le fils du premier thread, au sens des getpid...


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 09-04-2002 à 23:43:33    

Ouais c'est vrai ! Je prendrai pas de chance et je vais essayer de faire qqchose avec les fork(). Reste à savoir comment m'amuser à gérer tous les fils en même temps. Parce que de la façon mon TP fait, j'ai au moins 6 processus fils plus le père.
 
Yeah ![:wouaf]


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 09-04-2002 à 23:43:33   

Reply

Marsh Posté le 09-04-2002 à 23:47:33    

Matheo a écrit a écrit :

Ouais c'est vrai ! Je prendrai pas de chance et je vais essayer de faire qqchose avec les fork(). Reste à savoir comment m'amuser à gérer tous les fils en même temps. Parce que de la façon mon TP fait, j'ai au moins 6 processus fils plus le père.


Auquel cas, soit tu t'arranges pour que les fils n'aient pas à communiquer entre eux mais seulement avec le père, soit tu utilises un segment de mémoire partagée, soit tu trouves une sale combine : je me souviens avoir utilisé jadis une cascade de tubes récursive entre fils pour faire remonter les pids jusqu'au père. Ça marchait bien (je rigole rien que de repenser à cette idée).


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 10-04-2002 à 04:35:16    

1) Je vais avoir un nombre de processus variables (entre 2 et 20)à chaque exécution. Comment je fais pour en créer autant que je veux tout en enregistrant leur pid à chaque fois car il faut que je puisse les appeler par la suite ?
 
2) Segment de mémoire partagée ? J'ai de la difficulté à bien saisir ce que ça fait car j'ai rien dans mes notes de cours là-dessus. Quelqu'un a un lien intéressant là-dessus ?
 
Merci.


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 10-04-2002 à 09:55:10    

1) Je vais avoir un nombre de processus variables (entre 2 et 20)à chaque exécution. Comment je fais pour en créer autant que je veux tout en enregistrant leur pid à chaque fois car il faut que je puisse les appeler par la suite ?
 
Bah tu fais une boucle, et tu ranges les pids dans un tableau au fur et à mesure de la création des fils.
 
 
2) Segment de mémoire partagée ? J'ai de la difficulté à bien saisir ce que ça fait car j'ai rien dans mes notes de cours là-dessus. Quelqu'un a un lien intéressant là-dessus ?
 
Regarde du côté de shmget, mais je ne te conseille pas de t'en servir si tu peux faire autrement, parce que c'est vraiment tordu. Ça permet de partager une zone de mémoire entre plusieurs processus.

 

[jfdsdjhfuetppo]--Message édité par Jar Jar--[/jfdsdjhfuetppo]


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 10-04-2002 à 14:00:03    

Code :
  1. for(i = 0 ; i < NbMax ; i++)
  2. {
  3.    tableau_pid[i] = fork();
  4. }


 
Bon je viens de relire les notes de cours et normalement je pense que je peux faire ça. Mais par contre, après comment je fais pour dire que je veux que mon processus X excéute la fonction que je veux ? Est-ce que ça marcherait ça :
 

Code :
  1. if(tableau_pid[X] == 0)
  2. {
  3.    Ma_fonction();
  4. } // Fin du if


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 10-04-2002 à 14:05:26    

Matheo a écrit a écrit :

Code :
  1. for(i = 0 ; i < NbMax ; i++)
  2. {
  3.    tableau_pid[i] = fork();
  4. }




Avec ça, tu n'auras pas N processus, mais 2^N...
 
 
C'est plutôt :

Code :
  1. pid_pere=getpid();
  2. for(i=0; i<NbMax; i++)
  3. {
  4.    if((tableau_pid[i]=fork())==0)
  5.        break;
  6. }
  7. switch(i)
  8. {
  9. case 0:
  10.   Premiere_fonction();
  11.   break;
  12. case 1:
  13.   Deuxième_fonction();
  14.   break;
  15. ...
  16. case NbMax:
  17.   fonction_du_père();
  18. }


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 11-04-2002 à 00:09:27    

Ouais, c'est pas pire ton affaire ! Je pense que je vais m'en inspirer  :D  
 
Par contre, je ne comprends pas trop bien l'utilisation des segments de données. Je dois attacher le segment à un processus, inscrire des données dedans et les trier puis après un quantum de temps, je fais un backup et j'exécute un autre processus qui fait la même chose. Mes interrogations se situent par rapport aux segments : quel est leur utilité (à quoi ça sert?) et comment les utiliser (avec les paramètres de clé et tout le tralala) ?
 
Je sens que je vais virer dingue ! [:wouaf]

 

[jfdsdjhfuetppo]--Message édité par Matheo--[/jfdsdjhfuetppo]


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 11-04-2002 à 09:59:31    

Matheo a écrit a écrit :

Par contre, je ne comprends pas trop bien l'utilisation des segments de données. Je dois attacher le segment à un processus, inscrire des données dedans et les trier puis après un quantum de temps, je fais un backup et j'exécute un autre processus qui fait la même chose. Mes interrogations se situent par rapport aux segments : quel est leur utilité (à quoi ça sert?) et comment les utiliser (avec les paramètres de clé et tout le tralala) ?


Les segments de mémoire partagée, c'est un truc très compliqué pour faire des choses simples. C'est pour ça que depuis on a inventé les threads. (Pareil pour les signaux d'ailleurs, depuis on a inventé les mutex.)
Ça sert à avoir une zone de mémoire commune à plusieurs processus. Dans cette zone de mémoire, tu mets des données, par exemple sous forme d'un tableau. Tout le problème après coup est qu'il faut un moyen aux différents processus d'accéder à la même zone de mémoire : c'est la clé.


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 11-04-2002 à 17:11:49    

Ça y est, je commence à y voir clair dans tout ça ! C'est pas évident mais je pense que je vais parvenir à me débrouiller. Je te remercei très fort pour toutes tes indications et si t'habitais proche de chez moi, je te payerais volontiers une bière.[:z-bob]


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 11-04-2002 à 17:21:10    

Matheo a écrit a écrit :

Ça y est, je commence à y voir clair dans tout ça ! C'est pas évident mais je pense que je vais parvenir à me débrouiller. Je te remercei très fort pour toutes tes indications et si t'habitais proche de chez moi, je te payerais volontiers une bière.[:z-bob]


Je t'en prie.


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 11-04-2002 à 18:33:49    

Au fait, t'habites dans quel coin ?


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 11-04-2002 à 19:12:50    

Matheo a écrit a écrit :

Au fait, t'habites dans quel coin ?


c01n c01n.
 
Euh, pardon, Lyon.


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 11-04-2002 à 19:43:28    

Moi je suis à Montréal ! 5000 km pour boire une bière ça fait un peu loin quand même !


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 11-04-2002 à 20:01:00    

Matheo a écrit a écrit :

Moi je suis à Montréal ! 5000 km pour boire une bière ça fait un peu loin quand même !


Ouaip ! Surtout que je ne bois pas de bière !


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 11-04-2002 à 21:28:25    

Juste une petite précision concernant la création des processus

Code :
  1. pid_pere=getpid();
  2. for(i=0; i<NbMax; i++)
  3. {
  4.   if((tableau_pid[i]=fork())==0)
  5.       break;
  6. }
  7. switch(i)
  8. {
  9. case 0:
  10. Premiere_fonction();
  11. break;
  12. case 1:
  13. Deuxième_fonction();
  14. break;
  15. ...
  16. case NbMax:
  17. fonction_du_père();
  18. }


 
1) Pourquoi les instructions du père se trouvent au case NbMax ?
 
2) À la sortie du switch, dans quel processus je me retrouve alors ?
 
3) Si tu bois pas de bière, tu bois quoi alors ?


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 11-04-2002 à 22:29:06    

1) fork renvoie une valeur non nulle (à savoir le pid du fils) uniquement quand on est dans le père, donc c'est le seul à rester dans la boucle, ce qui fait qu'à la fin i==NbMax.
 
2) Tous !
 
3) Du vin, du whisky, de la goutte... À peu près tout ce qui contient de l'alcool, en fait ;)


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 11-04-2002 à 23:34:28    

Étant donné que j'ai un nombre variable de processus mais qu'ils font presque tous la même fonction, est-ce que je peux faire :

Code :
  1. switch(i)
  2. {
  3.    case 0 :
  4.       fonction_1();
  5.       break;
  6.    case NbMax :
  7.       //fonctions du père avec les signaux pour endormir et réveiller les processus
  8.       break;
  9.    default :
  10.       if(i < NbMax)     //Juste pour s'assurer de ne pas avoir n'importe quoi
  11.          fonction_processus();
  12.       break;
  13. } // fin du switch


 
 
Aussi, si j'envoie un signal SIGSTOP à un processus qui est en train de faire un tri, est-ce qu'il va continuer au même endroit quand je vais faire un SIGCONT ?


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 12-04-2002 à 00:35:46    

Aucun problème pour ces deux trucs.


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 12-04-2002 à 06:07:10    

Est-ce possible d'exécuter une fonction A lorsque j'envoie un signal SIGCONT du père au fils et une fonction B quand j'envoie un signal SIGCONT du fils au père ?
Exemple

Code :
  1. switch
  2. {
  3.    case 0 : // Le fils
  4.       signal(SIGCONT, Fonction_A()) ;
  5.       break ;
  6.     case NbMax : // Le pere
  7.       signal(SIGCONT, Fonction_B()) ;
  8.       break ;
  9. } //Fin du switch


Ou même, ne pas spécifier de fonction spécifique pour le fils et traiter le signal normalement.


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 12-04-2002 à 09:54:23    

Oui, ça devrait se faire.
Enfin, je suppose que tu voulais dire switch(i)...
 
Au passage, évite signal et utilise plutôt sigaction (c'est plus souple et ça évite certains problèmes).


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 12-04-2002 à 10:27:42    

Je comprends vraiment pas !

Code :
  1. void fonc_fils(void)
  2. {
  3. cout << "Le fils s'endort. Pid = " << getpid() << endl;
  4. pause();
  5. cout << "Le fils se reveille.  Pid = " getpid() << endl;
  6. ...
  7. }// Fin de la fonction
  8. void fonc_papa(void)
  9. {
  10. cout << "Le pid du fils = " << tableau_pid[indice] << endl;
  11. kill(tableau_pid[indice], SIGCONT);
  12. ...
  13. }// Fin de la fonction


Ça donne ça
>Le fils s'endort. Pid = 12528
 Le pid du fils = 12528

et ça tombe en boucle infini. Est-ce que je dois rajouter qqchose ?


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 12-04-2002 à 10:41:28    

Tu viens de comprendre pourquoi on a inventé les sémaphores et les mutex.
 
Quand le père envoie SIGCONT, il est possible que le fils ne soit pas encore endormi...


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 12-04-2002 à 10:48:55    

http://pages.infinit.net/matheo/telnet.jpg
Je peux pas croire qu'il ne le réveille jamais. La boucle fait que le père s'exécute à l'infini.


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 12-04-2002 à 11:10:47    

Matheo a écrit a écrit :

Je peux pas croire qu'il ne le réveille jamais. La boucle fait que le père s'exécute à l'infini.


Tu as du mettre le père dans une autre boucle, alors... À moins que la fonction du père ne soit exécutée par erreur par un fils, sinon.


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 12-04-2002 à 11:42:45    

Là je comprends vraiment pas ce qui se passe.

Code :
  1. void Afficheur(int)
  2. {
  3. cout << "L'afficheur s'endort !" << endl;
  4. pause();
  5. cout << "L'afficheur se réveille!" << endl ;
  6. } // fin de la fonction
  7. void Fonc_Processus(int)
  8. {
  9. cout << "Le fils s'endort !" << endl;
  10. pause();
  11. cout << "Le fils se reveille !"<< endl ;
  12. } // fin de la fonction
  13. int main (int argc, char *argv[])
  14. {
  15. void Afficheur(int) ;
  16. void Fonc_Processus(int) ;
  17. int index ;
  18. int i ;
  19. int tableau_pid[3] ;
  20. // Création des processus
  21. for(index = 0 ; index < 2 ; index++)
  22. {
  23.  if( (tableau_pid[index] = fork() ) ==  0)
  24.   break ;
  25. } // Fin du for
  26. switch(index)
  27. {
  28.  case 0 :
  29.   signal(SIGCONT, Afficheur);
  30.   break ;
  31.  case 1 :
  32.   signal(SIGCONT, Fonc_Processus);
  33.   break ;
  34.  case 2 :
  35.   cout << "Le pere s'endort !" << endl;
  36.   sleep(3) ;
  37.   cout << "Le pere se reveille !" << endl;
  38.   kill(tableau_pid[0], SIGCONT) ;
  39.   cout << "Le pere se rendort !"<<endl;
  40.   sleep(3) ;
  41.   cout << "Le pere se reveille de nouveau !" << endl;
  42.   kill(tableau_pid[1], SIGCONT);
  43.   wait(NULL) ;
  44.   wait(NULL) ;
  45.   break ;
  46. } // Fin du switch
  47. } // Fin du programme


 
J'ai essayé de simplifier le code, juste la base et ça ne marche pas !! Ça me fait comme résultat :
>toto
Le pere s'endort !
Le pere se reveille !
Le pere se rendort !
Le pere se reveille de nouveau !

 
C'est tout, aucun contact avec les processus fils ! Pourtant c'est pratiquement l'exemple du livre ! Je comprends vraiment plus rien !

 

[jfdsdjhfuetppo]--Message édité par Matheo--[/jfdsdjhfuetppo]


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 12-04-2002 à 11:48:43    

Normal, les processus fils sont morts, le programme terminé, puisque tu ne leur fais rien faire.


---------------
« No question is too silly to ask, but, of course, some are too silly to answer. » -- Perl book
Reply

Marsh Posté le 12-04-2002 à 11:54:23    

Ils devraient au moins afficher un message. Sinon, à quoi elle sert la fonction pause() ?


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 12-04-2002 à 12:13:28    

Est-ce qu'il y a moyen aussi de passer des paramètres à la fonction reliée au signal ?
Ex : signal(SIGINT, Fonction_A(parametre)) ;


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le 12-04-2002 à 13:30:44    

Putain que je suis con ! Je suis con, je suis stupide, je ne mérite même pas de vivre !
 
Je viens de trouver LE bug qui faisait tout chier dans mon programme et maintenant ça marche impec. C'était tellement une erreur conne que j'en ai honte !
 
Y'a pas à dire, des fois je me surpasse au niveau de la connerie !


---------------
Je suis un franco-canado-québécois d'origine française de l'Amérique du nord francophone.
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed