- 专栏内容:linux下并发编程
- 个人主页:我的主页
- 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.
目录
前言
概述
原理
消息队列的大小
查看资源
接口
代码演示
结尾
前言
本专栏主要分享linux下并发编程相关知识,包括多进程,多线程,进程/线程间通信,并发同步控制,以及高并发下性能提升,请大家多多留言。
概述
进程间传递数据,在本专栏已经分享过共享内存,匿名/命名管道,文件映射等,今天给大家再分享一种可以通过消息包方式传递,类似于socket的方式,使用更加便捷。
原理
Linux 消息队列是一种进程间通信的机制,通过消息队列,不同进程可以彼此传递消息,实现进程间的数据共享。Linux 消息队列是一个存放消息的链表,每个消息都有一个消息类型和一个消息长度,发送方通过消息类型将消息发送到相应的消息队列中,接收方则通过消息类型从消息队列中读取相应的消息。消息队列的实现是通过内核提供的系统调用来完成的。
消息队列的大小
/proc/sys/kernel/msgmni | 消息队列消息数量 MSGMNI | Linux 3.19以后默认值为32000,以前为可用内存 |
/proc/sys/kernel/msgmnb | 消息队列最大字节数 MSGMNB | 默认为16384 |
/proc/sys/kernel/msgmax | 每个消息的最大字节数 MSGMAX | 默认为8192 |
/proc/sys/kernel/msg_next_id | 为下一个分配的IPC对象指定所需的ID | 没有分配时为-1 |
查看资源
因为是内核资源,可以通过ipcs命令来查看已分配的消息队列,也可以查看资源限制。
[senllang@localhost msgqueue]$ ipcs -l
------ Messages Limits --------
max queues system wide = 32000
max size of message (bytes) = 8192
default max size of queue (bytes) = 16384
还有 ipcs -q查看已经有的消息队列
接口
Linux 消息队列是进程间通信中的一种方式,其中发送和接收消息的进程可以独立于消息的数据格式。在 Linux 中,消息队列由消息队列标识符、消息队列权限和消息队列中的消息组成。可以使用 msgctl()、msgget()、msgsnd() 和 msgrcv() 等函数来进行操作。其中,msgctl() 可以用于操作消息队列的权限和属性,msgget() 用于创建和访问消息队列,msgsnd() 用于将消息发送到指定消息队列,msgrcv() 则用于从消息队列中接收消息。
消息队列涉及的头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
/* 获取一个System V 消息队列id */
int msgget(key_t key, int msgflg);
参数取值:
Key, 可以是ftok获取的,也可以是IPC_PRIVATE
msgflag, 可以取值IPC_CREAT,IPC_EXCL,还可以叠加权限进行,权限的取值与open的参数mode取值一样,只是没有可执行权限。默认指定IPC_CREAT时,没有key关联的消息队列时,就会创建,当指定IPC_EXCL时,如果不存在就会返回错误EEXIST。
/* 发送消息 */
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
/*接收消息 */
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);
调用中的flag取值 :
IPC_NOWAIT, 没有消息时立即返回;此时errno为ENOMSG。
MSG_EXCEPT,获取不是msgtyp的消息,如果队头不符合就会返回。
MSG_NOERROR,当消息超过msgsz时,会自动截断而不会报错。
/* 用于查看、设置参数,删除内核对象(用法和 shmctl 一样)*/
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
/*消息的格式,自定义消息mtype,必须大于0;后面mtext是消息数据。这里要注意,在发送时,msgsz是不包括mtype的,只是mtext的长度 */
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[1]; /* message data */
};
代码演示
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MAX_TEXT 512
struct msgbuf {
long mtype;
char mtext[MAX_TEXT];
};
int main() {
struct msgbuf buf;
int msqid;
key_t key;
if ((key = ftok(".", 123)) == -1) {
perror("ftok");
exit(1);
}
if ((msqid = msgget(key, 0644 | IPC_CREAT)) == -1) {
perror("msgget");
exit(1);
}
printf("Enter lines of text, ^D to quit:\n");
buf.mtype = 1;
while(fgets(buf.mtext, MAX_TEXT, stdin) != NULL) {
int len = strlen(buf.mtext);
if (buf.mtext[len-1] == '\n') buf.mtext[len-1] = '\0';
if (msgsnd(msqid, &buf, len+1, 0) == -1) // add str end '\0'
perror("msgsnd");
}
if (msgctl(msqid, IPC_RMID, NULL) == -1) {
perror("msgctl");
exit(1);
}
return 0;
}
结尾
作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。另外有什么想要了解的内容,也可以给我发邮件,互相谈讨,定知无不言。
注:未经同意,不得转载!