C Linux pthreads: отправка данных из одного потока в antoher с использованием очереди сообщений дает неожиданный результат

#c #linux #multithreading #pthreads #message-queue

#c #linux #многопоточность #pthreads #очередь сообщений

Вопрос:

Я пишу программу, которая передаст 50 целых чисел из одного потока в другой, используя очередь сообщений, и после получения целых чисел поток получателя распечатает их.

На данный момент поток получателя печатает первые 13 целых чисел (0,1,2 .. 12), но после этого он просто печатает все 0.

Вот мой код на данный момент:

 #include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>


//define declarations
#define SIZE     50


//structs
typedef struct msgbuf {
         long    mtype;
         int    data[SIZE];
         } data_buf;


//function declarations
void *send_data();
void *receive_data();

main()
{
     pthread_t thread1;
     pthread_t thread2;
     int ret_val_t1;
     int ret_val_t2;

     //create thread1
     ret_val_t1 = pthread_create( amp;thread1, NULL, send_data, NULL);
     if(ret_val_t1)
     {
         fprintf(stderr,"Error - pthread_create() return value: %dn",ret_val_t1);
         exit(EXIT_FAILURE);
     }

     //create thread2
     ret_val_t2 = pthread_create( amp;thread2, NULL, receive_data, NULL);
     if(ret_val_t2)
     {
         fprintf(stderr,"Error - pthread_create() return value: %dn",ret_val_t2);
         exit(EXIT_FAILURE);
     }

     printf("pthread_create() for thread 1 returns: %dn",ret_val_t1);
     printf("pthread_create() for thread 2 returns: %dn",ret_val_t2);

     //wait untill threads are done with their routines before continuing with main thread
     pthread_join( thread1, NULL);
     pthread_join( thread2, NULL); 

     exit(EXIT_SUCCESS);
}

void *send_data(){

    int msqid;
    int msgflg = IPC_CREAT | 0666;
    key_t key;
    data_buf sbuf;
    size_t buf_length;

    //get the message queue id for the key with value 1234
    key = 1234;

    (void) fprintf(stderr, "nmsgget: Calling msgget(%#lx,%#o)n", key, msgflg);

    if ((msqid = msgget(key, msgflg )) < 0) {
        perror("msgget");
        exit(1);
    }
    else{ 
    (void) fprintf(stderr,"msgget: msgget succeeded: msqid = %dn", msqid);
    }

    //send message type 1
    sbuf.mtype = 1;

    (void) fprintf(stderr,"msgget: msgget succeeded: msqid = %dn", msqid);

    //fill the array that is to be sent from thread1 to thread2
    int i = 0;
    for(i = 0; i < SIZE; i  ){
    sbuf.data[i] = i;
    }   

    (void) fprintf(stderr,"msgget: msgget succeeded: msqid = %dn", msqid);

    buf_length = SIZE;

    //send data from thread1 to thread2
    if (msgsnd(msqid, amp;sbuf, buf_length, IPC_NOWAIT) < 0) {
        perror("msgsnd");
        exit(1);
    }

   else 
      printf("Data sentn");
}

void *receive_data(){
    int msqid;
    key_t key;
    data_buf  rbuf;

    //get the message queue id for the key with value 1234
    key = 1234;

    if ((msqid = msgget(key, 0666)) < 0) {
        perror("msgget");
        exit(1);
    }

    //receive the answer with message type 1
    if (msgrcv(msqid, amp;rbuf, SIZE, 1, 0) < 0) {
        perror("msgrcv");
        exit(1);
    }


    //print received answer
    int j = 0;
    for(j = 0; j < SIZE; j  ){
    printf("%dn", rbuf.data[j]);
    }

}
  

И вот мой вывод:

 msgget: Calling msgget(0x4d2,01666)
pthread_create() for thread 1 returns: 0
pthread_create() for thread 2 returns: 0
msgget: msgget succeeded: msqid = 0
msgget: msgget succeeded: msqid = 0
msgget: msgget succeeded: msqid = 0
Data sent
0
1
2
3
4
5
6
7
8
9
10
11
12
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
  

Комментарии:

1. Вы отправляете и получаете только 50 байт, но вы отправляете целые числа, которые, вероятно, составляют 4 байта каждый на вашем компьютере.

2. @MarekKlein Сообщения SysV работают не так. sizeof(data_buf.data) если что-нибудь.

Ответ №1:

Это

 buf_length = SIZE;
  

устанавливает размер текста сообщения в 50 байт.

Тем не менее, структура определена как

 typedef struct msgbuf {
         long    mtype;
         int    data[SIZE];
} data_buf;
  

data составляет 50 int элементов. Это не 50 байт — это почти наверняка 200 байт, с 4-байтовым / 32-разрядным int .

И 50 байт достаточно для хранения 12 1/2 4-байтовых int значений, что объясняет, почему вы видите количество до 12.

Заменить buf_length = SIZE на buf_length = sizeof( data_buf );

Комментарии:

1. Я думаю, что он также пытается отправить mtype, таким образом buf_length = sizeof(data_buf)

2.@MarekKlein Не в приведенном здесь примере:pubs.opengroup.org/onlinepubs/9699919799/functions/msgsnd.html result = msgsnd(msqid, (void *) amp;msg, sizeof(msg.text), IPC_NOWAIT);

3. @AndrewHenle Спасибо за ваш ответ, теперь все работает нормально.