进程间通信 方法总结
进程间通信的四种方式

一、剪贴板1、基础知识剪贴板实际上是系统维护管理的一块内存区域,当在一个进程中复制数据时,是将这个数据放到该块内存区域中,当在另一个进程中粘贴数据时,是从该内存区域中取出数据。
2、函数说明:(1)、BOOL OpenClipboard( )CWnd类的OpenClipboard函数用于打开剪贴板。
若打开剪贴板成功,则返回非0值。
若其他程序或当前窗口已经打开了剪贴板,则该函数返回0值,表示打开失败。
若某个程序已经打开了剪贴板,则其他应用程序将不能修改剪贴板,直到前者调用了CloseClipboard函数。
(2)、BOOL EmptyClipboard(void)EmptyClipboard函数将清空剪贴板,并释放剪贴板中数据的句柄,然后将剪贴板的所有权分配给当前打开剪贴板的窗口。
(3)、HANDLE SetClipboardData(UINT uFormat, HANDLE hMem)SetClipboardData函数是以指定的剪贴板格式向剪贴板上放置数据。
uFormat指定剪贴板格式,这个格式可以是已注册的格式,或是任一种标准的剪贴板格式。
CF_TEXT表示文本格式,表示每行数据以回车换行(0x0a0x0d)终止,空字符作为数据的结尾。
hMem指定具有指定格式的数据的句柄。
hMem参数可以是NULL,指示采用延迟提交技术,则该程序必须处理WM_RENDERFORMA T和WM_RENDERALLFORMATS消息。
应用程序在调用SetClipboardData函数之后,就拥有了hMem参数所标识的数据对象,该应用程序可以读取该数据对象,但在应用程序调用CloseClipboard函数之前,它不能释放该对象的句柄,或者锁定这个句柄。
若hMem标识了一个内存对象,那么这个对象必须是利用GMEM_MOVEABLE标志调用GlobalAlloc函数为其分配内存。
注意:调用SetClipboardData函数的程序必须是剪贴板的拥有者,且在这之前已经打开了剪贴板。
进程间通信的方式及应用场景

进程间通信的⽅式及应⽤场景开头 每个进程的⽤户地址空间都是独⽴的,进程与进程之间,内部空间是隔离的,进程 A 不可能直接使⽤进程 B 的变量名的形式得到进程B 中变量的值。
但内核空间是每个进程都共享的,所以进程之间要通信必须通过内核。
实现进程与进程之间的通信,常⽤的⽅式主要有:管道、消息队列、共享内存、信号量、信号、socket等等。
⼀、管道 在 Linux 命令中,常见的“|”符号就是⼀种管道。
⽐如:ps auxf | grep mysql 上⾯的命令中,“|”的功能是将前⼀个命令(ps auxf)的输出,作为后⼀个命令(grep mysql)的输⼊。
这种管道没有名字,匿名管道,⽤完就销毁。
命名管道也被叫做 FIFO,因为数据的传输⽅式是先进先出(first in first out)。
管道传输数据是单向的,如果想相互通信,需要创建两个管道才⾏。
管道创建、写⼊、读取创建mkfifo myPipe myPipe 是新创建的管道的名称,基于 Linux ⼀切皆⽂件的理念,管道也是以⽂件的⽅式存在,可以⽤ ls 看到⽂件类型是 p,也就是pipe(管道)的意思:$ ls -lprw-r--r--. 1 root root 0 Jul 1702:45 myPipeecho "hello" > myPipe # 将数据写进管道。
程序会阻塞,只有当管道⾥的数据被读完后,程序才会正常继续。
管道写⼊数据cat < myPipe # 读取管道⾥的数据# hello管道读取数据管道的优缺点 缺点:管道的通信⽅式效率低,不适合进程间频繁地交换数据。
优点:简单。
⼆、消息队列 前⾯说到管道的通信⽅式效率很低,因此管道不适合进程间频繁地交换数据。
对于这个问题,消息队列可以解决。
⽐如,A 进程要给 B 进程发送消息,A 进程将数据存⼊消息队列,B 进程只需要读取数据即可。
反之亦如此。
消息队列的本质是保存在内核中的⼀种消息链表,在发送数据时,会分成独⽴的数据单元,也就是消息体(数据块)。
安卓进程间通信的四种方式(含案例)

安卓进程间通信的四种方式(含案例)Android通过进程间通信(IPC)技术来共享数据和资源,可以有效的提高应用程序的性能和可靠性。
Android共有四种进程间通信(IPC)方式:AIDL、ContentProvider、Messenger和Socket。
AIDL(Android Interface Definition Language)
AIDL(Android接口定义语言)是Android所提供的接口定义语言,可用于定义远程过程调用,也称为跨应用程序的远程过程调用(RPC)。
AIDL介绍远程调用的一种标准格式,可以实现不同应用之间的调用,非常适合用于安卓系统中的多进程通信。
案例:
AIDL应用示例:假设一个应用程序运行在安卓设备上,该应用程序既能监控设备的状态(如CPU使用率),也能向其他应用程序提供数据(如功耗数据)。
这时,如果要实现应用程序之间的交流,就需要使用AIDL,而且可以将AIDL程序集成到已有的应用程序中。
ContentProvider
ContentProvider是Android提供的IPC(进程间通信)机制,它可以被称为数据共享的另一种形式。
ContentProvider允许一个应用程序可以将它的数据共享给其他的应用程序,而不需要访问外部的数据库,这是一个非常安全有效的过程。
案例:。
进程通信的几种方法

进程通信的几种方法进程通信是指在操作系统中,不同的进程之间进行数据交换和信息传递的过程。
在现代操作系统中,进程通信是非常重要的,因为多个进程之间的协作可以提高系统的性能和效率。
本文将介绍几种常见的进程通信方法。
1.管道通信管道通信是一种单向、半双工的通信方式,通过创建一个管道,将一个进程的输出连接到另一个进程的输入,从而实现数据的传输。
管道通信一般用于具有父子关系的进程之间或者具有共同祖先的进程之间。
2.消息队列通信消息队列通信是一种通过操作系统内核来传递消息的机制。
进程可以将消息发送到消息队列,其他进程则可以从消息队列中接收消息。
消息队列通信具有高效、可靠、灵活等特点,常用于进程之间传递数据量较大的情况。
3.共享内存通信共享内存通信是一种进程间共享内存区域的方式。
多个进程可以访问同一块内存区域,从而实现数据的共享。
共享内存通信的优点是速度快,因为进程之间不需要进行数据的复制,但是需要进程之间进行同步和互斥操作,以避免数据的冲突。
4.信号量通信信号量通信是一种通过操作系统提供的信号量机制来实现进程间同步和互斥的方式。
进程可以通过信号量来进行互斥操作,以确保共享资源的安全访问。
信号量通信常用于进程之间共享资源的管理和同步。
5.套接字通信套接字通信是一种通过网络进行进程通信的方式,常用于不同主机之间的进程通信。
套接字通信可以通过TCP或UDP协议来实现,具有跨平台、可靠性高等特点。
总结起来,进程通信是操作系统中非常重要的一部分,不同的进程之间可以通过各种方式进行数据的交换和信息的传递。
管道通信、消息队列通信、共享内存通信、信号量通信和套接字通信是常见的几种进程通信方法。
不同的通信方法适用于不同的场景,开发人员需要根据具体需求选择合适的通信方式。
进程通信的正确使用可以提高系统的性能和效率,确保系统的稳定运行。
IT面试题:进程间的通信方式有哪几种

进程间的通信方式,其实我们一直在用它,但是我们都不会去注意它。
如果碰到面试官问你知道多少种进程间的通信方式,估计很多人都会有点懵。
今天我们就来总结下进程间的通信方式有哪些。
进程间通信的7种方式:1、管道/匿名管道(管道)管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道。
只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。
数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
(1)管道的实质:管道的实质是一个内核缓冲区,进程以先进先出的方式从缓冲区存取数据,管道一端的进程顺序的将数据写入缓冲区,另一端的进程则顺序的读出数据。
该缓冲区可以看做是一个循环队列,读和写的位置都是自动增长的,不能随意改变,一个数据只能被读一次,读出来以后在缓冲区就不复存在了。
当缓冲区读空或者写满时,有一定的规则控制相应的读进程或者写进程进入等待队列,当空的缓冲区有新数据写入或者满的缓冲区有数据读出来时,就唤醒等待队列中的进程继续读写。
(2)管道的局限:管道的主要局限性正体现在它的特点上:①只支持单向数据流;②只能用于具有亲缘关系的进程之间;③没有名字;④管道的缓冲区是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小);⑤管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令,或记录)等等;2、有名管道(FIFO)匿名管道,由于没有名字,只能用于亲缘关系的进程间通信。
为了克服这个缺点,提出了有名管道(FIFO)。
有名管道不同于匿名管道之处在于它提供了一个路径名与之关联,以有名管道的文件形式存在于文件系统中,这样,即使与有名管道的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过有名管道相互通信,因此,通过有名管道不相关的进程也能交换数据。
linux下进程通信的八种方法

linux下进程通信的八种方法在Linux下,有多种方法可以实现进程间的通信。
以下是八种常用的进程通信方法:
1. 管道(Pipe):管道是一种半双工通信方式,可用于具有亲缘关系的父子进程之间进行通信。
2. 命名管道(Named Pipe):命名管道也称为FIFO(First In, First Out),它可以在无亲缘关系的进程之间进行通信。
3. 信号(Signal):进程通过发送信号给其他进程来进行通信,例如,某些特定事件发生时,一个进程可以向另一个进程发送一个信号。
4. 消息队列(Message Queue):进程可以通过消息队列发送和接收消息,消息队列提供了一种先进先出的消息传递机制。
5. 共享内存(Shared Memory):多个进程可以共享同一块内存区域,进程可以直接读写该内存区域来进行通信。
6. 信号量(Semaphore):信号量用于进程间的互斥和同步,可以控制对共享资源的访问。
7. 套接字(Socket):套接字是一种网络编程中常用的通信机制,在本地主机或网络上不同主机的进程之间进行通信。
8. 文件锁(File Locking):进程可以使用文件锁来实现对某个文件或资源的独占访问。
linux进程间通讯的几种方式的特点和优缺点
linux进程间通讯的几种方式的特点和优缺点Linux进程间通讯的方式有多种,其优缺点也不尽相同,接受者依赖发送者之时间特性可承载其优端。
下面就讨论几种典型的方式:1、管道(Pipe):是比较传统的方式,管道允许信息在不同进程之间传送,由一端输入,另一端输出,提供全双工式劝劝信息传送,除此之外,伺服端也可以将其服务转换为管道,例如说Web服务程序。
管道的优点:简单易懂、可靠、灵活、容易管理,可以控制发送端和接收端的信息流量。
管道的缺点:线程之间的信息量不能太大,也只能在本机上使用,不能通过网络发送信息。
2、消息队列(Message queue):消息队列主要应用在大型网络中,支持多种消息队列协议,广泛用于在远程机器上的进程间的交互、管理进程间的数据和同步问题。
消息队列的优点:主要优点是这种方式可以将消息发送给接收端,然后接收端可以从距离发送端远的地方网络上接收消息,通过消息队列可以较好的管理和控制进程间的数据流量和同步问题。
消息队列的缺点:缺点是消息队里的管理复杂,并且有一定的延迟,而且它使用时应避免共享内存,对于多处理器和跨网络环境, TCP 传输数据时也比不上消息队列的传输效率高。
3、共享内存(Share Memory):是最高效的进程间通信方式,也是最常用的,它使进程在通信时共享一个存储地址,双方都可以以该存储地址作为参数进行读写操作。
共享内存的优点:实现高性能,数据同步操作快、数据可以高速传输,可以解决多处理器以及跨网络环境的通信。
共享内存的缺点:由于进程间直接使用物理内存,没有任何保护,所需要使用较复杂的同步机制来完成数据的可靠传输。
总的来说,每种进程通讯方式都有各自的优缺点,不同的系统需求也许需要多种方案的相互配合才能有效的处理系统间通信的问题。
系统设计者应根据具体系统需求,选择合适的进程通信方式来实现更好的进程间通信。
操作系统的消息传递和进程间通信实现进程间的信息传递和通信
操作系统的消息传递和进程间通信实现进程间的信息传递和通信操作系统是计算机中非常重要的一个组成部分,它负责管理和控制计算机的硬件和软件资源。
在多道程序设计环境下,操作系统需要负责调度和管理多个进程的执行。
而进程间的信息传递和通信是操作系统中一个关键的功能,它使得不同进程之间能够相互交互、传递数据,从而实现协同工作和资源共享。
本文将探讨操作系统中的消息传递和进程间通信,以及它们的实现方法和技术。
一、消息传递在操作系统中,进程间的信息传递可以通过消息传递的方式来实现。
消息传递是指一个进程向另一个进程发送消息,并由接收进程接收和处理该消息。
消息传递可以用于进程间的同步和通信,从而实现进程之间的交互。
消息传递一般包括以下几个步骤:1. 消息的创建:发送进程首先需要创建一条消息,并在消息中填写相应的内容。
消息可以包含数据、指令等信息,以满足不同的需求。
2. 消息的发送:发送进程将创建好的消息发送给接收进程。
发送进程需要指定接收进程的标识符,以确保消息能够被正确地发送到目标进程。
3. 消息的接收:接收进程通过等待操作等待消息的到达。
当消息到达时,接收进程将检查消息的标识符,以确定该消息是否是自己所期望接收的。
4. 消息的处理:接收进程接收到消息后,会对消息进行处理。
处理的方式取决于消息的内容和接收进程的需求。
消息传递可以有两种方式:直接消息传递和间接消息传递。
直接消息传递是指发送进程直接发送消息给接收进程。
间接消息传递是指通过操作系统的消息队列来传递消息。
不同的方式适用于不同的场景和需求。
二、进程间通信的实现为了实现进程间的信息传递和通信,操作系统提供了多种机制和技术。
以下是几种常见的进程间通信的实现方式:1. 共享内存共享内存是一种在多个进程之间共享同一块物理内存的方式。
通过将一块内存区域映射到多个进程的地址空间中,进程可以通过读写共享内存的方式来进行通信。
共享内存的优点是速度快,但需要进程之间进行同步和互斥操作,以避免数据的冲突和错误。
简述linux中进程间各种通信方式特点
简述linux中进程间各种通信方式特点Linux中进程间通信方式有多种,包括管道,命名管道,消息队列,信号量,共享内存和套接字。
每种通信方式都有自己的特点和适用场景。
一、管道1. 特点:- 管道是最简单的进程间通信方式之一,只能用于具有父子关系的进程间通信。
- 管道是一个单向通道,数据只能在一个方向上流动。
- 管道的容量有限,在写度满之前,读进程阻塞;在读度空之前,写进程阻塞。
2. 使用场景:- 父子进程之间需要进行简单的数据传输。
二、命名管道1. 特点:- 命名管道是一种特殊类型的文件,可以实现不相关进程的通信。
- 命名管道是半双工的,只能在一个方向上传输数据。
- 命名管道是顺序读写的,进程可以按照顺序读取其中的数据。
2. 使用场景:- 不相关的进程需要进行数据传输。
- 需要按照顺序进行传输的场景。
三、消息队列1. 特点:- 消息队列是一组消息的链表,具有特定的格式和标识符。
- 消息队列独立于发送和接收进程的生命周期,可以实现不相关进程间的通信。
- 消息队列可以根据优先级进行消息的传输。
2. 使用场景:- 需要实现进程间相对复杂的数据传输。
- 数据传输具有优先级。
四、信号量1. 特点:- 信号量是一个计数器,用于实现多个进程之间的互斥和同步。
- 信号量有一个整数值,只能通过定义的操作进行访问。
- 信号量可以用于控制临界区的访问次数。
2. 使用场景:- 多个进程需要共享公共资源。
- 需要进行互斥和同步操作。
五、共享内存1. 特点:- 共享内存是一块可以被多个进程共同访问的内存区域。
- 共享内存是最快的进程间通信方式,因为数据不需要在进程之间拷贝。
- 共享内存需要通过同步机制(如信号量)进行互斥访问。
2. 使用场景:- 需要高效地进行大量数据传输。
- 数据读写频繁,需要最小化数据拷贝的开销。
六、套接字1. 特点:- 套接字是一种网络编程中常用的进程间通信方式。
- 套接字支持不同主机上的进程进行通信。
linux的进程间的通信机制
linux的进程间的通信机制
Linux进程间通信的方式有多种,以下是一些常用的通信机制:
1. 管道(pipe):管道是一种半双工的通信方式,它可以在具
有父子关系的进程间进行通信。
管道有两种类型:普通管道(匿名管道)和命名管道(FIFO)。
2. 消息队列(message queue):消息队列是一种通过消息传
递进行进程间通信的机制。
进程可以通过将消息发送到消息队列中,另一个进程可以从该队列中读取消息。
3. 共享内存(shared memory):共享内存是一种高效的进程
间通信方式,允许多个进程访问同一段内存。
这种通信方式适用于需要大量数据交换的进程。
4. 信号(signal):信号是一种软件中断机制,用于通知进程
发生了一些特定事件。
发送信号的进程可以将信号发送给另一个进程,接收进程可以定义信号的处理函数。
5. 信号量(semaphore):信号量是一种用于进程同步和互斥
的机制。
它允许多个进程共享一个计数器,用于控制对临界资源的访问。
6. 套接字(socket):套接字是一种用于网络通信的机制,它
允许不同机器间的进程进行通信。
套接字提供了一种编程接口,使得进程可以通过互联网进行数据传输。
这些通信机制各有优缺点,应根据具体的需求选择合适的方式。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
WPC-DWC-0000版本: V1.0进程间通信方法总结2012/12/23目录第1章.文档说明 (1)第2章.进程间通信概述 (1)第3章.消息队列方法 (1)3.1.消息队列的基本概念 (1)3.2.消息队列的操作 (2)3.2.1.打开或创建消息队列 (2)3.2.2.读写消息队列 (3)3.3.消息队列应用实例 (6)第4章.共享内存方法 (9)4.1.共享内存的基本概念 (9)4.2.共享内存的操作 (9)4.2.1.创建共享内存 (10)4.2.2.映射共享内存 (11)4.3.共享内存应用实例 (12)第5章.管道方法 (16)5.1.管道的基本概念 (16)5.2.管道的操作 (17)5.3.管道应用实例 (17)第6章.信号量方法 (19)6.1.信号量的基本概念 (19)6.2.信号量的操作 (19)6.3.信号量应用实例 (21)第7章.小结 (23)Wireless System Laboratory(WST),无线系统研究室第1章.文档说明本文档主要介绍进程之间通信的几种方法,并且通过Linux下C语言代码运行验证。
第2章.进程间通信概述进程间通信就是在不同进程之间传播或交换信息,那么不同进程之间存在着什么双方都可以访问的介质呢?进程的用户空间是互相独立的,一般而言是不能互相访问的,唯一的例外是共享内存区。
但是,系统空间却是―公共场所‖,所以内核显然可以提供这样的条件。
除此以外,那就是双方都可以访问的外设了。
进程间通信的目的主要包括:●数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间。
●共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到。
●通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。
●资源共享:多个进程之间共享同样的资源。
为了作到这一点,需要内核提供锁和同步机制。
●进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。
进程间通信的方法主要有消息队列方法、共享内存方法、管道方法、信号量等,本文主要介绍这几种方法。
第3章.消息队列方法3.1. 消息队列的基本概念消息队列就是一个消息的链表。
可以把消息看作一个记录,具有特定的格式以及特定的优先级,本质就是内核地址空间中的内部链表。
对消息队列有写权限的进程可以向中按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读走消息。
消息队列是随内核持续的。
每个消息队列都有一个队列头,用结构struct msg_queue来描述。
队列头中包含了该消息队列的大量信息,包括消息队列键值、用户ID、组ID、消息队列中消息数目等等,甚至记录了最近对消息队列读写进程的ID。
读者可以访问这些信息,也可以设置其中的某些信息。
结构msg_queue如下,struct msg_queue {Wireless System Laboratory(WST),无线系统研究室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;};3.2. 消息队列的操作对消息队列的操作只有三种方式。
3.2.1.打开或创建消息队列消息队列的内核持续性要求每个消息队列都在系统范围内对应唯一的键值,所以,要获得一个消息队列的描述字,只需提供该消息队列的键值即可。
3.2.1.1. msgget ()简介为了创建一个新的消息队列,或者访问一个现有的队列,可以使用系统调用msgget()。
使用格式:int msgget(key_t key, int msgflg)msgget()的第一个变元是关键字的值。
这个关键字的值将被拿来与内核中其他消息队列的现有关键字值相比较。
比较之后,打开或者访问操作依赖于msgflg变元的内容。
IPC_CREAT—如果在内核中不存在该队列,则创建它。
IPC_EXCL—当与IPC_CREAT一起使用时,如果队列早已存在则将出错。
如果只使用了IPC_CREAT, msgget()或者返回新创建消息队列的消息队列标识符,或者会返回现有的具有同一个关键字值的队列的标识符。
如果同时使用了IPC_EXCL和IPC_CREAT,那么将可能会有两个结果。
或者创建一个新的队列,或者如果该队列存在,则调用将出错,并返回-1。
IPC_EXCL本身是没有什么用处的,但在与IPC_CREAT组合使用时,它可以用于保证没有一个现存的队列为了访问而被打开。
3.2.1.2. msgget ()举例下面实例演示了使用msgget函数创建一个队列,函数中参数falgs指定为Wireless System Laboratory(WST),无线系统研究室IPC_CREAT|0666,说明新建一个权限为0666的消息队列,其中组用户、当前用户以及其他用户拥有读写的权限。
并在程序的最后使用shell命令ipcs–q来查看系统IPC的状态。
(1)在vi编辑器中编辑该程序如下:#include <sys/msg.h>#include <sys/types.h>#include <sys/ipc.h>#include <stdio.h>#include <stdlib.h>int main ( void ){int qid;key_t key;key=113;qid=msgget(key,IPC_CREAT|0666);/* 创建一个消息队列*/if(qid<0){ /* 创建一个消息队列失败*/perror("msgget");exit(1);}printf("created queue id:%d \n", qid ); /* 输出消息队列的ID */system("ipcs -q"); /* 查看系统IPC 的状态*/exit ( 0 );}(2)在shell中编译该程序如下:$gcc create_msg.c–o create_msg(3)在shell中运行该程序如下:$./ create_msgcreated queue id : 163840------- Message Queues --------key msqid owner perms used-bytes messages0x00000071 163840 sun 666 0 0在程序中使用了系统命令ipcs,命令参数-q说明只查看消息队列的状态。
注意在输出消息中,key段标明的是IPC的key值,msqid为该队列的ID值,perms为执行权限。
同样,队列的执行权限像其他IPC对象一样没有执行权限。
3.2.2.读写消息队列一旦获得了队列标识符,用户就可以开始在该消息队列上执行相关操作了。
为了向队列传递消息,用户可以使用msgsnd系统调用。
由于消息队列的特殊性,系统为这个数据类型提供了两个接口(msgsnd函数,msgrcv函数),分别对应写消息队列及读消息队列。
将一个新的消息写入队列Wireless System Laboratory(WST),无线系统研究室3.2.2.1. msgsnd函数和msgrcv函数简介使用函数msgsnd,函数原型如下:#include <sys/msg.h>int msgsnd ( int msqid, const void *prt, size_t nbytes, int flags);对于写入队列的每一个消息,都含有三个值,正长整型的类型字段、数据长度字段和实际数据字节。
新的消息总是放在队列的尾部,函数中参数msqid指定要操作的队列,ptr指针指向一个msgbuf的结构,定义如下:struct msgbuf{long mtype;char mbuf[];};这是一个模板的消息结构,其中成员mbuf是一个字符数组,长度是根据具体的消息来决定的,切忌消息不能以NULL结尾。
成员mtype是消息的类型字段。
函数参数nbytes指定了消息的长度,参数flags指明函数的行为。
函数成功返回0,失败返回–1并设置错误变量errno。
当函数成功返回后会更新相应队列的msqid_ds结构。
使用函数msgrcv可以从队列中读取消息,函数原型如下:#include <sys/msg.h>ssize_t msgrcv ( int msqid, void *ptr, size_t nbytes, long type , int flag);函数中参数msqid为指定要读的队列,参数ptr为要接收数据的缓冲区,nbytes为要接收数据的长度,当队列中满足条件的消息长度大于nbytes的值时,则会参照行为参数flag的值决定如何操作:当flag中设置了MSG_NOERROR位时,则将消息截短到nbytes指定的长度后返回。
如没有MSG_NOERROR位,则函数出错返回,并设置错误变量errno。
设置type 参数指定msgrcv函数所要读取的消息,3.2.2.2. msgsnd函数和msgrcv函数举例下面实例演示了消息队列在进程间的通信。
程序中创建了一个消息的模板结构体,并对声明变量做初始化。
使用msgget函数创建了一个消息队列,使用msgsnd 函数向该队列中发送了一条消息,然后使用函数msgrcv从指定消息队列中读取队列中的一条消息,并将该消息输出到标准输出。
1 )在vi 编辑器中编辑该程序如下:#include <string.h>#include <sys/msg.h>#include <sys/types.h>#include <sys/ipc.h>#include <stdio.h>#include <stdlib.h>#define BUFSZ 4096struct msg{ /* 声明消息结构体*/long msg_types; /* 消息类型成员*/char msg_buf[511]; /* 消息*/Wireless System Laboratory(WST),无线系统研究室};int main( void ) {int qid;int pid;int len;struct msg pmsg,pmsg1; /* 一个消息的结构体变量*/pmsg.msg_types = getpid(); /* 消息类型为当前进程的ID*/sprintf (pmsg.msg_buf,"hello!this is :%d/n/0", getpid() ); /* 初始化消息*/len = strlen ( pmsg.msg_buf ); /* 取得消息长度*/if ( (qid=msgget(IPC_PRIV A TE, IPC_CREAT | 0666)) < 0 ) { /* 创建一个消息队列*/ perror ( "msgget" );exit (1) ;}if ( (msgsnd(qid, &pmsg, len, 0 )) < 0 ){ /* 向消息队列中发送消息*/perror ( "msgsn" );exit ( 1 );}printf ("successfully send a message to the queue: %d /n", qid);len = msgrcv ( qid, &pmsg1, BUFSZ, 0, 0 );if ( len > 0 ){pmsg1.msg_buf[len] = '\0'; /* 为消息添加结束符*/printf ("reading queue id :%05ld\n", qid ); /* 输出队列ID*//* 该消息类型就是发送消息的进程ID*/printf ("message type : %05ld\n", pmsg1.msg_types );printf ("message length : %d bytes\n", len ); /* 消息长度*/printf ("mesage text: %s\n", pmsg1.msg_buf); /* 消息内容*/}else if ( len == 0 )printf ("have no message from queue %d\n", qid );else {perror ( "msgrcv");exit (1);}system("ipcs -q");exit ( 0 ) ;}(2 )在shell 中编译该程序如下:$gcc snd_msg.c –o snd_msg(3 )在shell 中运行该程序如下:$./ snd_msgsuccessfully send a message to the queue: 262147 /nreading queue id :262147Wireless System Laboratory(WST),无线系统研究室message type : 21160message length : 24 bytesmesage text: hello!this is :21160/n/0------ Message Queues --------key msqid owner perms used-bytes messages0x00000071 163840 sun 666 0 00x00000000 196609 sun 666 24 10x00000000 229378 sun 666 24 10x00000000 262147 sun 666 0 03.3. 消息队列应用实例消息队列应用相对较简单,下面实例基本上覆盖了对消息队列的所有操作,同时,程序输出结果有助于加深对前面所讲的某些规则的理解。