qnx进程通信

qnx微内核支持三种基本类型的进程间通信:消息、代理和信号。

1 消息

在QNX中的Message-passing通信是主从式,双向通信的,在每一个进程中都有一个线程来负责通信,当为收到回信时,线程会block住,直到收到回复信息。

消息是qnx中进程间通信的基本形式。一个消息是 一个将若干字节数据封装在一起组成的数据包,可以从一个进程同步地传递到另一个进程。

消息通用的C语言函数

    /* 假定进程A通过发送一个请求向进程B发送消息 */
     
    //进程A发送消息
    Send(pid, smsg, rmsg, smsg_len, rmsg_len);
    /*  参数说明
     *  pid   接收进程B的进程标识符
     *  smsg  保存待发送消息的缓冲区
     *  rmsg  保存接收进程B返回的回答消息
     *  smsg_len  待发送消息的长度
     *  rmsg_len  进程A可以接收的回答消息的最大长度
     */
     
    //进程B接收消息
    pid = Rcecive(0, msg, msg_len);
    /*  参数说明
     *  0    表示进程B接收来自任何进程的消息
     *  msg  用于接收消息的缓冲区
     *  msg_len  接收消息缓冲区的最大长度
     *  pid      返回值为发送进程A的pid
     *  如果发送发调用Send()时所指定的smsg_len与接收方调用Recevie()时所指定的msg_len大小不同,
     *  则使用两者中较小的值作为接收缓冲区的最大数据长度。
     */
     
    //进程B向进程A返回的应答消息
    Reply(pid, reply, reply_len);
    /*  参数说明
     *  pid  接收该应答消息的进程A pid
     *  reply      应答消息缓冲区
     *  reply_len  应答消息缓冲区中数据的长度
     *  如果reply_len和rmsg_len不同,则较小者为最终传输的长度。
     */


ChannelCreate()	         Create a channel to receive messages on.
ChannelDestroy()	Destroy a channel.
ConnectAttach()	        Create a connection to send messages on.
ConnectDetach()	        Detach a connection.
name_open()	Open a name to connect to a server
name_close()	Close a server connection that was opened by name_open()
name_attach()	Register a name in the pathname space and create a channel
name_detach()	Remove a name from the namespace and destroy the channel
MsgSend()	Send a message and block until reply.
MsgSendv()	Send a message to a channel
MsgReceive()	Wait for a message.
MsgReceivev()	Wait for a message or pulse on a channel
MsgReceivePulse()	Wait for a tiny, nonblocking message (pulse).
MsgReply()	Reply to a message.
MsgError()	Reply only with an error status. No message bytes are transferred.
MsgRead()	Read additional data from a received message.
MsgReadv()	Read data from a message
MsgWrite()	Write additional data to a reply message.
MsgWritev()	Write a reply message
MsgInfo()	Obtain info on a received message.
MsgSendPulse()	Send a tiny, nonblocking message (pulse).
MsgDeliverEvent()	Deliver an event to a client.
MsgKeyData()	Key a message to allow security checks.

 1)客户端使用MsgSend()给服务器端发送消息。如果服务器线程没有调用MsgReceive,客户端线程状态则为SEND blocked,一旦服务器线程调用了MsgReceive(),客户端线程状态变为REPLY blocked,当服务器线程执行MsgReply()后,客户端线程状态就变成了READY。如果客户端线程调用了MsgSend()之后,服务器线程卡在MsgReceive上,则客户端线程直接跳过SEND blocked,直接变为REPLY blocked。服务器线程失败,退出或者消失之后,客户端线程会变成READY,此时MsgSend()会发出来一个错误值

2)服务器端使用MsgReceive接收来自客户端的消息。

3)服务端使用MsgReply来向客户端发送消息。

2 Channels and connections

在QNX的消息传递是通过Channels和Connections实现的,并不是通过线程间传递,一个server线程要接收消息,必须先生成一个Channels,一个client线程要发送消息,必须要依附于(Attaching) Channel生成一个Connection。一个进程中的多个客户线程可以同时依附于一个服务线程创建的Channel上,这时所有Connection实际上都会映射到同一内核对象。

