From 24d316e72ca81dc660d28874fc355e00cc124caf Mon Sep 17 00:00:00 2001
From: laojiahuo <2944346255@qq.com>
Date: Thu, 19 Dec 2024 18:29:08 +0800
Subject: [PATCH 1/2] =?UTF-8?q?=E6=B6=88=E6=81=AF=E9=98=9F=E5=88=971?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Makefile                   |   2 +
 kernel/include/defs.h      |   8 +
 kernel/include/param.h     |   3 +-
 kernel/include/proc.h      |   4 +-
 kernel/include/syscall.h   |   5 +-
 kernel/main.c              |   1 +
 kernel/proc/exec.c         |   3 +-
 kernel/proc/messagequeue.c | 309 +++++++++++++++++++++++++++++++++++++
 kernel/proc/proc.c         |   5 +
 kernel/syscall.c           |  15 +-
 user/test/msgtest.c        |  65 ++++++++
 user/test/msgtset.c        |  64 ++++++++
 user/user.h                |   8 +-
 user/usys.pl               |   3 +
 14 files changed, 486 insertions(+), 9 deletions(-)
 create mode 100644 kernel/proc/messagequeue.c
 create mode 100644 user/test/msgtest.c
 create mode 100644 user/test/msgtset.c

diff --git a/Makefile b/Makefile
index fe44446..751429f 100755
--- a/Makefile
+++ b/Makefile
@@ -37,6 +37,7 @@ OBJS = \
   $K/interrupt/plic.o \
   $K/driver/virtio_disk.o \
   $K/sharemem.o \
+  $K/proc/messagequeue.o
 
 
 # riscv64-unknown-elf- or riscv64-linux-gnu-
@@ -165,6 +166,7 @@ UPROGS=\
 	$U/_writefile\
 	$U/_mkf\
 	$U/_sharemm\
+	$U/test/_msgtest\
 
 
 
diff --git a/kernel/include/defs.h b/kernel/include/defs.h
index 38a0625..82e9485 100644
--- a/kernel/include/defs.h
+++ b/kernel/include/defs.h
@@ -9,6 +9,14 @@ struct sleeplock;
 struct stat;
 struct superblock;
 struct sharemem;
+// messagequeue.c
+void mqinit();                 // 初始化系统消息队列
+int mqget(uint);               // 申请使用某个消息队列
+int msgsnd(uint, void *, int); // 发送消息
+int msgrcv(uint, void *, int); // 接收消息
+void releasemq(uint);          // 释放消息队列
+void releasemq2(int);
+void addmqcount(uint); // 增加消息队列的引用计数
 // sharemem.c
 void sharememinit();
 void *shmgetat(uint64, uint64);
diff --git a/kernel/include/param.h b/kernel/include/param.h
index b659fac..a411dc8 100644
--- a/kernel/include/param.h
+++ b/kernel/include/param.h
@@ -12,5 +12,6 @@
 #define MAXOPBLOCKS 10
 #define LOGSIZE (MAXOPBLOCKS * 3) // 指定日志区域的大小为每次可以写入的最大磁盘块数的3倍
 #define NBUF (MAXOPBLOCKS * 3)    // size of disk block cache
-#define FSSIZE 100000               // size of file system in blocks
+#define FSSIZE 100000             // size of file system in blocks
 #define MAXPATH 128               // maximum file path name
+#define MQMAX 8                   // 消息队列数量
\ No newline at end of file
diff --git a/kernel/include/proc.h b/kernel/include/proc.h
index 2b2f233..aeb17e6 100644
--- a/kernel/include/proc.h
+++ b/kernel/include/proc.h
@@ -136,6 +136,8 @@ struct proc
   uint shm;        // 本进程共享内存区域的下边界
   uint shmkeymask; // 本进程的8个共享内存区与使用掩码(位图)
   void *shmva[8];  // 本进程共享内存起始地址(虚地址)列表
+
+  uint mqmask; // 本进程使用的消息队列(掩码)
 };
 
-extern struct proc proc[NPROC]; // 声明进程表(全局)
\ No newline at end of file
+extern struct proc proc[NPROC]; // 声明进程表(全局)
diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h
index be7b108..75936da 100644
--- a/kernel/include/syscall.h
+++ b/kernel/include/syscall.h
@@ -36,6 +36,9 @@
 #define SYS_sem_p 35         // 信号量:P操作,获取资源
 #define SYS_sem_v 36         // 信号量:V操作,释放资源
 #define SYS_symlink 37       // 创建软链接
-#define SYS_mkf 38        // 创建文件
+#define SYS_mkf 38           // 创建文件
 #define SYS_shmgetat 39      // 共享内存
 #define SYS_shmrefcount 40   // 共享内存
+#define SYS_mqget 41
+#define SYS_msgsnd 42
+#define SYS_msgrcv 43
\ No newline at end of file
diff --git a/kernel/main.c b/kernel/main.c
index c8a79e9..4ed54df 100755
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -39,6 +39,7 @@ void main()
     virtio_disk_init(); // emulated hard disk
     initsem();          // 信号量数组初始化
     sharememinit();
+    mqinit();
     userinit();           // first user process
     __sync_synchronize(); // 防止编译器优化,确保后续的任何操作都是初始化之后进行
     started = 1;
diff --git a/kernel/proc/exec.c b/kernel/proc/exec.c
index c95eb8e..50e8439 100644
--- a/kernel/proc/exec.c
+++ b/kernel/proc/exec.c
@@ -121,7 +121,8 @@ int exec(char *path, char **argv)
   proc_freepagetable(oldpagetable, oldsz);
   proc->shm = KERNBASE; // 重置虚拟内存信息
   proc->shmkeymask = 0;
-
+  releasemq(p->mqmask);
+  p->mqmask = 0;
   return argc; // this ends up in a0, the first argument to main(argc, argv)
 
 bad:
