#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 Спасибо за ваш ответ, теперь все работает нормально.