我正在尝试使用邮箱(即共享邮件缓冲区)实现线程间通信。
我已经写了以下功能,用于将邮件存入邮箱并从邮箱中退出,但我确信我错过了一些小的东西(但是,我无法弄清楚是什么)。当我尝试从邮箱中检索消息时,消息长度以某种方式设置为0,理想情况下它应该从缓冲区中的节点读取。我的邮箱功能代码,测试程序及其预期输出以及我得到的输出如下:
void mbox_deposit(mbox *mb, char *msg, int len)
{
struct msg *temp, *temp1;
temp = GetNewMsgNode(len);
// temp = mb->msg_queue;
sem_wait(mb->sem_mbox);
// lock mailbox - critical section locked
if(mb->msg_queue == NULL)
{
temp->message = msg;
temp->length = len;
temp->next = NULL;
mb->msg_queue = temp;
}
else
{
temp->message = msg;
temp->length = len;
temp->next = NULL;
temp1 = mb->msg_queue;
while(temp1->next != NULL)
temp1 = temp1->next;
temp1->next = temp;
}
// unlock mailbox - critical section unlocked
sem_signal(mb->sem_mbox);
}
void mbox_withdraw(mbox *mb, char *msg, int *len)
{
// struct msg *temp;
// temp = mb->msg_queue;
sem_wait(mb->sem_mbox);
// lock mailbox - critical section locked
if(mb->msg_queue == NULL)
{
printf("No message to withdraw!");
return;
}
else
{
// withdraw first message from message queue
// temp = temp->next;
len = &(mb->msg_queue->length);
printf("%d", len);
if(len != 0)
{
msg = mb->msg_queue->message;
// make the msg_queue head point to the new first message in the queue after the first message has been removed
if(mb->msg_queue->next != NULL)
mb->msg_queue = mb->msg_queue->next;
}
// free(temp);
}
// unlock mailbox - critical section unlocked
sem_signal(mb->sem_mbox);
}
预期输出的测试程序如下:
#include <stdio.h>
#include <stdlib.h>
#include "ud_thread.h"
mbox *mb;
char *msg[2] = {"hello world...", "bye, bye"};
void producer(int id)
{
int i;
char mymsg[30];
for (i = 0; i < 2; i++) {
sprintf(mymsg, "%s - tid %d", msg[i], id);
printf("Producer (%d): [%s] [length=%d]\n", id, mymsg, strlen(mymsg));
mbox_deposit(mb, mymsg, strlen(mymsg));
}
t_terminate();
}
void consumer(int id)
{
int i;
int len;
char mesg[1024];
for (i = 0; i < 4; i++) {
mbox_withdraw(mb, mesg, &len);
printf("Message from mailbox: [%s]\n", mesg);
}
t_terminate();
}
int main(void) {
t_init();
mbox_create(&mb);
t_create(producer, 1, 1);
t_create(producer, 2, 1);
t_create(consumer, 3, 1);
t_yield();
mbox_destroy(&mb);
t_shutdown();
printf("Done with mailbox test...\n");
return 0;
}
预期产出:
Producer (1): [hello world... - tid 1] [length=22]
Producer (1): [bye, bye - tid 1] [length=16]
Producer (2): [hello world... - tid 2] [length=22]
Producer (2): [bye, bye - tid 2] [length=16]
Message from mailbox: [hello world... - tid 1]
Message from mailbox: [bye, bye - tid 1]
Message from mailbox: [hello world... - tid 2]
Message from mailbox: [bye, bye - tid 2]
Done with mailbox test...
但是,我最终得到的邮箱功能是:
Producer (1): [hello world... - tid 1] [length=22]
Producer (1): [bye, bye - tid 1] [length=16]
Producer (2): [hello world... - tid 2] [length=22]
Producer (2): [bye, bye - tid 2] [length=16]
Message from mailbox: []
Message from mailbox: []
Message from mailbox: []
Message from mailbox: []
Done with mailbox test...
关于我在这里可能缺少什么的任何建议?
答案 0 :(得分:1)
此分配对调用者无效:
void mbox_withdraw(mbox *mb, char *msg, int *len)
....
msg = mb->msg_queue->message;
您只是更改自己的指针msg
副本。这是C FAQ的一个着名问题的一个复杂的例子(或者你可能试图以错误的方式复制字符串)。
你可能想做类似的事情:
memcpy(msg, b->msg_queue->message, ...);
如果您已经信任邮箱中的字符串(您可能在此类测试程序中执行此操作),则只需使用strcpy
。
修改
在你的代码msg
中只是一个变量,一个指针。当您调用该函数时,它指向char mesg[1024]
中的数据。但是,如果你说msg = mb->msg_queue->message
,你的变量msg
指向别的东西。在函数结束时,msg
点的任何地方都无关紧要;重要的是对呼叫者的影响。