操作系统原理实验报告

课程名称 操作系统原理实验
实验项目名称 实验九 消息队列

实验目的

  • 了解 Linux 系统的进程间通信机构 (IPC);
  • 理解Linux 关于消息队列的概念;
  • 掌握 Linux 支持消息队列的系统调用;
  • 巩固进程同步概念。

实验内容

  • 在并发进程问通过消息队列进行通信;
  • 使用系统调用:msgget ()、msgsnd ()、 msgrcv ()、msgctl ()。

实验步骤

一、基本概念

消息队列保存在内核中,是一个由消息结构组成的链表,每个消息队列(链表)有消息队列标识符。消息队列允许一个或多个进程写入或读取消息,因此消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法,并可实现双向通信。消息队列解决了读写进程的同步和阻塞问题。

二、有关 System V 消息队列的系统调用

System V 消息队列需使用下列头文件:

  • #include <sys/types.h>
  • #include <sys/ipc.h>
  • #include <sys/msg.h>

1、创建消息队列函数:int msgget(key_t key, int msgflg)

2、向消息队列中发送信息:int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg)

3、从消息队列中接收信息:size_t msgrev(int msqid, void *msgp, size _t msgsz, long msgtyp, int msgflg)

4、在消息队列上执行指定操作:int msgetl(int msgid, int emd, struct msqid ds *buf)

三、例程:使用消息队列进行并发进程间传递信息

例程 0

先启动服务器端,再启动客户端进程,查看消息队列:

正常发送完10条数据后,进程自动退出,查看消息队列,发现已经自动删除:

注:删除服务器端的msgctl(msgqid,IPC_RMID,0);,则在退出进程后消息队列仍然存在

这里,服务器端进程必须先执行,该进程会先创建好传输结点、75号消息队列并进入循环等待接收数据,在完成接收后删除消息队列。客户端则先连接75号消息队列,然后循环10次接收键入信息、写入结点并发送的过程,然后退出进程。

例程 1,两个进程并发执行,通过消息队列,分别进行消息的发送和接收。

编译链接通过后,在两个终端分别运行发送进程和接收进程,观察进程并发执行结果,并思考下述问题:

1、熟悉和消息队列相关的系统调用;

启动服务器端、客户端进程,查看消息队列:

尝试发送数据:

这里的程序相较于例程0来说功能方面没有差别,但是结构、安全性方面更加完善。

服务器端先声明传输结点,然后创建1234号消息队列(这里有错误返回),最后进入循环等待接收信息(这里有错误返回),并在接收到“end”后结束循环,并删除消息队列然后结束进程(这里有错误返回)。客户端开始时也会创建1234号消息队列,因此不需要先启动服务器端,然后循环接收键入信息并写入结点传输,并在接收到“end”后结束循环然后退出进程。

这里值得注意的是,及时客户端发送的数据不是“end”仍然可能会导致进程退出,推测是判断的时候是从缓冲区开始处开始判断字符“end”,只要匹配到就会退出而不管后面是否还有字符。

2、尝试运行多个发送进程和多个接收进程,观察进程的并发执行情况,并解释原因。

启动两个服务器端和客户端:

在这里,先后启动的一对服务器、客户端进程之间可以进行数据发送,且不同对的进程之间的数据传输不共享,却又同时使用一个消息队列。因此我们可以看到在客户端1结束进程后,导致服务器端2的消息队列结束,产生43号错误。

例程2,三个线程(两个发送者,一个接收者)并发执行。通过消息队列,分别进行消息的发送和接收。

编译链接通过后,运行程序,通过程序提示,观察多线程的并发执行,并思考下述问题:

1、熟悉和消息队列相关的系统调用;

启动进程,查看进程树、消息队列:

尝试发送数据:

观察到这里生产者1陷入饥饿状态,这是由于生产者2结束后又直接执行生产者2线程。

在生产者线程发送完成后加入sleep:

程序生产者交替执行,也可以通过控制sleep时间来实现随机执行。

这里程序仍然是生产者-消费者问题,程序先创建后信号量,然后创建3个子线程(分别对应2个生产者1个消费者),并在3个子线程都结束后结束进程。对于消费者线程,完成初始化后创建消息队列,然后进入循环等待接收信息(这里读取结点信息时,可以通过结点内数据来判断信息是由哪个进程发送的)。并在接收到结束信息时返回结束的信号来告诉生产者线程可以结束了。对于发送者线程,完成初始化后链接到消息队列,然后进行数据的发送。

