实验目的
通过对进程间通信(消息队列)的设计,深入理解进程之间是如何通过消息队列进行通信的。
实验原理
消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。
对消息队列有写权限的进程可以向中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读走消息。
消息缓冲区可以理解成进程通过消息队列在传送或接收消息时的信息容器。当有人发送信息时则将信息通过消息缓冲区放入队列,有人读取此消息队列时,则从队列中取出信息放入接收方缓冲区(先进先出)。
实验内容
(1)编程实现两个进程通过消息队列进行通信,一个 Server 进程,一个 Client 进程。
(2)Server 进程向 Client 进程发送其进程 ID,Client 进程同时也向 Server 进程发送其进程 ID,双方接收到消息后,将所接收到的进程 ID 输出到屏幕上。
实验器材
硬件环境:个人计算机
操作系统:CentOS 7
实验步骤
(1)利用消息队列实现进程间的通信的实现流程图
(2)利用消息队列实现进程间的通信的实现代码
-
建立消息队列。
-
创建子进程作为客户进程,父进程作为服务进程。
服务进程从消息队列读取数据,再向消息队列发送数据,不断循环;客户进程向消息队列发送数据,再从消息队列读取数据,然后结束。
实验结果
//Using Message Queue to Realize IPC
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/msg.h>
#include <sys/types.h>
#define MAX_TEXT 512
struct mymesg {
long mytype; //消息类型,使用正数
char mytext[MAX_TEXT]; //消息数据,长度可以自行定义
};
int main() {
//建立消息队列
int msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
if (msgid == -1)
return -1;
struct mymesg datasnd, datarcv;
pid_t pid = fork(); //创建子进程作为客户进程,父进程作为服务进程
if (pid > 0) { //服务进程
while (1) {
//从消息队列读取数据
int ret = msgrcv(msgid, &datarcv, MAX_TEXT, 2, 0);
if (ret == -1) {
//删除消息队列
msgctl(msgid, IPC_RMID, NULL);
return 0; //结束进程
}
printf("%s\n", datarcv.mytext);
//向消息队列发送数据
datasnd.mytype = 1;
sprintf(datasnd.mytext, "Server Process ID: %d", getpid());
msgsnd(msgid, &datasnd, MAX_TEXT, 0);
}
}
else {
//向消息队列发送数据
datasnd.mytype = 2;
sprintf(datasnd.mytext, "Client Process ID: %d", getpid());
msgsnd(msgid, &datasnd, MAX_TEXT, 0);
//从消息队列读取数据
msgrcv(msgid, &datarcv, MAX_TEXT, 1, 0);
printf("%s\n", datarcv.mytext);
return 0; //结束进程
}
}
Server 进程向 Client 进程发送其进程 ID,Client 进程同时也向 Server 进程发送其进程 ID,双方接收到消息后,将所接收到的进程 ID 输出到屏幕上。
客户进程 ID:11294
服务进程 ID:11293
操作系统基础实验: