QNX operating system information transfer-message transfer information transfer between qnx tasks

Reprinted: https://blog.csdn.net/xjhhjx/article/details/77139457

1. Overview of
QNX messages QNX messages can be divided into synchronous messages and asynchronous messages. Asynchronous (pulse) messages mainly reflect a notification mechanism. Synchronous messages mainly refer to the process of mutual cooperation between the two parties in the message delivery process.
2. Several basic concepts of QNX message delivery
1. Channel and link
Message delivery is based on the model of server and client. QNX6 abstracts the concept of "Channel". A channel is the entrance to a service; as to how many threads the channel has to serve for it, it is the server's own business. If a server has multiple services, it can also open multiple channels. The client needs to establish a connection (Connection) before sending a message to the "channel", and then send the message on the connection. In this way, the same client can establish multiple connections with the same channel if necessary.
2. Name space (name_space)
In the communication between the client and the server, in order for the client to easily know the nd/pid/chid of the server, the server process can register a path name and associate it with the nd, pid, and chid of the service channel. The client only needs to request the path name of the connection server.

3. Client server communication under QNX synchronization signal

1. Client model
1) Call name_open(PATH) to connect to the server channel to obtain a connection ID
3) Call API to send a message and wait for the server to respond
4) When the response is received, call name_close() to close Connection

2. Server model
1) Call name_attach to register a namespace and create a channel
2) Receive and process messages
3) Reply to the message processing result
4) name_detach deletes the name from the namespace

3. The client-server message transfer process
1) The server registers a namespace and waits for the client to connect
2) The client connects to the namespace
3) The client calls the MsgSend interface to send messages to the server, and the client is blocked
4) The server calls the MsgReceive interface Receiving data, the client is in response blocking
5) The server processes the message and calls the MsgReply function to send the response message.
6) The client returns from the MsgSend function to unblock.

4. Use multi-channel message transfer to improve efficiency.
Use iov_t to "collect" data. In other words, several pieces of data can be transferred at a time. Header and databuf are two non-adjacent pieces of memory, but they are continuous when passed to the ReceiveBuffer on the server side.
SETIOV(&iov[0], &header, sizeof(header));
SETIOV(&iov[1], databuf, datalen);
MsgSendvs(ConnectionId, iov, 2, Replybf, ReplyLen);

5. The direction of message delivery and MsgDeliverEvent()
The client sends a message to the server, the server cannot reply immediately and the client does not want to wait. In this situation, the correct approach is to tell the client that the request will be processed after a period of time and the client can continue to run. Once the server completes the task, the server needs some way to tell the client that the request is complete.

Client: Prepare a "Notification Event" and send this event to the server with MsgSend(), which means: "If xxx happens, please use this event to notify me".
  Server: After receiving this message, record the rcvid at that time and the incidents passed by, and then reply "Okay, got it". 
  Client: Because of the response from the server, the client is no longer blocked and can do other things 
  ... 
  Server: At a certain moment, the "xxx situation" requested by the client is met, and the server calls MsgDeliverEvent (rcvid, event); To notify the client client 
  : After receiving the notification, use MsgSend() to send off "Where is the data for the xxx situation?" 
  Server: Use MsgReply() to return the data to the client

  int MsgDeliverEvent (int rcvid ,const struct sigevent *event); The
event server does not need to be modified. rcvid is received by the server from the client. When the server responds to the client, this id will be meaningless. In addition, MsgDeliverEvent is a non-blocking function.

6. Common API
ChannelCreate(), ChannelDestroy()
    ConnectAttach(), ConnectDetach()
    MsgDeliverEvent()
    MsgError()
    MsgRead(), MsgReadv()
    MsgReceive(), MsgReceivePulse(), MsgReceivev()
    MsgReply(v), MsgReply()
    MsgSend(), MsgSendnc(), MsgSendsv(), MsgSendsvnc(), MsgSendv(), 
