2026/6/1 7:26:06
网站建设
项目流程
农业网站建设模板下载,如何做资源论坛网站,婚恋网站策划,定制一个网站多少钱文章目录消息队列消息队列VS管道System V 消息队列系统管理命令核心函数创建/获取消息队列发送消息接收消息控制操作消息队列通信POSIX 消息队列特点核心函数创建/打开队列发送消息接收消息关闭与删除文件系统集成查看消息配置异常处理消息队列通信System V vs POSIX 对比消息队…文章目录消息队列消息队列VS管道System V 消息队列系统管理命令核心函数创建/获取消息队列发送消息接收消息控制操作消息队列通信POSIX 消息队列特点核心函数创建/打开队列发送消息接收消息关闭与删除文件系统集成查看消息配置异常处理消息队列通信System V vs POSIX 对比消息队列内核维护的进程间通信IPC机制以消息为单位进行数据交换非字节流支持不同类型消息的分类处理消息队列独立于创建进程存在消息队列VS管道特性管道消息队列数据类型字节流结构化消息通信方式先进先出支持消息类型过滤持久性进程结束即消失显式删除才消失容量固定缓冲区可配置消息数量System V 消息队列系统管理命令# 查看所有IPC对象ipcs# 创建消息队列键值12ipcmk -Q12# 删除消息队列ID为1ipcrm -q1核心函数创建/获取消息队列#includesys/msg.hintmsgget(key_tkey,intmsgflg);key消息队列键值IPC_PRIVATE 或 ftok() 生成可以使用ftok()函数生成也可以指定为IPC_PRIVATE创建一个新的消息队列msgflg标志位IPC_CREAT | 0666,IPC_CREAT创建消息队列IPC_EXCL与IPC_CREAT一起使用确保创建新的消息队列返回成功返回消息队列标识符 (msqid)失败返回 -1发送消息intmsgsnd(intmsqid,constvoid*msgp,size_tmsgsz,intmsgflg);msqid消息队列IDmsgp消息结构体指针必须包含long mtypemsgsz消息数据长度不含mtypemsgflg标志位0 或 IPC_NOWAIT接收消息ssize_tmsgrcv(intmsqid,void*msgp,size_tmsgsz,longmsgtyp,intmsgflg);msqid: 消息队列标识符msgp: 指向消息结构的指针msgsz: 消息缓冲区的最大长度msgtyp消息类型选择0接收第一个消息0接收指定类型的第一个消息0接收类型≤|msgtyp|的最小类型的消息msgflg: 标志位例如IPC_NOWAIT非阻塞接收返回值: 成功返回接收到的消息数据的长度失败返回 -1控制操作intmsgctl(intmsqid,intcmd,structmsqid_ds*buf);msqid: 消息队列标识符cmdIPC_RMID删除队列IPC_STAT获取状态IPC_SET设置属性buf: 指向msqid_ds结构的指针返回值: 成功返回 0失败返回 -1消息队列通信发送端#includesys/msg.h#includestring.h#includestdio.hstructmsgbuf{longmtype;// 消息类型必须 0charmtext[100];// 消息数据};intmain(){key_tkeyftok(.,a);// 生成键值intmsqidmsgget(key,IPC_CREAT|0666);structmsgbufmsg;msg.mtype1;// 设置消息类型strcpy(msg.mtext,Hello from sender);//msgsnd(msqid, msg, strlen(msg.mtext) 1, 0);if(msgsnd(msqid,msg,sizeof(msg.mtext),0)-1){perror(msgsnd);exit(1);}printf(Message sent: %s\n,msg.mtext);return0;}接收端#includesys/msg.h#includestdio.hstructmsgbuf{longmtype;charmtext[100];};intmain(){key_tkeyftok(.,a);intmsqidmsgget(key,0666);structmsgbufmsg;// msgrcv(msqid, msg, sizeof(msg.mtext), 1, 0);if(msgrcv(msqid,msg,sizeof(msg.mtext),1,0)-1){perror(msgrcv);exit(1);}printf(Received: %s\n,msg.mtext);msgctl(msqid,IPC_RMID,NULL);// 删除消息队列return0;}POSIX 消息队列特点更现代的API设计支持优先级消息与文件系统集成提供更多控制选项核心函数创建/打开队列#includemqueue.h// 仅打开已存在的消息队列mqd_tmq_open(constchar*name,intoflag);// 打开或创建新的消息队列带属性配置mqd_tmq_open(constchar*name,intoflag,mode_tmode,structmq_attr*attr);name队列名称以/开头如/myqueue 且后续不能再包含其他font stylecolor:rgb(31, 35, 41);background-color:rgba(0, 0, 0, 0);//font系统级可见的不同进程通过相同 name 访问同一个消息队列oflagO_CREAT | O_RDONLY | O_WRONLY | O_RDWRmode仅当 oflag 包含 O_CREAT 时有效用于指定新消息队列的访问权限取值与 open() 函数的权限一致例如 0644所有者读写、同组读、其他读最终权限会被进程的 umask 掩码修正实际权限 mode ~umaskattr仅当 oflag 包含 O_CREAT 时有效用于指定新消息队列的属性若为 NULL则使用系统默认属性struct mq_attr 核心成员包括mq_maxmsg队列最大可容纳的消息数量mq_msgsize队列中单个消息的最大字节长度mq_curmsgs队列当前的消息数量仅用于查询创建时设置无效返回值成功返回一个有效的 消息队列描述符mqd_t 类型后续所有消息队列操mq_send/mq_receive 等均依赖该描述符失败返回 (mqd_t)-1同时设置全局变量 errno 指示错误原因例如 EEXISTO_CREAT|O_EXCL 时队列已存在ENOENT队列不存在且未指定 O_CREAT发送消息#includemqueue.hintmq_send(mqd_tmqdes,constchar*msg_ptr,size_tmsg_len,unsignedintmsg_prio);mqdes由 mq_open() 成功返回的消息队列描述符标识要操作的目标消息队列msg_ptr指向要发送的消息数据缓冲区的指针消息数据可以是任意二进制数据无格式要求msg_len 指定msg_ptr指向的消息的长度此长度必须小于或等于队列的mq_msgsize属性允许使用零长度的消息即0 msg_len ≤ 消息队列的 mq_msgsize 属性msg_prio优先级0最低数值越大优先级越高越先被接收若无需优先级可设为 0默认优先级返回值成功返回 0表示消息已成功写入消息队列失败返回 -1同时设置 errno 指示错误原因例如 EAGAIN非阻塞模式下队列已满EBADF无效的消息队列描述符或无写权限接收消息mq_receive()从消息队列描述符 mqdes 引用的消息队列中删除优先级最高的最早消息并将其放置在msg_ptr指向的缓冲区中如果队列为空则默认情况下mq_receive()会阻塞直到消息可用或者调用被信号处理程序中断接收最高优先级的最早消息ssize_tmq_receive(mqd_tmqdes,char*msg_ptr,size_tmsg_len,unsignedint*msg_prio);mqdes由 mq_open() 成功返回的消息队列描述符标识要操作的目标消息队列msg_ptr指向用于接收消息数据的缓冲区的指针需提前分配足够大小的内存空间msg_len 指定 msg_ptr 指向的缓冲区的大小必须大于或等于消息队列的 mq_msgsize 属性msg_prio指向用于存储接收消息优先级的变量指针接收成功后消息的优先级会被写入该变量若不关心消息优先级可传入 NULL返回值成功返回实际接收到的消息数据的字节长度ssize_t 类型非负整数失败返回 -1同时设置 errno 指示错误原因例如 EAGAIN非阻塞模式下队列为空EMSGSIZE接收缓冲区大小 msg_len mq_msgsize关闭与删除intmq_close(mqd_tmqdes);// 关闭队列描述符intmq_unlink(constchar*name);// 删除队列文件mqdes 由 mq_open() 成功返回的消息队列描述符标识要关闭的消息队列name与 mq_open() 中一致的消息队列唯一标识名必须以 / 开头格式合法标识要删除的目标消息队列返回值成功返回 0表示消息队列描述符已成功关闭/消息队列的链接已被移除失败返回 -1同时设置 errno 指示错误原因文件系统集成在 Linux 上消息队列是在虚拟文件系统中创建的挂载文件系统后可以使用通常用于文件的命令例如ls 和 rm 来查看和作系统上的消息队列# 挂载消息队列文件系统mkdir/dev/mqueuemount-t mqueue none /dev/mqueue# 查看队列信息ls/dev/mqueue/cat/dev/mqueue/myqueue# 目录中每个文件的内容都由一行组成其中包含有关队列的信息# 输出QSIZE:129 NOTIFY:2 SIGNO:0 NOTIFY_PID:8260QSIZE: 队列中所有消息的数据字节数NOTIFY_PID: 如果该值为非零则具有此 PID 的进程已使用**mq_notify()**来注册异步消息通知其余字段描述通知的发生方式NOTIFY: 通知方式0为SIGEV_SIGNAL1表示SIGEV_NONE2为SIGEV_THREADSIGNO: 用于SIGEV_SIGNAL的SIGNO信号查看消息配置# 默认消息大小 cat/proc/sys/fs/mqueue/msgsize_default # 默认8192字节 # 最大消息大小 cat/proc/sys/fs/mqueue/msgsize_max # 限制值异常处理// 检查消息队列是否已满if(msgsnd(msqid,msg,size,IPC_NOWAIT)-1){if(errnoEAGAIN){// 队列已满处理逻辑}}// POSIX 非阻塞接收if(mq_receive(mqdes,buf,size,prio)-1){if(errnoEAGAIN){// 队列为空}}消息队列通信发送端#includemqueue.h#includestring.h#includefcntl.h#defineQUEUE_NAME/my_queue#defineMSG_PRIORITY1intmain(){mqd_tmqdesmq_open(QUEUE_NAME,O_WRONLY|O_CREAT,0666,NULL);charmessage[]Hello, POSIX!;mq_send(mqdes,message,strlen(message),MSG_PRIORITY);mq_close(mqdes);return0;}接收端#includemqueue.h#includestdio.h#defineQUEUE_NAME/my_queue#defineMAX_MSG_SIZE8192intmain(){mqd_tmqdesmq_open(QUEUE_NAME,O_RDONLY);charbuffer[MAX_MSG_SIZE];unsignedintpriority;ssize_tlenmq_receive(mqdes,buffer,MAX_MSG_SIZE,priority);buffer[len]\0;printf([优先级:%u] %s\n,priority,buffer);mq_close(mqdes);// mq_unlink(QUEUE_NAME); // 删除队列return0;}System V vs POSIX 对比特性System VPOSIXAPI风格较旧较新类似文件操作命名方式数字键值路径名消息优先级无有阻塞控制有限更灵活文件系统集成无有/dev/mqueue可移植性广泛较新系统默认限制系统配置可调节