[C] programmation IPC (memoire partagee) sous Unix >> magie inside <<

programmation IPC (memoire partagee) sous Unix >> magie inside << [C] - C - Programmation

Marsh Posté le 25-02-2004 à 13:30:47    

voila, ayant deja poste un topic auparavant sur ce probleme (dont j'ai trouve la reponse), j'ai de nouveau un probleme sur ce sujet.
 
Pour etre clair, precis et concis, mon programme IPC utilise une zone de memoire partagee :
- j'ai un programme qui cree la shm
- j'ai un programme qui depose dans la shm
- ... rien qu'avec ces 2 programme, kkchose ne tourne pas rond.
 
Je les lance l'un apres l'autre :
d'abord la creation...une fois le programme termine, je lance le programme producteur.
Le probleme c'est que ce dernier n'arrive pas a ecrire dans la shm (malgre qu'il a les droits)
J'espere que la sortie suivante, bien que lourde, vous aiderez a voir clairement que le producteur n'ecrit rien dans la shm (on le voit quand j'affiche le contenu de la shm) mais sait y lire dedans;
alors que le programme de creation lui arrive bien a y lire/ecrire dedans.
 
voici la sortie du programme de creation :


/Net/mahonet/Utilisateurs/ffournel/iup/shm_queue_v2>./shm_create
creation : creation de la zone de memoire partagee...
creation : creation de l'ensemble des semaphores...
creation : je suis attache au segment shm d'adresse 0x40016000...
creation : contenu de la shm : 0, adresse 0x40016000
creation : contenu de la shm : 0, adresse 0x40016004
creation : contenu de la shm : 0, adresse 0x40016008
creation : contenu de la shm : 0, adresse 0x4001600c
creation : contenu de la shm : 0, adresse 0x40016010
creation : contenu de la shm : 0, adresse 0x40016014
creation : contenu de la shm : 0, adresse 0x40016018
creation : contenu de la shm : 0, adresse 0x4001601c
creation : contenu de la shm : 0, adresse 0x40016020
creation : contenu de la shm : 0, adresse 0x40016024
creation : contenu de la shm : 0, adresse 0x40016028
creation : contenu de la shm : 0, adresse 0x4001602c
creation : contenu de la shm : 0, adresse 0x40016030
creation : contenu de la shm : 0, adresse 0x40016034
creation : contenu de la shm : 0, adresse 0x40016038
creation : initialisation de la structure QueueLimited dans la shm...
creation : fifo->elements = 0x40016014
creation : fifo->head = 0x40016014
creation : fifo->end = 0x40016014
creation : fifo->max = 0x4001603c
creation : fifo->size_elt = 4
creation : contenu de la shm : 0x40016014, adresse 0x40016000
creation : contenu de la shm : 0x40016014, adresse 0x40016004
creation : contenu de la shm : 0x40016014, adresse 0x40016008
creation : contenu de la shm : 0x4001603c, adresse 0x4001600c
creation : contenu de la shm : 0x4, adresse 0x40016010
creation : contenu de la shm : 0, adresse 0x40016014
creation : contenu de la shm : 0, adresse 0x40016018
creation : contenu de la shm : 0, adresse 0x4001601c
creation : contenu de la shm : 0, adresse 0x40016020
creation : contenu de la shm : 0, adresse 0x40016024
creation : contenu de la shm : 0, adresse 0x40016028
creation : contenu de la shm : 0, adresse 0x4001602c
creation : contenu de la shm : 0, adresse 0x40016030
creation : contenu de la shm : 0, adresse 0x40016034
creation : contenu de la shm : 0, adresse 0x40016038
creation : je me suis detache du segment shm 0x40016000...  


 
voici la sortie du programme de production :


/Net/mahonet/Utilisateurs/ffournel/iup/shm_queue_v2>./shm_prod2
producteur 2 : je suis attache au segment shm d'adresse 0x40015000...
producteur 2 : fifo->elements = 0x40016014
producteur 2 : fifo->head = 0x40016014
producteur 2 : fifo->end = 0x40016014
producteur 2 : fifo->max = 0x4001603c
producteur 2 : fifo->size_elt = 4
producteur 2 : contenu de la shm : 0x40016014
producteur 2 : contenu de la shm : 0x40016014
producteur 2 : contenu de la shm : 0x40016014
producteur 2 : contenu de la shm : 0x4001603c
producteur 2 : contenu de la shm : 0x4
producteur 2 : contenu de la shm : 0
producteur 2 : contenu de la shm : 0
producteur 2 : contenu de la shm : 0
producteur 2 : contenu de la shm : 0
producteur 2 : contenu de la shm : 0
producteur 2 : contenu de la shm : 0
producteur 2 : contenu de la shm : 0
producteur 2 : contenu de la shm : 0
producteur 2 : contenu de la shm : 0
producteur 2 : contenu de la shm : 0
producteur 2 : je suis en zone critique : depot de 18 a l'adresse : 0x40016014
producteur 2 : contenu de la shm : 0x40016014, adresse : 0x40015000
producteur 2 : contenu de la shm : 0x40016014, adresse : 0x40015004
producteur 2 : contenu de la shm : 0x40016014, adresse : 0x40015008
producteur 2 : contenu de la shm : 0x4001603c, adresse : 0x4001500c
producteur 2 : contenu de la shm : 0x4, adresse : 0x40015010
producteur 2 : contenu de la shm : 0, adresse : 0x40015014
producteur 2 : contenu de la shm : 0, adresse : 0x40015018
producteur 2 : contenu de la shm : 0, adresse : 0x4001501c
producteur 2 : contenu de la shm : 0, adresse : 0x40015020
producteur 2 : contenu de la shm : 0, adresse : 0x40015024
producteur 2 : contenu de la shm : 0, adresse : 0x40015028
producteur 2 : contenu de la shm : 0, adresse : 0x4001502c
producteur 2 : contenu de la shm : 0, adresse : 0x40015030
producteur 2 : contenu de la shm : 0, adresse : 0x40015034
producteur 2 : contenu de la shm : 0, adresse : 0x40015038
producteur 2 : je suis en zone critique : depot de 65 a l'adresse : 0x40016018
producteur 2 : contenu de la shm : 0x40016014, adresse : 0x40015000
producteur 2 : contenu de la shm : 0x40016014, adresse : 0x40015004
producteur 2 : contenu de la shm : 0x40016018, adresse : 0x40015008
producteur 2 : contenu de la shm : 0x4001603c, adresse : 0x4001500c
producteur 2 : contenu de la shm : 0x4, adresse : 0x40015010
producteur 2 : contenu de la shm : 0, adresse : 0x40015014
producteur 2 : contenu de la shm : 0, adresse : 0x40015018
producteur 2 : contenu de la shm : 0, adresse : 0x4001501c
producteur 2 : contenu de la shm : 0, adresse : 0x40015020
producteur 2 : contenu de la shm : 0, adresse : 0x40015024
producteur 2 : contenu de la shm : 0, adresse : 0x40015028
producteur 2 : contenu de la shm : 0, adresse : 0x4001502c
producteur 2 : contenu de la shm : 0, adresse : 0x40015030
producteur 2 : contenu de la shm : 0, adresse : 0x40015034
producteur 2 : contenu de la shm : 0, adresse : 0x40015038  


 
on voit que le depot de la valeur 18 et 65 en shm ont echoue car le contenu est inchange :??:


Message édité par Giz le 27-02-2004 à 15:17:48
Reply

Marsh Posté le 25-02-2004 à 13:30:47   

Reply

Marsh Posté le 25-02-2004 à 13:43:46    

...bien et maintenant voici le code (dont j'ai vire quelques les commentaires pour faire court et les test d'erreurs)
 
 
shm_create.c :

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/ipc.h>
  6. #include <sys/shm.h>
  7. #include <sys/sem.h>
  8. #include "queue_limited.h"
  9. #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
  10. /* l'union semun est définie par l'inclusion de <sys/sem.h> */
  11. #else
  12. /* d'après X/OPEN il faut la définir nous-mêmes */
  13. union semun {
  14.       int val;                  /* valeur pour SETVAL */
  15.       struct semid_ds *buf;     /* buffer pour IPC_STAT, IPC_SET */
  16.       unsigned short *array;    /* table  pour GETALL, SETALL */
  17.                                 /* Spécificité Linux : */
  18.       struct seminfo *__buf;    /* buffer pour IPC_INFO */
  19. };
  20. #endif
  21. //taille d'un element dans la file de message en shm
  22. #define SIZE_ELT (sizeof (int))
  23. //nombre d'element max que peut contenir la file dans la shm
  24. #define NB_ELT 10
  25. int main ()
  26. {
  27. key_t key;
  28. int shm_id, sem_id, i;
  29. union semun arg;
  30. QueueLimited *fifo;
  31. printf ("creation : creation de la zone de memoire partagee...\n" );
  32. //generation d'une cle secrete pour identifier la zone de memoire partagee
  33. key = ftok ("./shm_main.c", 987654321)
  34. shm_id = shmget (key, NB_ELT * SIZE_ELT + sizeof (QueueLimited), IPC_CREAT | IPC_EXCL | 0666)
  35. printf ("creation : creation de l'ensemble des semaphores...\n" );
  36. //generation d'une cle secrete pour identifier l'ensemble de semaphores
  37. key = ftok ("./shm_main.c", 876543210)
  38. sem_id = semget (key, 4, IPC_CREAT | IPC_EXCL | 0666)
  39. //parametrage de chaque semaphore avec leur valeur initiale
  40. arg.val = 1;
  41. semctl (sem_id, 0, SETVAL, arg)
  42. arg.val = 1;
  43. semctl (sem_id, 1, SETVAL, arg)
  44. arg.val = NB_ELT;
  45. semctl (sem_id, 2, SETVAL, arg)
  46. arg.val = 0;
  47. semctl (sem_id, 3, SETVAL, arg)
  48. //initialisation de la structure QueueLimited dans la shm
  49. fifo = (QueueLimited *) shmat (shm_id, NULL, 0)
  50. printf ("creation : je suis attache au segment shm d'adresse %#x...\n", fifo );
  51. for (i = 0; i < 15; i++)
  52.  printf ("creation : contenu de la shm : %#x, adresse %#x\n", *((int *) fifo + i), (int *) fifo + i);
  53. printf ("creation : initialisation de la structure QueueLimited dans la shm...\n" );
  54. fifo->elements = (char *) fifo + sizeof (QueueLimited);
  55. printf ("creation : fifo->elements = %#x\n", fifo->elements);
  56. fifo->head  = (char *) fifo + sizeof (QueueLimited);
  57. printf ("creation : fifo->head = %#x\n", fifo->head);
  58. fifo->end  = (char *) fifo + sizeof (QueueLimited);
  59. printf ("creation : fifo->end = %#x\n", fifo->end);
  60. fifo->max  = (char *) fifo + sizeof (QueueLimited) + NB_ELT * SIZE_ELT;
  61. printf ("creation : fifo->max = %#x\n", fifo->max);
  62. fifo->size_elt = SIZE_ELT;
  63. printf ("creation : fifo->size_elt = %d\n", fifo->size_elt);
  64. for (i = 0; i < 15; i++)
  65.  printf ("creation : contenu de la shm : %#x, adresse %#x\n", *((int *) fifo + i), (int *) fifo + i);
  66. //detachement du processus de la shm
  67. shmdt (fifo)
  68. printf ("creation : je me suis detache du segment shm %#x...\n", (int) fifo);
  69. return 0;
  70. }


 
le programme de shm_prod2.c :
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/ipc.h>
  6. #include <sys/shm.h>
  7. #include <sys/sem.h>
  8. #include <time.h>
  9. #include "queue_limited.h"
  10. int main ()
  11. {
  12. key_t key;
  13. int shm_id, sem_id, to_send, i;
  14. struct sembuf prendre[2] = {{2, -1, 0}, {1, -1, 0}};
  15. struct sembuf vendre[2]  = {{1, 1, 0}, {3, 1, 0}};
  16. QueueLimited *fifo;
  17. //generation d'une cle secrete pour identifier la zone de memoire partagee
  18. key = ftok ("./shm_main.c", 987654321)
  19. shm_id = shmget (key, 1, IPC_CREAT)
  20. //attachement du processus a la shm
  21. fifo = (QueueLimited *) shmat (shm_id, NULL, 0)
  22. printf ("producteur 2 : je suis attache au segment shm d'adresse %#x...\n", fifo);
  23. printf ("producteur 2 : fifo->elements = %#x\n", fifo->elements);
  24. printf ("producteur 2 : fifo->head = %#x\n", fifo->head);
  25. printf ("producteur 2 : fifo->end = %#x\n", fifo->end);
  26. printf ("producteur 2 : fifo->max = %#x\n", fifo->max);
  27. printf ("producteur 2 : fifo->size_elt = %d\n", fifo->size_elt);
  28. for (i = 0; i < 15; i++)
  29.  printf ("producteur 2 : contenu de la shm : %#x\n", *((int *) fifo + i));
  30. //generation d'une cle secrete pour identifier l'ensemble de semaphores
  31. key = ftok ("./shm_main.c", 876543210))
  32. sem_id = semget (key, 0, IPC_CREAT)
  33. /*
  34.  * depot dans la file FIFO et operation sur les semaphores
  35.  */
  36. srand (time (0));
  37. while (1)
  38. {
  39.  //valeur a deposer
  40.  to_send = rand () % 100;
  41.  semop (sem_id, &prendre[0], 2)
  42.  /*
  43.   *   *** ZONE CRITIQUE ***
  44.   */
  45.  //gestion de facon circulaire de la FIFO
  46.  if (fifo->end == fifo->max)
  47.   fifo->end = fifo->elements;
  48.  //insertion de la valeur dans la fifo
  49.  *((int *) fifo->end) = to_send;
  50.  printf ("producteur 2 : je suis en zone critique : depot de %d a l'adresse : %#x\n", *((int *) fifo->end), fifo->end);
  51.  for (i = 0; i < 15; i++)
  52.   printf ("producteur 2 : contenu de la shm : %#x, adresse : %#x\n", *((int *) fifo + i), (int *) fifo + i);
  53.  //avancement du pointeur "end"
  54.  fifo->end = (char *) fifo->end + fifo->size_elt;
  55.  /*
  56.   *   *** FIN ZONE CRITIQUE ***
  57.   */
  58.  semop (sem_id, &vendre[0], 2)
  59.  sleep (1);
  60. }
  61. return 0;
  62. }


 
la structure QueueLimited :

Code :
  1. typedef struct
  2. {
  3. void *elements;  //elements de la file
  4. void *head;   //prochaine valeur a extraire
  5. void *end;   //prochaine valeur a ajouter
  6. void *max;   //taille max de la file
  7. size_t size_elt; //taille des elements dans la file
  8. }
  9. QueueLimited;


 
voila tout :)


Message édité par Giz le 25-02-2004 à 14:00:41
Reply

Marsh Posté le 25-02-2004 à 14:01:47    

Bon voilà, j'espere que kk1 d'entre vous pourra m'eclairer.
Desole mais je ne peux pas faire plus court je pense :/
 
@+ je dois y aller

Reply

Marsh Posté le 26-02-2004 à 13:27:06    

j'ai cherché jusqu'à 2 heures du mat  :sweat: , personne n'a une petite idée ?

Reply

Marsh Posté le 27-02-2004 à 15:17:04    

Alors là j'hallucine grave !
Avec ce code ci-dessus, le programme producteur n'arrive pas a ecrire dans la shm (ca se voit lorsque il liste le contenu de celle-ci).
En rajoutant simplement l'instruction suivante :

Code :
  1. printf ("key = %d\n", key);


après le 1er appel ftok() dans shm_prod2.c, le programme producteur se met à marcher ! :
il ecrit bien dans la shm et lorsque il lit le contenu, on voit bien la valeur ainsi déposée.
Ceci est un tour de magie dont je ne peux expliquer.
Avant de rire derriere votre écran, j'aimerais bien que vous compiliez ce code.
Regardez la sortie obtenue AVANT puis APRES l'ajout de l'instruction printf; et vous verrez que je ne raconte pas de sottises !  
De mon coté, j'ai fais ça sur 2 machines differentes, et le resultat est bien comme je l'ai dis. (une sous Redhat, l'autre sous Mandrake).
Bref j'attends des explications sur la "magie" de l'informatique :D
 
Autre chose, ayant donc "reussi" (je ne comprends pas quel miracle) a faire fonctionner au moins un producteur et un consommateur ensemble, les 2 programmes bouclant en permanence, au bout d'un certain temps aléatoire (assez court), un programme plante sur l'instruction semop() (fonction ininterruptible) a cause de la reception d'un signal système (EINTR).
Comment cela se fait, je n'ai aucune explication la dessus :sarcastic:


Message édité par Giz le 27-02-2004 à 15:21:18
Reply

Marsh Posté le 27-02-2004 à 15:27:27    

Il manque pleins de ; en fin de ligne. Comment veux tu que ça compile ton code ?

Reply

Marsh Posté le 02-03-2004 à 10:15:33    

Kristoph a écrit :

Il manque pleins de ; en fin de ligne. Comment veux tu que ça compile ton code ?


 
a la place des tests d'erreur , j'ai transformer la ligne en instruction, fo juste les rajouter j'ai oublier  :sarcastic:

Reply

Marsh Posté le 02-03-2004 à 10:32:21    

Giz a écrit :


 
a la place des tests d'erreur , j'ai transformer la ligne en instruction, fo juste les rajouter j'ai oublier  :sarcastic:  


 
Je ne t'avais pas attendu pour corriger ça mais ça fait perdre du temps quand on copie colle le code pour le tester et donc comme ça tu as potentiellement perdu de l'aide.
 
De plus, le programme a planté une fois au bout de quelque temps, et après il ne voulait plus se lancer du tout :o Même Valgrind plantait.

Reply

Marsh Posté le 02-03-2004 à 12:06:05    

sous nunux, les sémaphores (et mémoire partagée ché pu :D) survivent à la mort du process.

Reply

Marsh Posté le 02-03-2004 à 19:03:09    

Kristoph a écrit :


 
Je ne t'avais pas attendu pour corriger ça mais ça fait perdre du temps quand on copie colle le code pour le tester et donc comme ça tu as potentiellement perdu de l'aide.
 
De plus, le programme a planté une fois au bout de quelque temps, et après il ne voulait plus se lancer du tout :o Même Valgrind plantait.


 
au lieu de me faire un caca nerveu, tu veux que je te mail ENTIEREMENT les sources (2 prod + 2 conso + creation + destruction + analyse des semaphores + analyse de la shm + tout les makefile)
 
Et la tu compile et tout marchera nickel (il me faut ton mail)

Reply

Sujets relatifs:

Leave a Replay

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