C – Problème de transmission de message entre les threads à l’aide de files d’attente

J’essaie de faire passer des messages entre deux threads en utilisant une queue, mais je n’ai pas obtenu de résultat jusqu’à présent. Lorsque j’imprime le contenu du message après sa réception et avant son envoi, il ne semble garder que sa valeur dans la bande de roulement. Je dois l’implémenter avec 1 thread de serveur et plusieurs threads de client, mais pour l’instant, je n’en utilise qu’un. Voici mon code

struct msg //struct for client requests to server { long mtype; int numResources; //number of resources to be requested int ID; //ID associated with client thread }; int c1PID; //process ID variable for client thread 1 int serverPID; key_t key1; key_t keyS; int msqid1; int msqidS; int main(int arc, char *argv[]) { key1 = ftok(".", '1'); //queue for client thread 1 to receive msgs from server msqid1 = msgget(key1, 666 | IPC_CREAT); keyS = ftok(".", 's'); //general queue for server msqidS = msgget(keyS, 666 | IPC_CREAT); pthread_t threads[2]; //create an array of pthreads if ((serverPID = pthread_create(&threads[0], NULL, server, NULL)) != 0) { perror("server thread"); exit(1); } if ((c1PID = pthread_create(&threads[1], NULL, client, NULL)) != 0) { perror("client thread"); exit(1); } pthread_exit(NULL); } void *server() { struct msg request; size_t size = sizeof(struct msg) - offsetof(struct msg, numResources); while (1) { msgrcv(msqidS, &request, size, 2, 0); printf("received: numResources requested = %d\n", request.numResources); request.numResources = 9001; printf("sending: numResources requested = %d\n", request.numResources); msgsnd(msqid1, &request, size, 0); sleep(1); } } void *client() { struct msg request; size_t size; request.numResources = 0; size = sizeof(struct msg) - offsetof(struct msg, numResources); msgsnd(msqidS, &request, size, 0); while(1) { msgrcv(msqid1, &request, size, 2, 0); printf("received: numResources requested = %d\n", request.numResources); request.numResources += 1;//(int)(ceil((double)(rand()%2)) + 1); printf("sending: numResources requested = %d\n", request.numResources); msgsnd(msqidS, &request, size, 0); sleep(1); } 

J’ai sorti beaucoup de mes déclarations imprimées, mais cela ressemble à ceci:

 Server thread: received: numResources = 9001; sending: numResources = 9001; client thread: received: numResources = 1; sending: numResources = 2; Server thread: received: numResources = 9001; sending: numResources = 9001; client thread: received: numResources = 2; sending: numResources = 3; 

Edit: Le sizeof (struct msg) – offsetof (struct msg, numResources); ça devrait être bon.

Mais, votre type de mtype doit être, conformément à la documentation , un entier positif. Initialisez-le à 2, car vos appels à msgrecv indiquent de ne recevoir que le type de message 2.

Ajoutez une vérification des erreurs à tous les appels msgsnd / msgrecv afin que vous soyez sûr de ne pas recevoir d’erreurs en silence.

Ajoutez une vérification d’erreur à vos appels ftok et msgget.

Votre problème est que vous avez défini des permissions non-sens sur vos files de messages. Dans ces lignes, vous avez utilisé une constante décimale 666 laquelle vous auriez dû utiliser une constante octale 0666 :

  msqid1 = msgget(key1, 666 | IPC_CREAT); msqid1 = msgget(key1, 666 | IPC_CREAT); 

Cela signifie que vous avez créé les files d’attente avec des permissions 01232 , ce qui n’inclut pas l’autorisation de lecture. Par conséquent, vos appels msgget() suivants msgget() maintenant avec EPERM (ce que vous verrez si vous recherchez des erreurs dans ces appels).

Vous devrez supprimer vos files de messages et permettre à votre programme de les recréer avec les permissions appropriées. Vous devez utiliser le msqid pour la queue avec la commande msgctl() à msgctl() pour ce faire, comme dans le programme suivant:

 #include  #include  #include  #include  #include  int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "Usage: %s  [ ...]\n", argv[0]); return 1; } while (*++argv) { int msqid = atoi(*argv); printf("Removing msqid %d\n", msqid); if (msgctl(msqid, IPC_RMID, NULL) != 0) { perror("msgctl"); return 2; } } return 0; } 

En raison de la conception affreuse des files de messages SYS V, vous ne pouvez plus obtenir les valeurs de msgget() partir de msgget() , car msgget() échoue. Pour que les valeurs de msqid supprimées, consultez le fichier /proc/sysvipc/msg .

PS:

Je recommande fortement d’utiliser des files de messages POSIX à la place ( mq_open() , mq_send() , mq_receive() etc.). L’interface est considérablement améliorée.

Voici ce qu’il a imprimé sur le fil qui semblait fonctionner.

 program starting Msg sent from client *****In client thread***** Msg received by client received: numResources requested = 0 sending: numResources requested = 1 Msg sent from client *****In server thread***** Msg received by server received: numResources requested = 1 sending: numResources requested = 9001 Msg sent from server. *****In client thread***** Msg received by client received: numResources requested = 9001 sending: numResources requested = 9002 Msg sent from client *****In server thread***** Msg received by server received: numResources requested = 9002 sending: numResources requested = 9001 Msg sent from server. *****In client thread***** Msg received by client received: numResources requested = 9001 sending: numResources requested = 9002 Msg sent from client *****In server thread***** Msg received by server received: numResources requested = 9002 sending: numResources requested = 9001 Msg sent from server. *****In client thread***** Msg received by client received: numResources requested = 9001 sending: numResources requested = 9002 Msg sent from client 

Et tout de suite après ….

 program starting Msg sent from client *****In client thread***** Msg received by client received: numResources requested = 9001 sending: numResources requested = 9002 Msg sent from client *****In server thread***** Msg received by server received: numResources requested = 0 sending: numResources requested = 9001 Msg sent from server. *****In client thread***** Msg received by client received: numResources requested = 9002 sending: numResources requested = 9003 Msg sent from client *****In server thread***** Msg received by server received: numResources requested = 9001 sending: numResources requested = 9001 Msg sent from server. *****In client thread***** Msg received by client received: numResources requested = 9003 sending: numResources requested = 9004 Msg sent from client *****In server thread***** Msg received by server received: numResources requested = 9001 sending: numResources requested = 9001 Msg sent from server. 

Celles-ci ont été exécutées l’une après l’autre sans modification du code entre les deux.