进程间通信—消息传递机制

本文档简要介绍了一种基于队列的进程间消息传递机制,旨在实现不同进程之间的数据交换和协作。此机制通过消息队列来管理消息,保证消息的有序传递与接收,且采用锁机制确保线程安全。每个进程拥有独立的消息队列,通过消息队列管理消息的发送与接收。

核心功能:

  1. 消息发送:进程可以将消息发送到指定的目标进程队列。
  2. 消息接收:进程可以从自己的消息队列中接收消息。
  3. 队列管理:消息队列采用先进先出的顺序进行管理,确保消息的有序传递。

系统设计:

代码实现

1. 消息结构体定义:

#define MAX_MSG_SIZE 256    // 最大消息大小,定义消息中 `data` 字段的最大字节数。
#define MAX_MSG_COUNT 16    // 最大消息数量,限制消息队列中最多存储的消息个数。

struct msg {
  char data[MAX_MSG_SIZE];  // 消息的内容,最大为 `MAX_MSG_SIZE` 字节。
  int size;                 // 消息的大小,表示 `data` 中实际存储的数据字节数。
  int sender;               // 发送者的标识符。
  int receiver;             // 接收者的标识符。
  struct msg *next;         // 指向下一条消息的指针。
};

2. 消息队列结构体定义:

struct msgqueue {
  struct msg *head;         // 队列的头指针。
  struct msg *tail;         // 队列的尾指针。
  int count;                // 当前队列中消息的数量。
  struct spinlock lock;     // 互斥锁,用于保证线程安全。
};

3. 消息发送系统调用实现:

uint64
sys_msgsend(void)
{
  int receiver;
  uint64 data;
  int size;
  char buf[MAX_MSG_SIZE];

  argint(0, &receiver);
  if (receiver < 0) {
    printf("msgsend: failed to get receiver\\n");
    return -1;
  }

  argaddr(1, &data);
  if (data < 0) { // 使用 argaddr 获取用户空间指针
    printf("msgsend: failed to get data address\\n");
    return -1;
  }

  argint(2, &size);
  if (size < 0) {
    printf("msgsend: failed to get size\\n");
    return -1;
  }

  if (size > MAX_MSG_SIZE) {
    printf("msgsend: message too large\\n");
    return -1;
  }

  // 从用户空间复制数据到内核缓冲区
  if (copyin(myproc()->pagetable, buf, data, size) < 0) {
    printf("msgsend: failed to copy data from user space\\n");
    return -1;
  }

  return msgsend(receiver, buf, size);
}

4. 消息接收系统调用实现:

uint64
sys_msgrecv(void)
{
  uint64 data; // 修改为用户空间指针
  char buf[MAX_MSG_SIZE];
  int size;

  argaddr(0, &data);
  if (data < 0) { // 使用 argaddr 获取用户空间指针
    return -1;
  }

  size = msgrecv(buf);
  if (size < 0)
    return -1;

  // 将数据复制回用户空间
  if (copyout(myproc()->pagetable, data, buf, size) < 0)
    return -1;

  return size;
}

5. 消息发送和接收功能函数实现: