计划步骤:
1.看视频中的 消息队列部分 视频:https://www.bilibili.com/video/BV1tJ41117ty/?spm_id_from=333.337.search-card.all.click&vd_source=7a1a0bc74158c6993c7355c5490fc600
2.看那篇英文文章中,基于共享内存和消息队列的 “生产者-消费者” 模型
https://www.geeksforgeeks.org/inter-process-communication-ipc/
task1: 看视频中的 消息队列部分
管道的顺序队列(数组)
消息队列是链式队列(链表?)
使用 ipcs -q 可以查看系统中现存的消息队列中,有几个消息,占用多少字符
消息队列有点类似 FIFO 缓冲区。往里面写信息就是插入,读信息就是删除
最核心的问题是:消息队列的读写是否阻塞?
根据 视频中的 消息队列(1) 来看,使用 msgsnd 和 msgrcv 需要定义一个数据结构,如下:
(视频中定义的数据结构和 man msgsnd 看到的数据结构有些不同,建议参考原视频)
// 以下数据结构抄自 man msgsnd
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
根据 视频中的 消息队列(3) 来看,msgsnd 和 msgrcv 两个函数都可以设置 阻塞 or 非阻塞
根据 视频中的 消息队列(3) 来看,消息队列不但能实现单向通信,还能实现双向通信,而且只需要一个消息队列就能做到。以下是一个简单的实现方式的描述:
实现一个 server.c 和一个 client.c 代码
server.c 向消息队列写入类型为 100 的数据,client.c 向消息队列写入类型为 200 的数据。server.c 再 fork 一个子进程,循环接收消息队列中类型为 200 的数据。client.c 再 fork 一个子进程,循环接收消息队列里类型为 100 的数据。
根据 视频中的 消息队列(3) 来看,如果是无亲缘关系的两个进程要使用消息队列通信,那么也要使用 ftok 函数来创建唯一的 key
根据 视频中的 消息队列(3) 来看,当消息队列中有数据时,msgrcv 读取完消息后会直接返回,当消息队列中没有数据时,msgrcv 会阻塞直到有数据
TODO:可以试试,循环往消息队列中写入数据但是不接收,在消息队列满了后,msgsnd 是否会阻塞
等待
QUESTION:研究一下消息队列视频中,提到的 “使用共享内存需要用星号/信号表示写入完毕是什么意思” (回答:根据视频共享内存(4), 是在读写共享内存结束时,向对方发送 SIGUSR1/2 信号,表示读写完毕)
根据共享内存(2),使用 IPC_PRIVATE 创建的共享内存的key永远是0,而使用 ftok 创建的共享内存key > 0。IPC_PRIVATE 创建的共享内存只能让拥有亲缘关系的进程共享,而使用 ftok 创建的共享内存可以让任意进程共享。
根据共享内存(3),使用 shmdt 只是取消了对共享内存的映射,并没有实际删除内核中的共享内存。要真正删除,还得使用 shmctl
根据共享内存(3),命令 ipcs -m 的实现方式实际上是 使用 shmctl 和 IPC_STAT ; 实现 ipcrm -m 的命令的方式实际上是使用 shmctl 和 IPC_RMID
根据共享内存(4),在使用共享内存的时候,父子进程可以使用 SIGUSR1 和 SIGUSR2 两个信号告诉对方自己已经写入/接收了共享内存中的信息。(子进程可以使用 getppid() 系统调用来获取父进程的 pid)
TODO:here