2026/10/17 2:31:32

QNX IPC消息发送接收sample

QNX IPC消息发送接收sample 关联数据结构struct _msg_info {int nd;int srcnd;pid_t pid; // 发送方进程pidint32_t chid;int32_t scoid;int32_t coid; // client连接idint32_t msglen; // client发送的原始消息总长度int32_t tid; // 发送方线程tidint16_t priority;int16_t flags;int32_t srcmsglen;int32_t dstmsglen;};typedef struct _name_attach {dispatch_t* dpp;int chid;int mntid;int zero[2];} name_attach_t;dispatch_create用于手动创建dispatch_t对象该函数调用内部会创建Channelname_attach, message_attachGNSGNS Global Name ServiceQNX中的DNS服务端用户调用name_attach的时候会发生如下事情1. name_attach函数内部通过ChannelCreate创建一个Channel返回一个chid(channel id)2. chid保存到name_attach返回的name_attach_t结构体中3. GNS内部将name_attach中的name参数和ChannelCreate创建时的pid, node和返回的chid进行绑定: name - (pid, chid, node)4. 如果name_attach的参数中传入的dispatch_t不是空的还需要将chid和dpp(dispatch_t*)绑定用于事件回调客户端用户用户调用的是name_open其传入name_attach中的name参数GNS根据这个name找到绑定的chid然后在name_open内部调用ChannelConnect进行IPC Channel连接手动MsgReceive不使用自定义dispatch_t)// 使用name_attach自动创建dispatch_t并且使用MsgReceive手动收消息// #include sys/neutrino.h#include sys/dispatch.hconst char* localchannel_name calib_server;const char* remotechannel_name calib_client;// 1. 在local channel上创建服务端name_attach_t* attr name_attach(nullptr, localchannel_name, 0); // 第一个参数dispatch_t处传空name_attach内部自动创建dispatch_t对象默认在name_deattach中销毁该对象// 2. 在remote channel上创建客户端int32_t clientid name_open(remotechannel_name, 0);// 3. 向remote发送消息uint8_t send_buf[1024];memset(send_buf, 0, 1024);MsgSend(clientid, send_buf, 1024, nullptr, 0);// 4. 在local channel上接收消息uint8_t recv_buf[1024];struct _msg_info info;memset(recv_buf, 0, 1024);while(true) {uint32_t recv_id MsgReceive(attr-chid, recv_buf, 1024, info); // MsgReceive是阻塞的,收到正确长度的MsgReply(recv_id, EOK, nullptr, 0); // 一定要做MsgReply否则对方的MsgSend会一直阻塞}使用dispatch接收消息// 手动创建dispatch_t并且使用message_attach设定消息处理函数// #include stdio.h#include stdlib.h#include string.h#include sys/dispatch.h#include sys/neutrino.h// 自定义消息ID用户业务消息避开系统保留的 _IO_XXX#define MY_MSG_HELLO 0x1001// 消息结构体typedef struct {int msg_id;char data[64];} my_msg_t;// 回调函数原型dispatch消息handlerint my_msg_handler(message_context_t *ctp, int code, unsigned flags, void *handle);int main(void){dispatch_t *dpp NULL;name_attach_t *attach NULL;message_attach_t *matt NULL;dispatch_context_t *ctp NULL;// 1. 创建dispatch句柄dpp dispatch_create();if (dpp NULL) {perror(dispatch_create failed);return EXIT_FAILURE;}// 2. name_attach 注册服务名绑定到我们自己的dppattach name_attach(dpp, my_vcpu_service, 0);if (attach NULL) {perror(name_attach failed);dispatch_destroy(dpp);return EXIT_FAILURE;}printf(Server attached name, chid%d\n, attach-chid);// 3. message_attach注册【MY_MSG_HELLO】消息对应的回调函数matt message_attach(dpp, NULL, MY_MSG_HELLO, 0, my_msg_handler, NULL);if (matt NULL) {perror(message_attach failed);name_detach(attach, NAME_FLAG_DETACH_SAVEDPP);dispatch_destroy(dpp);return EXIT_FAILURE;}// 主事件循环printf(Server run loop, waiting client message...\n);for (;;){ctp dispatch_block(ctp); // 阻塞等待消息/脉冲底层封装MsgReceiveif (ctp NULL) {perror(dispatch_block);break;}dispatch_handler(ctp); // 根据消息code自动调用 my_msg_handler}// 清理资源message_detach(matt);name_detach(attach, NAME_FLAG_DETACH_SAVEDPP); // 不要销毁dppdispatch_destroy(dpp);return EXIT_SUCCESS;}// 自定义消息回调函数int my_msg_handler(message_context_t *ctp, int code, unsigned flags, void *handle){// ctp 里面包含 rcvid消息缓冲区等信息int rcvid ctp-rcvid;my_msg_t *msg (my_msg_t *)ctp-msg;printf(Received MY_MSG_HELLO from client: %s\n, msg-data);// 构造应答my_msg_t reply;reply.msg_id MY_MSG_HELLO;snprintf(reply.data, sizeof(reply.data), Hello from QNX Server);// MsgReply回复客户端客户端MsgSend才会解除阻塞MsgReply(rcvid, EOK, reply, sizeof(reply));return 0;}客户端发送消息// 客户端发送MY_MSG_HELLO的消息// // 传给 MsgSend 的发送缓冲区起始位置必须是 int 类型 MsgID#include sys/neutrino.h#include sys/dispatch.h#include stdio.h#include string.hint main(void){// 1. 通过服务名打开连接拿到 coidint coid name_open(my_vcpu_service, 0);if (coid -1) {perror(name_open);return -1;}// 2. 构造发送消息my_msg_t send_msg;my_msg_t reply_msg;memset(send_msg, 0, sizeof(send_msg));send_msg.msg_id MY_MSG_HELLO; // ✅ 关键消息码strncpy(send_msg.data, Hello from client, sizeof(send_msg.data)-1);// 3. MsgSend 同步发送IPC消息int ret MsgSend(coid,send_msg, sizeof(send_msg), // 发送缓冲区长度reply_msg, sizeof(reply_msg) // 接收应答缓冲区长度);if (ret -1) {perror(MsgSend);name_close(coid);return -1;}printf(Server reply: %s\n, reply_msg.data);name_close(coid);return 0;}