第4章 进程间通信 3.

Slides:



Advertisements
Similar presentations
第一讲:导论 The Introduction  哲学与中国哲学  哲学与哲学史  中国哲学史的历史.
Advertisements

数据结构的引入. 通讯录管理 社团机构管理 校园导航管理 通讯录管理 社团机构管理 校园导航管理.
阻塞操作. 在 linux 里,一个等待队列由一个 wait_queue_head_t 类型的结构来描述 等待队列的初始化: static wait_queue_head_t testqueue; init_waitqueue_head(&testqueue);
代理商入件流程.
小学生游戏.
C++中的声音处理 在传统Turbo C环境中,如果想用C语言控制电脑发声,可以用Sound函数。在VC6.6环境中如果想控制电脑发声则采用Beep函数。原型为: Beep(频率,持续时间) , 单位毫秒 暂停程序执行使用Sleep函数 Sleep(持续时间), 单位毫秒 引用这两个函数时,必须包含头文件
在PHP和MYSQL中实现完美的中文显示
Kvm异步缺页中断 浙江大学计算机体系结构实验室 徐浩.
複習 struct score_Type{ int chinese,english; }; struct my_Type{
chapter 1-Introduction
Hadoop I/O By ShiChaojie.
佇列 (Queue).
多进程编程.
进程及进程管理 第4章 进程及进程管理.
实践演练 广州创龙电子科技有限公司 01 广州创龙电子科技有限公司
走进编程 程序的顺序结构(二).
临界区软件互斥软件实现算法.
中国科学技术大学计算机系 陈香兰(0512- ) Autumn 2010
进程操作.
第一单元 初识C程序与C程序开发平台搭建 ---观其大略
文件读写实践 广州创龙电子科技有限公司 01 广州创龙电子科技有限公司
第十章 IDL访问数据库 10.1 数据库与数据库访问 1、数据库 数据库中数据的组织由低到高分为四级:字段、记录、表、数据库四种。
临界区软件互斥软件实现算法 主讲教师:夏莹杰
Windows 7 的系统设置.
用event class 从input的root文件中,由DmpDataBuffer::ReadObject读取数据的问题
第七章 操作符重载 胡昊 南京大学计算机系软件所.
宁波市高校慕课联盟课程 与 进行交互 Linux 系统管理.
第2章 进程管理 2.1 进程概念 2.2 线程 2.3 进程管理 2.4 进程间通信 2.5 经典进程同步问题 2.6 管程
宁波市高校慕课联盟课程 与 进行交互 Linux 系统管理.
SOA – Experiment 2: Query Classification Web Service
实验二、线程同步与通信 一、实验目的 1、掌握Linux下线程的概念; 2、了解Linux线程同步与通信的主要机制;
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
内容摘要 ■ 课程概述 ■ 教学安排 ■ 什么是操作系统? ■ 为什么学习操作系统? ■ 如何学习操作系统? ■ 操作系统实例
简单介绍 用C++实现简单的模板数据结构 ArrayList(数组, 类似std::vector)
$9 泛型基础.
实验三、共享内存与进程同步 一、实验目的 1、掌握Linux下共享内存的概念与使用方法; 2、掌握环形缓冲的结构与使用方法;
实验三、共享内存与进程同步 一、实验目的与要求 二、实验内容
本节内容 随机读取 视频提供:昆山爱达人信息技术有限公司.
DQMClientDim.cxx及双光子练习
本节内容 消息的分发 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
线 性 代 数 厦门大学线性代数教学组 2019年4月24日6时8分 / 45.
第二章 Java基本语法 讲师:复凡.
分裂对象模型 C++ otcl.
工业机器人知识要点解析 (ABB机器人) 主讲人:王老师
<编程达人入门课程> 本节内容 内存的使用 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群: ,
Select模型 本节内容 视频提供:昆山爱达人信息技术有限公司 视频录制:yang 官网地址:
本节内容 Win32 API中的宽字符 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
成绩是怎么算出来的? 16级第一学期半期考试成绩 班级 姓名 语文 数学 英语 政治 历史 地理 物理 化学 生物 总分 1 张三1 115
信号量(Semaphore).
第4章 Excel电子表格制作软件 4.4 函数(一).
iSIGHT 基本培训 使用 Excel的栅栏问题
3.16 枚举算法及其程序实现 ——数组的作用.
本节内容 文件系统 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第二章 基本数据类型 ——数据的表示.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
Visual Basic程序设计 第13章 访问数据库
C++语言程序设计 C++语言程序设计 第六章 指针和引用 第十一组 C++语言程序设计.
本节内容 消息的接收 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
GIS基本功能 数据存储 与管理 数据采集 数据处理 与编辑 空间查询 空间查询 GIS能做什么? 与分析 叠加分析 缓冲区分析 网络分析
本节内容 Windows线程切换_时钟中断切换 视频提供:昆山滴水信息技术有限公司 官网地址: 论坛地址: QQ交流 :
WSAAsyncSelect 模型 本节内容 视频提供:昆山爱达人信息技术有限公司 视频录制:yang
阻塞式模型 本节内容 视频提供:昆山爱达人信息技术有限公司 视频录制:yang 官网地址:
基于列存储的RDF数据管理 朱敏
C++语言程序设计 C++语言程序设计 第一章 C++语言概述 第十一组 C++语言程序设计.
本节内容 动态链接库 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
第四章 UNIX文件系统.
第三章 流程控制 程序的运行流程 选择结构语句 循环结构语句 主讲:李祥 时间:2015年10月.
本节内容 SEMAPHORE 视频提供:昆山滴水信息技术有限公司 官网地址: 论坛地址: QQ交流 :
《操作系统设计与实现》 Linux系统编程.
Presentation transcript:

第4章 进程间通信 3

4.4 Linux消息缓冲通信(消息队列) 4.4.1 消息缓冲通信概述 消息队列满足IPC通信机制的通用规则:使用一个消息队列标识符(键值key,参考上节中的ipc_perm结构)来唯一标识一个消息队列,并依此检查访问权限。 通过多进程共享同一个消息队列实现。 消息队列本身是一个临界资源,需实现互斥操作。 2018/12/6 操作系统与实验 第4章2

2. Linux消息缓冲通信的数据结构 ⑴.消息缓冲区msgbuf 该数据结构用来存放需要发送或接收的消息类型和消息正文。 /usr/src/linux-2.4/include/linux/msg.h文件中描述如下: /* message buffer for msgsnd and msgrcv calls */ struct msgbuf { long mtype; //消息类型,由用户约定 char mtext[1]; //消息正文 }; mtext[1]是消息正文,该域可由程序员定义为任意数据结构,但消息及消息队列的长度有限,其设置在系统配置时可以改变,其缺省值定义在 /usr/src/linux-2.4/include/linux/msg.h中: #define MSGMNI 16 /* <= IPCMNI */ /* max # of msg queue identifiers */ #define MSGMAX 8192 /* <= INT_MAX */ /* max size of message (bytes) */ #define MSGMNB 16384 /* <= INT_MAX */ /* default max size of a message queue */ 2018/12/6 操作系统与实验 第4章2

2. Linux消息缓冲通信的数据结构 ⑵.每条消息使用一个数据结构msg_msg进行描述,并通过指针*next与msgbuf链接成一个完整的消息实体。同一消息队列中的消息通过m_list表组织起来,形成一个满足同一key值的消息队列。 msg_msg数据结构在文件/usr/src/linux-2.4/ipc/msg.c中定义为: /* one msg_msg structure for each message */ struct msg_msg { struct list_head m_list; long m_type; int m_ts; /* message text size */ struct msg_msgseg* next; /* the actual message follows immediately */ }; 2018/12/6 操作系统与实验 第4章2

⑶.消息队列链表msgque Linux内核维护一个消息队列链表msgque,该表描述了当前系统中的消息队列。链表中每个元素指向一个描述消息队列的kern_ipc_perm结构,以及与该消息队列有关的3个队列结构的头元素:消息缓冲队列、接收进程等待队列、发送进程等待队列。同时,还保留有关队列变动的时间以及进程标识等信息。其结构定义在/usr/src/linux-2.4/ipc/msg.c文件中: /* one msq_queue structure for each present queue on the system */ struct msg_queue { struct kern_ipc_perm q_perm; time_t q_stime; /* last msgsnd time */ time_t q_rtime; /* last msgrcv time */ time_t q_ctime; /* last change time */ unsigned long q_cbytes; /* current number of bytes on queue */ unsigned long q_qnum; /* number of messages in queue */ unsigned long q_qbytes; /* max number of bytes on queue */ pid_t q_lspid; /* pid of last msgsnd */ pid_t q_lrpid; /* last receive pid */ struct list_head q_messages; struct list_head q_receivers; struct list_head q_senders; }; 2018/12/6 操作系统与实验 第4章2

3. Linux消息缓冲通信数据结构之间的关系 msg_queue 发送进程pid 接收进程pid …… msg_msg *next msgbuf i ker_ipc_perm key q_messages q_receivers q_sanders 图‑给定key值的消息队列 2018/12/6 操作系统与实验 第4章2

发送消息原语与接收消息原语的同步互斥算法描述如下: /*mutex 为互斥信号量,s1表示消息队列上是否有消息,s2表示消息队列是否有空(允许长度)*/ int mutex= 1,s1=0,s2=n; /*发送消息原语*/ send() { P(s2); P(mutex); 将消息缓冲区msgbuf挂到消息队列; V(mutex); V(s1); } /*接收消息原语*/ receive() { P(s1); P(mutex); 从消息队列取消息缓冲区msgbuf; V(mutex); V(s2) } 2018/12/6 操作系统与实验 第4章2

4. 发送和接收消息执行过程 2018/12/6 操作系统与实验 第4章2

发送消息进程与接收消息进程: 发送进程在调用send()原语之前,先要作好以下准备工作: ⑴.申请一个消息缓冲区msgbuf; 接收进程在接收到消息后要做以下善后处理: ⑴.将消息缓冲区msgbuf中的消息复制到进程存储空间; ⑵.释放消息缓冲区msgbuf; 2018/12/6 操作系统与实验 第4章2

共提供了4个系统调用 4.4.2 Linux消息缓冲通信的系统调用 msgget() Msgsnd() msgrcv() Msgctl() 所用头函数: # include <sys/types.h > # include <linux/msg.h > 2018/12/6 操作系统与实验 第4章2

4.4.2 Linux消息缓冲通信的系统调用 1. 创建一个消息队列或获取已存在消息队列的标识 格式: 功能: 参数说明: 返回: 1. 创建一个消息队列或获取已存在消息队列的标识 格式: int msgget ( key_t key, int msgflag ); 功能: 创建标识为key值的消息队列或者获取已存在的消息队列的描述符msgid。 参数说明: msgqid——该系统调用返回的消息队列描述符,-1表示失败; key——用户指定的消息队列标识符,为一正整数,其值可以由用户指定,如果使用IPC_PRIVATE则由系统产生key值; flag——用户设置的标志或访问方式,其值由操作权限和控制命令进行或运算得到。 返回: 正确返回该消息队列的描述符msgid; 错误返回-1。 通常使用语句:msgid = msgget(Key, 0666|IPC_CREAT); 2018/12/6 操作系统与实验 第4章2

2. 发送一条消息到指定的消息队列 格式: 功能: 参数说明: 返回: 2. 发送一条消息到指定的消息队列 格式: int msgsnd( int msgid, struct msgbuf*msgp, int size, int flag ); 功能: 发送一个消息给指定描述符的消息队列。将msgp所指向的msgbuf中的消息复制到消息数据结构并挂到指定消息队列尾,唤醒等待消息的进程。 参数说明: msgid——执行msgget()返回的消息队列的描述符; msgp——指向用户存储区的一个消息缓冲msgbuf的指针,在msgbuf中包含消息类型和消息正文,其结构参见4.4.1 节 size——由msgp指向的数据结构中字符数组的长度(消息长度); flag ——规定当核心用尽内部空间时应执行的动作,例如:若在flag中设置了IPC_NOWAIT,则当消息队列中的字节数超过最大值msgsnd立即返回,否则msgsnd睡眠。flag可置0。 返回: 成功返回0; 错误返回-1。 2018/12/6 操作系统与实验 第4章2

3. 从消息队列接收消息 格式: 功能: 参数说明: 返回: 3. 从消息队列接收消息 格式: int msgrcv( int msgid, struct msgbuf*msgp, int size, int type, int flag); 功能: 从指定的消息队列接收一个消息。将消息复制到msgp所指的msgbuf中,从消息队列中删除此消息,若消息未到则调用进程阻塞插入等待消息队列尾。 参数说明: msgid——消息队列描述符; msgp—— 用来存放要接收消息的用户消息缓冲msgbuf的地址; size ——msgp中数据数组的大小; type——用户要读的消息类型: =0--接收队列的第一个消息; >0--接收类型type的第一个消息; <0—接收小于或等于|type|的最低类型的第一个消息。 flag——规定若该队列无消息,操作系统核心应当做什么,可置0。 返回: 成功返回接收到的数据长度; 错误返回-1。 2018/12/6 操作系统与实验 第4章2

4. 对消息队列的操作 格式: 功能: 参数说明: 返回: 4. 对消息队列的操作 格式: int msgctl( int msgid, int cmd, struct msgid_ds *buf ); 功能: 查询一个消息队列的状态;设置或修改它的状态;撤消一个消息队列。 参数说明: msgid——该消息队列的描述符; cmd——规定命令的类型: IPC_STAT查询消息队列状态,将与msgid相关联的消息队列首标读入buf; IPC_SET设置或修改消息队列状态,设置有效用户、组标识、操作允许权,及字节数; IPC_RMID撤消描述符为msgid的消息队列; Buf——含有控制参数或查询结果的用户缓冲区的地址,可为0。 返回: 调用成功返回0, 不成功返回-1。 注意: 设置和撤消消息队列的进程需要有一定的权限,如超级用户、具有有效用户ID、符合msg_perm权限设置。 2018/12/6 操作系统与实验 第4章2

4.4.3 消息缓冲通信应用举例 1. 使用方法 ⑴.使用系统调用函数msgget()创建或者获取指定key值的消息队列: 4.4.3 消息缓冲通信应用举例 1. 使用方法 ⑴.使用系统调用函数msgget()创建或者获取指定key值的消息队列: 给定key值的消息队列不存在时为创建,已创建后再执行为获取。 消息缓冲区定义: struct my_msg { long int my_msg_type; char some_text[MAXMSG]; }msg; 用户缓冲区定义: char buffer[BUFSIZ]; 2018/12/6 操作系统与实验 第4章2

4.4.3 消息缓冲通信应用举例 ⑵.发送消息进程使用发送消息系统调用函数msgsnd()发送消息;接收进程使用系统调用函数msgrcv()接收消息。 将buffer中的消息复制到消息缓冲区,然后发送消息缓冲区到消息队列: msg.my_msg_type=1; //设置消息类型为1 strcpy(msg.some_text,buffer); //将buffer的消息复制到消息缓冲区 msgsnd(msgid,&msg,512,0); //发消息到消息队列 从消息msgid队列上接收一个消息并显示消息内容: msgrcv(msgid,&msg, BUFSIZ, 0, 0); printf(“%s”,msg.some_text); ⑶.消息队列不再使用时,使用系统调用函数msgctl()删除消息队列。 msgctl(msgid,IPC_RMID,0); //撤消指定的消息队列 2018/12/6 操作系统与实验 第4章2

4.4.3 消息缓冲通信应用举例 [例4-5] 编程实现消息的发送与接收: 4.4.3 消息缓冲通信应用举例 [例4-5] 编程实现消息的发送与接收: 发送进程sndfile.c,将要发送的消息从键盘输入,每输入一行就作为一条消息发送,用“end”作为结束消息。 接收进程rcvfile.c从消息队列上逐个取出消息并显示输出,也用“end” 作为结束消息。设消息队列的key为1234。 结束信息“end”的判断可以使用函数:strncmp(str1,str2,n); 其中n表示需要比较的字符个数; 其功能是比较str1和str2的前n个字符。 2018/12/6 操作系统与实验 第4章2

2018/12/6 操作系统与实验 第4章2 发送进程sndfile.c #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<sys/types.h> #include<linux/msg.h> #define MAXMSG 512 //定义消息长度 struct my_msg //定义消息缓冲区数据结构 { long int my_msg_type; char some_text[MAXMSG]; }msg; main( ) int msgid; //定义消息缓冲区内部标识 char buffer[BUFSIZ]; //定义用户缓冲区 msgid=msgget(1234,0666|IPC_CREAT); //创建消息队列,key为1234 while(1) puts("Enter some text:"); //提示键入消息内容 fgets(buffer,BUFSIZ,stdin); //标准输入送buffer msg.my_msg_type=1; //设置消息类型为1 strcpy(msg.some_text,buffer); //buffer送消息缓冲 msgsnd (msgid,&msg,MAXMSG,0); //发送消息到消息队列 if(strncmp(msg.some_text,"end",3)==0) /消息为“end”则结束 break; } exit(0); } 2018/12/6 操作系统与实验 第4章2

2018/12/6 操作系统与实验 第4章2 接收进程rcvfile.c #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<sys/types.h> #include<linux/msg.h> #define MAXMSG 512 //定义消息长度 struct my_msg //定义消息f缓冲区数据结构 { long int my_msg_type; char some_text[MAXMSG]; }msg; main() int msgid; //定义消息缓冲区内部标识 long int msg_to_receive=0; msgid=msgget(1234, 0666|IPC_CREAT); //获取消息队列,key为1234 while (1) msgrcv (msgid, &msg, BUFSIZ, msg_to_receive, 0); //接收消息 printf ("You wrote:%s",msg.some_text); //显示消息 if (strncmp (msg.some_text,"end",3)==0) //消息为“end”则结束 break; } msgctl (msgid, IPC_RMID,0); //撤消消息队列 exit (0); 2018/12/6 操作系统与实验 第4章2

4.4.3 消息缓冲通信应用举例 在创建或获取一个消息缓冲队列时,其key值可以由用户给出也可以由系统生成。本例中,由于发送与接收是两个完全独立的进程,因此双方只能使用事先约定好的key值,以用户指定的方式给出。如果发送和接收进程都是同一个家族的子进程,则可以由其祖先创建后,子孙使用,因而可以采用由系统指定key值的方式,这种情况可以使用参数IPC_PRIVATE取代我们设定的key值1234。 2018/12/6 操作系统与实验 第4章2

小结 消息缓冲优缺点、适用场合及其应用 自带同步工具,使用起来较方便。(优点) 该通信方式不适合信息量大或信息交换频繁的场合。 (缺点) 存在用户普通缓冲区与消息缓冲区之间的信息复制过程,时间开销较大。 消息缓冲区自数据结构msg_msg存在空间的开销。 消息队列机制是客户/服务器模型中常用的进程通信方式。 2018/12/6 操作系统与实验 第4章2

作业 第4章 4、5、6 2018/12/6 操作系统与实验 第4章2