diff --git a/kernel/proc/messagequeue.c b/kernel/proc/messagequeue.c
new file mode 100644
index 0000000..a4a879c
--- /dev/null
+++ b/kernel/proc/messagequeue.c
@@ -0,0 +1,309 @@
+#include "types.h"
+#include "spinlock.h"
+#include "riscv.h"
+#include "defs.h"
+#include "param.h"
+#include "proc.h"
+struct msg
+{                     // 消息结构体
+    struct msg *next; // 下一个消息
+    long type;        // 消息类型
+    char *dataaddr;   // 数据地址
+    int datasize;     // 消息长度
+};
+
+struct mq
+{                     // 消息队列
+    int key;          // 对应的key
+    int status;       // 0代表未使用,1代表已使用
+    struct msg *msgs; // 指向msg链表
+    int maxbytes;     // 一个消息队列最大为4k
+    int curbytes;     // 当前已使用字节数
+    int refcount;     // 引用数(进程数)
+};
+
+struct spinlock mqlock;     // 消息队列锁
+struct mq mqs[MQMAX];       // 默认系统最多8个消息队列
+struct proc *wqueue[NPROC]; // 写阻塞队列
+int wstart = 0;             // 写阻塞队列指示下标
+struct proc *rqueue[NPROC]; // 读阻塞队列
+int rstart = 0;             // 读阻塞队列指示下标
+
+int findkey(int key)
+{
+    int idx = -1;
+    for (int i = 0; i < MQMAX; ++i)
+    {
+        if (mqs[i].status != 0 && mqs[i].key == key)
+        {
+            idx = i;
+            break;
+        }
+    }
+    return idx;
+}
+
+void mqinit()
+{
+    printf("mq消息队列初始化完成\n");
+    initlock(&mqlock, "mqlock");
+    for (int i = 0; i < MQMAX; ++i)
+    {
+        mqs[i].status = 0;
+    }
+}
+int newmq(int key)
+{
+    int idx = -1;
+    for (int i = 0; i < MQMAX; i++)
+    {
+        if (mqs[i].status == 0)
+        {
+            idx = i;
+            break;
+        }
+    }
+    if (idx == -1)
+    {
+        printf("newmq 失败:分配新的消息队列失败,无法获得idx\n");
+        return -1;
+    }
+    mqs[idx].msgs = (struct msg *)kalloc(); // 为消息池分配一个页
+    if (mqs[idx].msgs == 0)
+    {
+        printf("newmq 失败:无法分配新的页面\n");
+        return -1;
+    }
+    mqs[idx].key = key;               // 为该消息队列设置key值
+    mqs[idx].status = 1;              // 标示为已启用
+    memset(mqs[idx].msgs, 0, PGSIZE); // 清空消息池
+    mqs[idx].msgs->next = 0;          // 接下来都是初始化消息队列
+    mqs[idx].msgs->datasize = 0;
+    mqs[idx].maxbytes = PGSIZE;
+    mqs[idx].curbytes = 16;
+    mqs[idx].refcount = 1;
+    proc->mqmask |= 1 << idx; // 修改当前进程的mqmask,表示使用中
+    return idx;
+}
+
+void addmqcount(uint mask)
+{
+    acquire(&mqlock);
+    for (int key = 0; key < MQMAX; key++)
+    {
+        if (mask >> key & 1)
+        {
+            mqs[key].refcount++;
+        }
+    }
+    release(&mqlock);
+}
+
+int sys_mqget(uint key)
+{
+    acquire(&mqlock);
+    int idx = findkey(key);
+    if (idx != -1)
+    { // 如果key对应的消息队列已经创建
+        if (!(proc->mqmask >> idx & 1))
+        {
+            proc->mqmask |= 1 << idx; // 标记该进程使用该消息队列
+            mqs[idx].refcount++;      // 消息队列的引用计数+1
+        }
+        release(&mqlock);
+        return idx;
+    }
+
+    // 对应key消息队列未创建则newmg创建
+    idx = newmq(key); // 创建消息队列
+    release(&mqlock);
+    return idx; // 返回该消息队列在mqs[]中的下标
+}
+
+// 消除内存碎片
+int reloc(int mqid)
+{
+    struct msg *pages = mqs[mqid].msgs;
+    struct msg *m = pages;
+    struct msg *t;
+    struct msg *pre = pages;
+    while (m != 0)
+    {
+        t = m->next;
+        memmove(pages, m, m->datasize + 16);
+        pages->next = (struct msg *)((char *)pages + pages->datasize + 16);
+        pages->dataaddr = ((char *)pages + 16);
+        pre = pages;
+        pages = pages->next;
+        m = t;
+    }
+    pre->next = 0;
+    return 0;
+}
+
+int sys_msgsnd(uint mqid, void *msg, int sz)
+{
+    // 校验消息队列的合法性
+    if (mqid < 0 || mqid >= MQMAX || mqs[mqid].status == 0)
+    {
+        return -1;
+    }
+
+    // 解析传入的消息数据
+    char *data = (char *)(((int *)(msg + 4)));
+
+    int *type = ((int *)msg); // 获取消息类型
+
+    // 如果队列为空,打印错误信息
+    if (mqs[mqid].msgs == 0)
+    {
+        printf("msgsnd failed: msgs == 0.\n");
+        return -1;
+    }
+
+    acquire(&mqlock);
+
+    while (1)
+    { // 一直循环直到发送成功
+        if (mqs[mqid].curbytes + sz + 16 <= mqs[mqid].maxbytes)
+        { // 如果剩余空间充裕
+            struct msg *m = mqs[mqid].msgs;
+
+            // 找到队尾最后一个空闲消息区
+            while (m->next != 0)
+            {
+                m = m->next;
+            }
+            // 退出循环时,m->next == 0,表示空闲消息区
+
+            m->next = (void *)m + m->datasize + 16; // 计算用于存储消息的起始位置
+            m = m->next;                            // m为本消息存储空间起点
+
+            m->type = *(type);            // 填写本消息的类型
+            m->next = 0;                  // 本消息暂无后续消息
+            m->dataaddr = (void *)m + 16; // 数据区的起始位置
+            m->datasize = sz;             // 数据长度
+
+            // 复制消息数据到消息区
+            memmove(m->dataaddr, data, sz);
+
+            mqs[mqid].curbytes += (sz + 16); // 可用空间缩减
+
+            // 唤醒所有读阻塞进程
+            for (int i = 0; i < rstart; i++)
+            {
+                wakeup(rqueue[i]);
+            }
+
+            rstart = 0; // 读阻塞队列置空
+            release(&mqlock);
+            return 0; // 成功发送消息
+        }
+        else
+        { // 如果空间不足,进程睡眠在wqueue阻塞队列
+            printf("msgsnd: cannot alloc: pthread: %d sleep.\n", myproc()->pid);
+            wqueue[wstart++] = proc; // 将当前进程加入等待队列
+
+            sleep(proc, &mqlock); // 进入休眠状态,等待唤醒
+        }
+    }
+    return -1; // 发送失败
+}
+
+int sys_msgrcv(uint mqid, void *msg, int sz)
+{
+    // 校验消息队列的合法性
+    if (mqid < 0 || mqid >= MQMAX || mqs[mqid].status == 0)
+    {
+        return -1;
+    }
+
+    int *type = msg;     // 待读取消息类型
+    int *data = msg + 4; // 待读取消息目标位置
+
+    acquire(&mqlock);
+
+    while (1)
+    {
+        struct msg *m = mqs[mqid].msgs->next;
+        struct msg *pre = mqs[mqid].msgs;
+
+        while (m != 0)
+        {
+            if (m->type == *type)
+            { // 找到要读取的消息类型
+                // 复制消息数据到目标位置
+                memmove(data, m->dataaddr, sz);
+
+                // 从队列中删除已读取的消息
+                pre->next = m->next;
+
+                // 释放消息占用的空间
+                mqs[mqid].curbytes -= (m->datasize + 16);
+
+                // 重新整理内存
+                reloc(mqid);
+
+                // 唤醒所有写阻塞进程
+                for (int i = 0; i < wstart; i++)
+                {
+                    wakeup(wqueue[i]);
+                }
+                wstart = 0; // 写阻塞队列置空
+
+                release(&mqlock);
+                return 0; // 成功读取消息
+            }
+
+            pre = m;
+            m = m->next;
+        }
+
+        // 如果没有找到匹配的消息类型,当前进程进入休眠状态
+        printf("msgrcv: can not read: pthread: %d sleep.\n", proc->pid);
+
+        // 将当前进程加入读阻塞队列
+        rqueue[rstart++] = proc;
+
+        sleep(proc, &mqlock); // 进入休眠状态,等待唤醒
+        return -1;            // 未能成功读取消息
+    }
+}
+
+void rmmq(int mqid)
+{
+    kfree((char *)mqs[mqid].msgs);
+    mqs[mqid].status = 0;
+}
+
+void releasemq(uint key)
+{
+    int idx = findkey(key);
+    if (idx != -1)
+    {
+        acquire(&mqlock);
+        mqs[idx].refcount--;
+        if (mqs[idx].refcount == 0)
+        {
+            rmmq(idx);
+        }
+        release(&mqlock);
+    }
+}
+
+void releasemq2(int mask)
+{
+    acquire(&mqlock);
+    for (int id = 0; id < MQMAX; ++id)
+    {
+        if (mask >> id & 0x1)
+        {
+            mqs[id].refcount--;
+            if (mqs[id].refcount == 0)
+            {
+                rmmq(id);
+            }
+        }
+    }
+    release(&mqlock);
+}
\ No newline at end of file
diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c
index a764a33..dfc50b8 100644
--- a/kernel/proc/proc.c
+++ b/kernel/proc/proc.c
@@ -128,6 +128,7 @@ static struct proc *allocproc(void)
 found:
 
   p->pid = allocpid();