MsgSendvnc(), MsgSendvs(), MsgSendvsnc()
  MsgWrite(), MsgWritev()

name_close), name_close)() and name_open()


7. Summary
1) The client specifies the server response buffer when sending a message to the service.
2) The server passes the parameter as the MsgSend return value when the client responds to the message (MsgReply).
3) The server can do it in MsgReceive. Passing parameters is used to obtain some information about the message sent by the
client 4) When the client opens the service name space, the system will send an _IO_CONNECT message to the server
5) When the client disconnects or closes the name space, the server will receive it _PULSE_CODE_DISCONNECT pulse
6) client view unblock REPLY BLOCK from the time server will receive _PULSE_CODE_UNBLOCK pulse
time 7) to create a namespace is automatically set up _NTO_CHF_DISCONNECT_NTO_CHF_COID_DISCONNECT, _NTO_CHF_UNBLOCK standard, so the server can receive the corresponding system pulse



IV notification signal -Pulse
1, basic concepts
The pulse is actually more like a short message, which is also sent on the "connection". The biggest feature of pulse is that it is asynchronous. The sender does not need to wait for the receiver to respond, and can continue to execute directly. However, this asynchrony also limits the pulse. The amount of data that pulses can carry is limited. There is only an 8-bit "code" field to distinguish between different pulses, and a 32-bit "value" field to carry data. The main purpose of the pulse is to carry out "Notification" (Notification). Not only the user program, the kernel also generates and sends a special "system pulse" to the user program to notify the occurrence of a special situation.

2. When receiving pulses,
know that there will be no other messages on the channel. If there are only pulses, you can use MsgReceivePulse() to receive only pulses; if the channel can receive both messages and pulses, use MsgReceive() directly, just make sure The receive buffer (ReveiveBuf) can hold at least one pulse (sizeof struct _pulse). If the rcvid returned by MsgReceive() is 0, it means that a pulse has been received, otherwise, a message has been received.

3. Pulse signal characteristics
1) Effectively transmit 40-bit data (8-bit pulse code, 32-bit data)
2) Non-blocking for the sender
3) Can be received like other messages
4) Pulse will be queued, as long as the receiver It is not blocking waiting for the pulse.
5) If there is no pulse, the receiver will block and wait for the pulse.

4. Related data structure and API
struct _pulse {       uint16_t type;       uint16_t subtype;       int8_t code;       uint8_t zero [3];




      union sigval value;
      int32_t scoid;
  };
value is a union
      union sigval {       int sival_int;       void *sival_ptr;      };  int MsgReceivePulse (int chid,         void *         rmsg, int rbytes,         struct _msg_info *info); V. Asynchronous message 1 , Asynchronous signal commonly used API asyncmsg_channel_create() asyncmsg_channel_destroy() asyncmsg_connect_attach() asyncmsg_connect_detach() asyncmsg_flush() asyncmsg_put(), asyncmsg_get() asyncmsg_free() async flagmsg_malloc() 2, int async_channels unsigned flag , int async flag


























mode_t mode,
size_t buffer_size,
unsigned max_num_buffer,
const struct sigevent *ev,
int (*recvbuf_callback) (
size_t bufsize,
unsigned num_bufs,
void *bufs[],
int flags,
void *handle ),
void *recvbuf_callback_handle

: description channel ); Attribute, the default setting is _NTO_CHF_ASYNC. If _NTO_CHF_ASYNC_NONBLOCK is set, 
then the program will not block if no message arrives when calling asyncmsg_get().

Mode: Set the channel attribute

Buff_size: Set the size of the buffer for storing messages

Max_num_buffer: Set the maximum number of buffers for storing messages

Ev: NULL or a pointer to the sigevent structure, used to specify an event, when a message can be received When this event automatically sends

Recvbuf_callback: NULL or a function pointer, it is used to allocate space to store the received message when it is NULL. Use Malloc