2、回顾与 POSIX 线程控制和信号量相关的函数;
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
Link with -lrt or -pthread.
#include <semaphore.h>
int sem_post(sem_t *sem);
Link with -lrt or -pthread.
#include <semaphore.h>
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
Link with -lrt or -pthread

https://blog.csdn.net/vickytong1018/article/details/67631802

3、尝试删除信号量的同步控制,观察并发线程运行的混乱情况;

启动进程,查看进程树、消息队列:

尝试发送数据:

观察到发送产生混乱,使用客户端1发送数据会被判断为客户端2发送。因为这里没有进行进程同步、互斥,因此产生了并发线程运行的混乱情况。

4、厘清例程中并发线程同步和互斥关系。
  • w_mutex:互斥信号量,用于控制生产者对临界区(消息队列)的独占;
  • empty、full:一组同步信号量,用于控制临界区(消息队列)的生产;
  • over:互斥信号量,用于控制生产者在消费者接收到结束信号后退出线程;
  • rcv_dp、snd_dp:一组同步信号量,用于控制消费者对临界区(消息队列)消费。

这里,利用w_mutex来控制两个生产者的生产;利用over来控制生产者线程的推出;利用empty、full来同步生产者对临界区(消息队列)的生产;利用rcv_dp、snd_dp来同步消费者对临界区(消息队列)消费。

四、编程题

修改例程 1,模仿例程 2,在原有的 MSG1 向 MSG2 发送消息的基础上,实现 MSG2也能向 MSG1 发送消息,即两并发进程能通过消息队列,实现双向对话。运行效果如下图所示。