简单来说服务线程会创建一个channel(频道),而客户线程会依附于这个Channel创建一个Connection,从而来与服务线程进行通信 

QNX-IPC通信_qnx ipc_深海带鲤鱼的博客-CSDN博客

       除了用线性的缓冲区进行消息传递以外,QNX也提供了定义良好的消息类型iov_t来"汇集"数据,以便能扩充或替代系统提供的服务。消息在拷贝的时候,支持分块传输,也就是不要求连续的缓冲区,发送和接收线程可以指定IOV向量表,在这个表中去指定消息在内存中的位置。

MsgSendv,MsgReceivev,MsgReadv等接口

3 Pulses脉冲

脉冲其实更像一个短消息,也是在“连接Connection”上发送的。脉冲最大的特点是它是异步的。发送方不必要等接收方应答,直接可以继续执行。脉冲能携带的数据量有限,只有一个8位的"code"域 (1byte)用来区分不同的脉冲,和一个32位的“value"域 (4字节)来携带数据。脉冲最主要的用途就是用来进行“通知”(Notification)。不仅是用户程序,内核也会生成发送特殊的“系统脉冲”到用户程序,以通知某一特殊情况的发生。

1 MsgSendPulse() 只在一个进程中的通知,用与同一个进程中一个线程要通知另一个线程的情形, 其中 code 8bits; value 32bits

code 通常用于表示“脉冲类型”的有效范围是 _PULSE_CODE_MINAVAIL 到 _PULSE_CODE_MAXAVAIL。

priority 就像发送线程的消息优先级一样,接收线程以该优先级运行

发送顺序基于优先级

要跨进程边界发送脉冲,发送者必须与接收者具有相同的有效用户 ID 或者是 root 用户

2 MsgDeliverEvent() 在跨进程的时候的通知

3 MsgReceivePulse() 用于频道上只有pulse的接收

4 MsgReceive() 用于频道上既接收message又接收pulse

4 Events

QNX Neutrino提供异步事件通知机制,event是一种notification, 可以从thread到thread, 也可以从kernel到thread, 事件源可能有三种:

     调用MsgDeliverEvent()接口发送事件
    中断处理函数
    定时器到期

5 Signals

当一个服务器线程想通知一个客户端线程时,有两种合理的事件选择:Pulse或信号

1)Pulse,需要客户端创建一个channel,并且调用MsgReceive()接收;

2)信号,只需要调用sigwaitinfo(),不需要创建channel;

6 消息队列

QNX Neutrino内核不包含message queues,它的实现在内核之外。
QNX Neutrino提供了两种message queues的实现:

1)mqueue,使用mqueue资源管理的传统实现

2)mq,使用mq服务和非同步消息的替代实现

QNX IPC机制_msgsendpulse_voicialex的博客-CSDN博客

7共享内存

        共享内存提供了最高带宽的IPC机制,一旦创建了共享内存对象,访问对象的进程可以使用指针直接对其进行读写操作。共享内存本身是不同步的,需要结合同步原语一起使用,信号量和互斥锁都适合与共享内存一块使用,信号量一般用于进程之间的同步,而互斥锁通常用于线程之间的同步,通通常来说互斥锁的效率会比信号量要高。

         QNX中消息传递通过拷贝完成,当消息较大时,可以通过共享内存来完成,发送消息时不需要发送整个消息内容,只需将消息保存到共享内存中,并将地址传递过去即可。

8 Pipes and FIFOs

管道是一种非命名IO通道,用于在多个进程之间的通信,一个进程往管道写,其他进程从管道读取。管道一般用于平行的两个进程单向的传递数据,如果要双向通信的话,就应该使用消息传递了。
FIFOs与管道本质是一样的,不同点在于FIFOs会在文件系统中保存为一个永久的命名文件
 

猜你喜欢

转载自blog.csdn.net/wangbuji/article/details/127387983