+  p->mqmask = 0;
   p->priority = 10; // 设定优先级为10
   p->cpu_time = 0;
   p->wait_time = 0;
@@ -327,6 +328,8 @@ int fork(void)
   }
   shmaddcount(proc->shmkeymask); // fork新进程,所以共享内存引用数量加一
 
+  addmqcount(p->mqmask);  // 消息队列引用数量+1
+  np->mqmask = p->mqmask; // 掩码复制
   np->sz = p->sz;
 
   np->parent = p;
@@ -500,6 +503,8 @@ int wait(uint64 addr)
         {
           // Found one.
           pid = np->pid;
+          releasemq2(p->mqmask);
+          p->mqmask = 0;
           if (addr != 0 && copyout(p->pagetable, addr, (char *)&np->xstate,
                                    sizeof(np->xstate)) < 0)
           {
diff --git a/kernel/syscall.c b/kernel/syscall.c
index c78028b..7bd978e 100755
--- a/kernel/syscall.c
+++ b/kernel/syscall.c
@@ -140,10 +140,13 @@ extern uint64 sys_sem_create(void);   // 信号量
 extern uint64 sys_sem_free(void);     // 信号量
 extern uint64 sys_sem_p(void);        // 信号量
 extern uint64 sys_sem_v(void);        // 信号量
-extern uint64 sys_symlink(void); 
+extern uint64 sys_symlink(void);
 extern uint64 sys_mkf(void);
-extern uint64 sys_shmgetat(void);     // 共享内存
-extern uint64 sys_shmrefcount(void);  // 共享内存
+extern uint64 sys_shmgetat(void);    // 共享内存
+extern uint64 sys_shmrefcount(void); // 共享内存
+extern uint64 sys_mqget(void);
+extern uint64 sys_msgsnd(void);
+extern uint64 sys_msgrcv(void);
 
 static uint64 (*syscalls[])(void) = {
     [SYS_fork] sys_fork,
@@ -186,6 +189,9 @@ static uint64 (*syscalls[])(void) = {
     [SYS_mkf] sys_mkf,
     [SYS_shmgetat] sys_shmgetat,
     [SYS_shmrefcount] sys_shmrefcount,
+    [SYS_mqget] sys_mqget,
+    [SYS_msgsnd] sys_msgsnd,
+    [SYS_msgrcv] sys_msgrcv,
 }; // 这些索引会从1开始,不是从0开始
 static char *syscall_names[] = {
     [SYS_fork] "fork",
@@ -228,6 +234,9 @@ static char *syscall_names[] = {
     [SYS_mkf] "sys_mkf",
     [SYS_shmgetat] "sys_shmgetat",
     [SYS_shmrefcount] "sys_shmrefcount",
+    [SYS_mqget] "sys_mqget",
+    [SYS_msgsnd] "sys_msgsnd",
+    [SYS_msgrcv] "sys_msgrcv",
 };
 void syscall(void) // 在usys.s中系统调用的参数放在a0与a1中,系统调用号放在a7
 {
diff --git a/user/test/msgtest.c b/user/test/msgtest.c
new file mode 100644
index 0000000..284b892
--- /dev/null
+++ b/user/test/msgtest.c
@@ -0,0 +1,65 @@
+#include "param.h"
+#include "fcntl.h"
+#include "types.h"
+#include "stat.h"
+#include "riscv.h"
+#include "fs.h"
+#include "user/user.h"
+
+struct msg
+{
+    long type; // 使用 long 类型来符合消息队列要求
+    char *dataaddr;
+} s1, s2, g;
+
+void msg_test()
+{
+    // 创建消息队列
+    int mqid = mqget(123);
+
+    int pid = fork();
+    if (pid == 0)
+    { // 子进程
+        s1.type = 1;
+        s1.dataaddr = "This is the first message!";
+        msgsnd(mqid, &s1, 27); // 发送消息1
+
+        s1.type = 2;
+        s1.dataaddr = "Hello, another message comes!";
+        msgsnd(mqid, &s1, 30); // 发送消息2
+
+        s1.type = 3;
+        s1.dataaddr = "This is the third message, and this message has great characters!";
+        msgsnd(mqid, &s1, 70); // 发送消息3
+
+        printf("All messages have been sent.\n");
+        exit(0); // 子进程结束
+    }
+    else if (pid > 0)
+    {              // 父进程
+        sleep(10); // sleep 保证子进程消息写入之后才读入
+
+        g.dataaddr = malloc(70);
+
+        g.type = 2;
+        msgrcv(mqid, &g, 30); // 读入消息2
+        printf("Received the %ldth message: Hello, another message comes!\n", g.type);
+
+        g.type = 1;
+        msgrcv(mqid, &g, 27); // 读入消息1
+        printf("Received the %ldth message: This is the first message!\n", g.type, g.dataaddr);
+
+        g.type = 3;
+        msgrcv(mqid, &g, 70); // 读入消息3
+        printf("Received the %ldth message: This is the third message, and this message has great characters!\n", g.type, g.dataaddr);
+
+        wait(0); // 等待子进程结束
+        exit(0);
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    msg_test();
+    return 0;
+}
diff --git a/user/test/msgtset.c b/user/test/msgtset.c
new file mode 100644
index 0000000..17f1295
--- /dev/null
+++ b/user/test/msgtset.c
@@ -0,0 +1,64 @@
+#include "param.h"
+#include "fcntl.h"
+#include "types.h"
+#include "stat.h"
+#include "riscv.h"
+#include "fs.h"
+#include "user/user.h"
+
+struct msg
+{
+    long type; // 使用 long 类型来符合消息队列要求
+    char *dataaddr;
+} s1, s2, g;
+
+void msg_test()
+{
+    // 创建消息队列
+    int mqid = mqget(123);
+
+    int pid = fork();
+    if (pid == 0)
+    { // 子进程
+        s1.type = 1;
+        s1.dataaddr = "This is the first message!";
+        msgsnd(mqid, &s1, 27); // 发送消息1
+
+        s1.type = 2;
+        s1.dataaddr = "Hello, another message comes!";
+        msgsnd(mqid, &s1, 30); // 发送消息2
+
+        s1.type = 3;
+        s1.dataaddr = "This is the third message, and this message has great characters!";
+        msgsnd(mqid, &s1, 70); // 发送消息3
+
+        printf("All messages have been sent.\n");
+        exit(0); // 子进程结束
+    }
+    else if (pid > 0)
+    {              // 父进程
+        sleep(10); // sleep 保证子进程消息写入之后才读入
+
+        g.dataaddr = malloc(70);
+
+        g.type = 2;
+        msgrcv(mqid, &g, 30); // 读入消息2
+        printf("Received the %ldth message: %s\n", g.type, g.dataaddr);
+
+        g.type = 1;
+        msgrcv(mqid, &g, 27); // 读入消息1
+        printf("Received the %ldth message: %s\n", g.type, g.dataaddr);
+
+        g.type = 3;
+        msgrcv(mqid, &g, 70); // 读入消息3
+        printf("Received the %ldth message: %s\n", g.type, g.dataaddr);
+
+        wait(0); // 等待子进程结束
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    msg_test();
+    return 0;
+}
diff --git a/user/user.h b/user/user.h
index ab0a3df..fa695f1 100755
--- a/user/user.h
+++ b/user/user.h
@@ -35,7 +35,7 @@ void *mmap(void *addr, int length, int prot, int flags, int fd, int offset);
 int munmap(void *addr, int length);
 int sh_var_read(void);
 void sh_var_write(int n);
-int symlink(char target[MAXPATH],char path[MAXPATH]);
+int symlink(char target[MAXPATH], char path[MAXPATH]);
 // 信号量
 int sem_create(int);
 int sem_free(int);
@@ -45,6 +45,10 @@ int mkf(char *, short, short, short);
 // 共享内存
 uint64 shmgetat(int, int);
 int shmrefcount(int);
+// 消息队列
+int mqget(uint);               // 申请使用某个消息队列
+int msgsnd(uint, void *, int); // 发送消息
+int msgrcv(uint, void *, int); // 接收消息
 // ulib.c
 int stat(const char *, struct stat *);
 char *strcpy(char *, const char *);
@@ -53,7 +57,7 @@ char *strchr(const char *, char c);
 int strcmp(const char *, const char *);
 void fprintf(int, const char *, ...);
 void printf(const char *, ...);
-char *gets(char *, int );
+char *gets(char *, int);
 uint strlen(const char *);
 void *memset(void *, int, uint);
 void *malloc(uint);
diff --git a/user/usys.pl b/user/usys.pl
index d1f4041..ba27445 100755
--- a/user/usys.pl
+++ b/user/usys.pl
@@ -55,3 +55,6 @@ entry("symlink");
 entry("mkf");
 entry("shmgetat"); # 共享内存
 entry("shmrefcount");#  共享内存
+entry("mqget");
+entry("msgsnd");
+entry("msgrcv");
-- 
GitLab


From f0d6606ff79abb1b49fa9df839eeccfb6d9c1251 Mon Sep 17 00:00:00 2001
From: laojiahuo <2944346255@qq.com>
Date: Thu, 19 Dec 2024 18:32:14 +0800
Subject: [PATCH 2/2] =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=9B=B4=E6=96=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 README.md | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/README.md b/README.md
index 8ed363c..ec71d05 100644
--- a/README.md
+++ b/README.md
@@ -92,3 +92,13 @@
       - `SYS_shmrefcount`: 查询共享内存的引用计数。
     - 实现了共享内存的引用计数管理、内存分配、映射、解除映射等功能,确保进程间共享内存的同步与资源回收。
     - 完成了父子进程使用共享内存的示例,展示了父进程和子进程如何访问和修改共享内存中的数据。
+- **12/19:**  
+  - **消息队列功能开发:**
+    - 实现了消息队列的创建、发送、接收功能,支持进程间通信
+      - 实现了消息队列的创建、发送消息到队列、从队列接收消息的基本功能。
+      - 支持消息队列的内存管理,避免了内存碎片。
+      - 实现了进程在队列满时的写阻塞和在队列空时的读阻塞机制。
+    - 添加了以下系统调用:
+      - `SYS_mqget`: 获取消息队列。
+      - `SYS_msgsnd`: 发送消息到消息队列。
+      - `SYS_msgrcv`: 从消息队列接收消息。
-- 
GitLab