#include <stdio.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>#define MSGKEY1 66
#define MSGKEY2 68struct msgform
{long mtype;char mtext[1000];
}msg;int msgqid;void server( ) {msgqid=msgget(MSGKEY1,0777|IPC_CREAT);while (1){sleep(1);msgrcv(msgqid,&msg,1024,0,0);if (msg.mtype == 2) {printf("(server)received:%s\n", msg.mtext);strcpy(msg.mtext, "");msg.mtype = 1;msgsnd(msgqid, &msg, 1024, 0);}elsecontinue;}
}
void client() {/*打开消息队列*/msgqid=msgget(MSGKEY2,0777|IPC_CREAT);while (1) {sleep(1);scanf("%s", msg.mtext);msg.mtype = 2;msgsnd(msgqid, &msg, 1024, 0);}
}
int main( )
{if(fork()!=0)server();elseclient();
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>#define MSGKEY1 66
#define MSGKEY2 68struct msgform
{long mtype;char mtext[1000];
}msg;int msgqid;void server( ) {msgqid=msgget(MSGKEY2,0777|IPC_CREAT);while (1){sleep(1);msgrcv(msgqid,&msg,1024,0,0);if (msg.mtype == 2) {printf("(server)received:%s\n", msg.mtext);strcpy(msg.mtext, "");msg.mtype = 1;msgsnd(msgqid, &msg, 1024, 0);}elsecontinue;}
}
void client() {/*打开消息队列*/msgqid=msgget(MSGKEY1,0777|IPC_CREAT);while (1) {sleep(1);scanf("%s", msg.mtext);msg.mtype = 2;msgsnd(msgqid, &msg, 1024, 0);}
}
int main( )
{if(fork()!=0)server();elseclient();
}

ZUCC_操作系统原理实验_实验九 消息队列相关推荐

  1. ZUCC_操作系统原理实验_Lab9进程的通信消息队列

    lab9进程的通信–消息队列 一.两个进程并发执行,通过消息队列,分别进行消息的发送和接收 1.代码: //接受消息 #include<stdio.h> #include<stdli ...

  2. c语言上机实验指导西南交通大学,操作系统原理与应用实验指导书-西南交通大学.doc...

    操作系统原理与应用实验指导书-西南交通大学 <操作系统原理与应用> 实验指导书 西南交通大学经济管理学院 电子商务与信息管理系 王明亮编写 2007年7月 实验名称:1. 安装Linux操 ...

  3. cmi编码实验_实验二 - 光纤通信系统线路码型CMI - 编译码实验 - 图文 -

    实验二 光纤通信系统线路码型CMI 编译码实验 一.实验目的 1.了解线路码型在光纤传输系统中的作用 2.掌握线路码型CMI码的编译码过程以及电路实现原理 二.实验内容 1.验证符合光纤传输系统的线路 ...

  4. java基本语句回文数实验_实验二 java基本数据类型与把持语句.doc

    实验二 java基本数据类型与把持语句.doc 还剩 4页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,喜欢就下载吧,价低环保! 内容要点: 5System.out.println(num ...

  5. 怎么看rabbitmq的浏览器信息_没用过消息队列?一文带你体验RabbitMQ收发消息

    人生终将是场单人旅途,孤独之前是迷茫,孤独过后是成长. 楔子 先给大家说声抱歉,最近一周都没有发文,有一些比较要紧重要的事需要处理. 今天正好得空,本来说准备写SpringIOC相关的东西,但是发现想 ...

  6. 用户请求队列化_爬虫架构消息队列应用场景及ActiveMQ、RabbitMQ、RocketMQKafka

    前言:在之前的业务中,使用了Kafka和RabbitMQ两种消息队列,这篇文章来做一个总结. 消息队列中间件是分布式系统中重要的组件,主要实现异步消息,应用解耦,流量削峰及消息通讯等功能. 下面举例说 ...

  7. mysql消息队列的原理_PHP和MySQL实现消息队列

    最近遇到一个批量发送短信的需求,短信接口是第三方提供的.刚开始想到,获取到手机号之后,循环调用接口发送不就可以了吗? 但很快发现问题:当短信数量很大时,不仅耗时,而且成功率很低. 于是想到,用PHP和 ...

  8. activiti异步执行_对基于消息队列的Activiti异步执行器进行基准测试

    activiti异步执行 一点历史 永无休止的一件事是,Activiti在某些非常大的规模的大型组织中的使用方式. 过去,这导致了各种优化和重构,其中包括异步执行器-替换旧的作业执行器. 对于未启动的 ...

  9. rocketmq 如何保证高可用_如何保证消息队列是高可用的

    为什么写这篇文章? 博主有两位朋友分别是小A和小B: 小A,工作于传统软件行业(某社保局的软件外包公司),每天工作内容就是和产品聊聊需求,改改业务逻辑.再不然就是和运营聊聊天,写几个SQL,生成下报表 ...

最新文章

  1. vue实现pdf导出,解决生成canvas模糊等问题
  2. 关于批量发布blog的问题
  3. 在SAE搭建Python+Django+MySQL(基于Windows)
  4. shell脚本一键安装nginx
  5. 雅马哈机器人左手右手系统_消防管件组装成机器人 PM值临界时会报警并自动喷淋...
  6. 修改网站首页批处理_几个神奇的批处理,万事不求人!
  7. php启用openssl,php开启openssl的方法
  8. Nginx学习_狂神
  9. 【ElasticSearch】Es 源码之 快照 RepositoriesModule RepositoriesService 源码解读
  10. pillow api
  11. Ubuntu帮大忙了
  12. 《网络营销实战密码》书评征文获奖名单揭晓
  13. java中PrepareStatement使用的一点小问题
  14. 视图数据共享之SESSION/CACHE
  15. 微信小程序电商实战-购物车(下)
  16. DSP实验报告—实验1
  17. 云展网教程 | 如何更改logo和设置点击logo时的转跳链接?
  18. 2021-07-02-MySQL必知必会-笔记
  19. css3动画实现3d旋转效果
  20. 一个扫描器搞定TCP协议所有问题

热门文章

  1. Win7减肥攻略及小技巧
  2. T48568 【zzy】yyy送礼物
  3. Python程序设计基础第二版董付国版课后习题答案
  4. Pippo已经不能只用超级来形容了
  5. tomcat报错405
  6. Amy-Tabb机器人世界手眼标定(2、实验结果)
  7. 一只蝴蝶引发的海啸:垂死的CDN行业风云再起
  8. gis与计算机科学之间的联系,GIS与地图学及电子地图
  9. GIS电子地图定制开发技术
  10. HTML5七夕情人节表白网页(结婚倒计时) HTML+CSS+JS 求婚 html生日快乐祝福代码网页 520情人节告白代码 程序员表白源码 3D旋转相册 js烟花代码 css爱心表白