使用邮箱实现线程间通信的问题

时间:2014-05-08 18:10:24

标签: c multithreading

我正在尝试使用邮箱(即共享邮件缓冲区)实现线程间通信。

我已经写了以下功能,用于将邮件存入邮箱并从邮箱中退出,但我确信我错过了一些小的东西(但是,我无法弄清楚是什么)。当我尝试从邮箱中检索消息时,消息长度以某种方式设置为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...

关于我在这里可能缺少什么的任何建议?

1 个答案:

答案 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点的任何地方都无关紧要;重要的是对呼叫者的影响。