recvbuf_callback_handle: passed to the Recvbuf_callback function.

Note:
When Recvbuf_callback is not NULL:
A callback function is triggered every time asyncmsg_get() is called (flags is set to ASYNCMSG_RECVBUF_ALLOC, bufs points to the message...) when it wants to receive other messages, it returns 1 and returns 0 to stop.
When calling asyncmsg_channel_destroy(), the callback function is triggered multiple times to release space, and the flags are set to ASYNCMSG_RECVBUF_FREE.


int asyncmsg_channel_destroy( int chid );

chid: Channel ID
description:
When Recvbuf_callback is not NULL, each call will trigger the release of space, and the default call is free.

Return value:
success: EOK
failure: -1 ->errno

int asyncmsg_connect_attach (
uint32_t nd,
pid_t pid,
int chid,
unsigned index,
unsigned flags, 
const struct _asyncmsg_connection_attr * attr);

parameter description:
Nd/pid/chid: which computer /Process ID/Channel ID

index: The lowest acceptable connection ID (starting value)

Flags:
_NTO_COF_NOSHARE: The application uses its own BUFFER, otherwise it uses asyncmsg_malloc(), and the fill data is sent when asyncmsg_put() is called.

_NTO_COF_NONBLOCK: No need to block waiting, when the sending header is busy
Attr:
Specify connection attributes
Return value:
Success: Connection ID
failed: -1

int asyncmsg_connect_detach( int coid );


Parameters:
coid: Connection ID
Remarks:
Disconnect from the specified connection, All messages on the sending side are discarded. If all messages before this have been sent, the asyncmsg_flush() interface should be called before this.

Return value:
Success: EOK
failure: -1

int asyncmsg_flush( int coid,
int mode );

Parameter description:
Coid: Connection ID

Mode:
0, if you don’t want this function to block, set ASYNCMSG_FLUSH_NONBLOCK 

Return value:
Success: EOK
failure: -1

int asyncmsg_connect_attr (
int coid,
struct _asyncmsg_connection_attr *old_attr, 
const struct _asyncmsg_connection_attr *new_attr);

parameter description:
coid: connection ID
Old_attr: current attribute
new_attr: new attribute

Return value:
success: EOK
failure: -1


int asyncmsg_put( int coid,
const void *buff,
size_t size, 
unsigned handle) ,
int (*call_back) (
int err,
void* buf,
unsigned handle ));

int asyncmsg_putv( int coid,
const iov_t* iov,
int parts, 
unsigned handle,
int (*call_back) (
int err,
void* buf,
unsigned handle ));
Parameter description:
Coid: Connection ID
Buff: Message buffer
Size: Message size
Iov: Array storing IOV messages
Parts: IOV array size
Handle: User-defined data is passed to the callback function, used to distinguish the package type
call_back: NULL or a function pointer, it is called after the message is delivered, if it is NULL,
_asyncmsg_connection_attr is passed to asyncmsg_connect_attach and called.


struct _asyncmsg_get_header *asyncmsg_get( int chid );

Parameter description:
Chid: Channel ID
description: The function receives up to 5 asynchronous messages. In order to receive more messages, this interface should be called cyclically. Knowing that NULL is returned and errno is EAGAIN means Reading is complete.

Return type:
struct _asyncmsg_get_header { struct _msg_info info; int err; iov_t *iov; int parts; struct _asyncmsg_get_header *next; unsigned reserve[2]; }; Description: Info: asynchronous signal information structure err: error status Ivo: pointing to the message body Parts: ivo array size Next: point to the next information structure Return value: success: information linked list failure: NULL




















void asyncmsg_free( void *buf);

Parameter description:
buf: pointer to release memory
Description:
 asyncmsg_get() call causes memory to be released


void *asyncmsg_malloc( size_t size );

Description: The
function allocates space for sending messages.

Guess you like

Origin blog.csdn.net/modi000/article/details/113877196