百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

Linux中的消息队列、共享内存,你确定都掌握了吗?

liebian365 2024-11-03 15:46 8 浏览 0 评论

消息队列(message queue)

消息队列是消息的链表,存放在内存中,由内核维护

消息队列的特点
1、消息队列中的消息是有类型的。
2、消息队列中的消息是有格式的。
3、消息队列可以实现消息的随机查询。消息不一定要以先进先出的次序读取,编程时可以按消息的类型读取。
4、消息队列允许一个或多个进程向它写入或者读取消息。
5、与无名管道、命名管道一样,从消息队列中读出消息,消息队列中对应的数据都会被删除。
6、每个消息队列都有消息队列标识符,消息队列的标识符在整个系统中是唯一的。
7、只有内核重启或人工删除消息队列时,该消息队列才会被删除。若不人工删除消息队列,消息队列会一直存在于系统中。
8、*消息队列可以独立于进程存在,可以无阻塞收发,可以选择性的接收消息
》 在ubuntu 12.04中消息队列限制值如下:

  • 每个消息内容最多为8K字节
  • 每个消息队列容量最多为16K字节
  • 系统中消息队列个数最多为1609个
  • 系统中消息个数最多为16384个

System V提供的IPC通信机制需要一个key值,通过key值就可在系统内获得一个唯一的消息队列标识符。
key值可以是人为指定的,也可以通过ftok函数获得。

#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
功能:
	获得项目相关的唯一的IPC键值。
参数:
	pathname:路径名
	proj_id:项目ID,非0整数(只有低8位有效)
返回值:
	成功返回key值
	失败返回 -1

创建消息队列:

#include <sys/msg.h>
int msgget(key_t key, int msgflg);
功能:
创建一个新的或打开一个已经存在的消息队列。不同的进程调用此函数,
只要用相同的key值就能得到同一个消息队列的标识符。
参数:
key:IPC键值。
msgflg:标识函数的行为及消息队列的权限。
返回值:
成功:消息队列的标识符,失败:返回-1。

》msgflg的取值:
IPC_CREAT:创建消息队列。
IPC_EXCL:检测消息队列是否存在。
位或权限位:消息队列位或权限位后可以设置消息队列的访问权限,
格式和open函数的mode_t一样,但可执行权限未使用。

使用shell命令操作消息队列:
查看消息队列
ipcs -q
删除消息队列
ipcrm -q msqid

消息队列的消息的格式:

typedef struct _msg
{
	long mtype; /*消息类型*/
	char mtext[100]; /*消息正文*/
	... /*消息的正文可以有多个成员*/
}MSG;
消息类型必须是长整型的,而且必须是结构体类型的第一个成员,
类型下面是消息正文,正文可以有多个成员(正文成员可以是任意数据类型的)。

发送消息:

#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp,size_t msgsz, int msgflg);
功能:
	将新消息添加到消息队列。
参数:
	msqid:消息队列的标识符。
	msgp:待发送消息结构体的地址。
	msgsz:消息正文的字节数。
	msgflg:函数的控制属性
		0:msgsnd调用阻塞直到条件满足为止。
		IPC_NOWAIT: 若消息没有立即发送则调用该函数的进程会立即返回。
返回值:
	成功:0
	失败:返回-1

接收消息:

#include <sys/msg.h>
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz,
long msgtyp, int msgflg);
功能:
从标识符为msqid的消息队列中接收一个消息。一旦接收消息成功,
则消息在消息队列中被删除。
参数:
msqid:消息队列的标识符,代表要从哪个消息列中获取消息。
msgp: 存放消息结构体的地址。
msgsz:消息正文的字节数。
msgtyp:消息的类型、可以有以下几种类型
	msgtyp = 0:返回队列中的第一个消息
	msgtyp > 0:返回队列中消息类型为msgtyp的消息
	msgtyp < 0:返回队列中消息类型值小于或等于
	msgtyp绝对值的消息,如果这种消息有若干个,则取类型值最小的消息。
	注意:
	若消息队列中有多种类型的消息,msgrcv获取消息的时候按消息类型获取,
	不是先进先出的。在获取某类型消息的时候,若队列中有多条此类型的消息,
	则获取最先添加的消息,即先进先出原则。
msgflg:函数的控制属性
	0:msgrcv调用阻塞直到接收消息成功为止。
	MSG_NOERROR:若返回的消息字节数比nbytes字节数多,则消息就会截短到nbytes字节,且不通知消息发送进程。
	IPC_NOWAIT:调用进程会立即返回。若没有收到消息则立即返回-1。
返回值:
	成功返回读取消息的长度
	失败返回-1。

消息队列的控制:

#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:
	对消息队列进行各种控制,如修改消息队列的属性,或删除消息消息队列。
参数:
	msqid:消息队列的标识符。
	cmd:函数功能的控制。
	buf:msqid_ds数据类型的地址,用来存放或更改消息队列的属性。
返回值:
	成功:返回 0
	失败:返回 -1

》cmd:函数功能的控制
	IPC_RMID:删除由msqid指示的消息队列,将它从系统中删除并破坏相关数据结构。
	IPC_STAT:将msqid相关的数据结构中各个元素的当前值存入到由buf指向的结构中。
	IPC_SET:将msqid相关的数据结构中的元素设置为由buf指向的结构中的对应值。

文章福利:现在C++程序员面临的竞争压力越来越大。那么,作为一名C++程序员,怎样努力才能快速成长为一名高级的程序员或者架构师,或者说一名优秀的高级工程师或架构师应该有怎样的技术知识体系,这不仅是一个刚刚踏入职场的初级程序员,也是工作三五年之后开始迷茫的老程序员,都必须要面对和想明白的问题。为了帮助大家少走弯路,技术要做到知其然还要知其所以然。以下视频获取点击:正在跳转

如果想学习C++工程化、高性能及分布式、深入浅出。性能调优、TCP,协程,Nginx源码分析Nginx,ZeroMQ,MySQL,Redis,MongoDB,ZK,Linux内核,P2P,K8S,Docker,TCP/IP,协程,DPDK的朋友可以看一下这个学习地址C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂

例:01_message_queue_write.c 01_message_queue_read.c

总结:

》每个程序都有两个任务,一个任务是负责接收消息,一个任务是负责发送消息,
通过fork创建-子进程实现多任务。
》一个进程负责接收信息,它只接收某种类型的消息,只要别的进程发送此类型的消息,
此进程-就能收到。收到后通过消息的name成员就可知道是谁发送的消息。
》另一个进程负责发信息,可以通过输入来决定发送消息的类型。
》设计程序的时候,接收消息的进程接收消息的类型不一样,这样就实现了发送的消息
只被接收-此类型消息的人收到,其它人收不到。这样就是实现了给特定的人发送消息。

共享内存(shared memory)

共享内存允许两个或者多个进程共享给定的存储区域。

共享内存的特点
1、共享内存是进程间共享数据的一种最快的方法。一个进程向共享的内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容。
2、使用共享内存要注意的是多个进程之间对一个给定存储区访问的互斥。若一个进程正在向共享内存区写数据,则在它做完这一步操作前,别的进程不应当去读、写这些数据。


在ubuntu 12.04中共享内存限制值如下:
-共享存储区的最小字节数:1
-共享存储区的最大字节数:32M
-共享存储区的最大个数:4096
-每个进程最多能映射的共享存储区的个数:4096

获得一个共享存储标识符

#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size,int shmflg);
功能:创建或打开一块共享内存区
参数:
key:IPC键值
size:该共享存储段的长度(字节)
shmflg:标识函数的行为及共享内存的权限。
返回值:
成功:返回共享内存标识符。
失败:返回-1。

》参数属性shmflg:
IPC_CREAT:如果不存在就创建
IPC_EXCL:如果已经存在则返回失败
位或权限位:共享内存位或权限位后可以设置共享内存的访问权限,格式和open函数的mode_t一样,但可执行权限未使用。

使用shell命令操作共享内存:
查看共享内存
ipcs -m
删除共享内存
ipcrm -m shmid

共享内存映射(attach)

#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr,int shmflg);
功能:
将一个共享内存段映射到调用进程的数据段中。
参数:
shmid:共享内存标识符。
shmaddr:共享内存映射地址(若为NULL则由系统自动指定),推荐使用NULL。
shmflg:共享内存段的访问权限和映射条件。
返回值:
成功:返回共享内存段映射地址
失败:返回 -1

》shmflg:共享内存段的访问权限和映射条件
	0:共享内存具有可读可写权限。
	SHM_RDONLY:只读。
	SHM_RND:(shmaddr非空时才有效)
	没有指定SHM_RND则此段连接到shmaddr所指定的地址上(shmaddr必需页对齐)。
	指定了SHM_RND则此段连接到shmaddr-shmaddr%SHMLBA 所表示的地址上。
》注:
shmat函数使用的时候第二个和第三个参数一般设为NULL和0,
即系统自动指定共享内存地址,并且共享内存可读可写。

解除共享内存映射(detach)

#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
功能:
将共享内存和当前进程分离(仅仅是断开联系并不删除共享内存)。
参数:
shmaddr:共享内存映射地址。
返回值:
成功返回 0,
失败返回 -1。

共享内存控制

#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd,struct shmid_ds *buf);
功能:共享内存空间的控制。
参数:
shmid:共享内存标识符。
cmd:函数功能的控制。
buf:shmid_ds数据类型的地址,用来存放或修改共享内存的属性。
返回值:
成功返回 0,
失败返回 -1。

》cmd:函数功能的控制
	IPC_RMID:删除。
	IPC_SET:设置shmid_ds参数。
	IPC_STAT:保存shmid_ds参数。
	SHM_LOCK:锁定共享内存段(超级用户)。
	SHM_UNLOCK:解锁共享内存段。

例:02_shared_memory_write.c 02_shared_memory_read.c

注意:
SHM_LOCK用于锁定内存,禁止内存交换。并不代表共享内存被锁定后禁止其它进程访问。其真正的意义是:被锁定的内存不允许被交换到虚拟内存中。这样做的优势在于让共享内存一直处于内存中,从而提高程序性能。

相关推荐

快递查询教程,批量查询物流,一键管理快递

作为商家,每天需要查询许许多多的快递单号,面对不同的快递公司,有没有简单一点的物流查询方法呢?小编的回答当然是有的,下面随小编一起来试试这个新技巧。需要哪些工具?安装一个快递批量查询高手快递单号怎么快...

一键自动查询所有快递的物流信息 支持圆通、韵达等多家快递

对于各位商家来说拥有一个好的快递软件,能够有效的提高自己的工作效率,在管理快递单号的时候都需要对单号进行表格整理,那怎么样能够快速的查询所有单号信息,并自动生成表格呢?1、其实方法很简单,我们不需要一...

快递查询单号查询,怎么查物流到哪了

输入单号怎么查快递到哪里去了呢?今天小编给大家分享一个新的技巧,它支持多家快递,一次能查询多个单号物流,还可对查询到的物流进行分析、筛选以及导出,下面一起来试试。需要哪些工具?安装一个快递批量查询高手...

3分钟查询物流,教你一键批量查询全部物流信息

很多朋友在问,如何在短时间内把单号的物流信息查询出来,查询完成后筛选已签收件、筛选未签收件,今天小编就分享一款物流查询神器,感兴趣的朋友接着往下看。第一步,运行【快递批量查询高手】在主界面中点击【添...

快递单号查询,一次性查询全部物流信息

现在各种快递的查询方式,各有各的好,各有各的劣,总的来说,还是有比较方便的。今天小编就给大家分享一个新的技巧,支持多家快递,一次能查询多个单号的物流,还能对查询到的物流进行分析、筛选以及导出,下面一起...

快递查询工具,批量查询多个快递快递单号的物流状态、签收时间

最近有朋友在问,怎么快速查询单号的物流信息呢?除了官网,还有没有更简单的方法呢?小编的回答当然是有的,下面一起来看看。需要哪些工具?安装一个快递批量查询高手多个京东的快递单号怎么快速查询?进入快递批量...

快递查询软件,自动识别查询快递单号查询方法

当你拥有多个快递单号的时候,该如何快速查询物流信息?比如单号没有快递公司时,又该如何自动识别再去查询呢?不知道如何操作的宝贝们,下面随小编一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号若干...

教你怎样查询快递查询单号并保存物流信息

商家发货,快递揽收后,一般会直接手动复制到官网上一个个查询物流,那么久而久之,就会觉得查询变得特别繁琐,今天小编给大家分享一个新的技巧,下面一起来试试。教程之前,我们来预览一下用快递批量查询高手...

简单几步骤查询所有快递物流信息

在高峰期订单量大的时候,可能需要一双手当十双手去查询快递物流,但是由于逐一去查询,效率极低,追踪困难。那么今天小编给大家分享一个新的技巧,一次能查询多个快递单号的物流,下面一起来学习一下,希望能给大家...

物流单号查询,如何查询快递信息,按最后更新时间搜索需要的单号

最近有很多朋友在问,如何通过快递单号查询物流信息,并按最后更新时间搜索出需要的单号呢?下面随小编一起来试试吧。需要哪些工具?安装一个快递批量查询高手快递单号若干怎么快速查询?运行【快递批量查询高手】...

连续保存新单号功能解析,导入单号查询并自动识别批量查快递信息

快递查询已经成为我们日常生活中不可或缺的一部分。然而,面对海量的快递单号,如何高效、准确地查询每一个快递的物流信息,成为了许多人头疼的问题。幸运的是,随着科技的进步,一款名为“快递批量查询高手”的软件...

快递查询教程,快递单号查询,筛选更新量为1的单号

最近有很多朋友在问,怎么快速查询快递单号的物流,并筛选出更新量为1的单号呢?今天小编给大家分享一个新方法,一起来试试吧。需要哪些工具?安装一个快递批量查询高手多个快递单号怎么快速查询?运行【快递批量查...

掌握批量查询快递动态的技巧,一键查找无信息记录的两种方法解析

在快节奏的商业环境中,高效的物流查询是确保业务顺畅运行的关键。作为快递查询达人,我深知时间的宝贵,因此,今天我将向大家介绍一款强大的工具——快递批量查询高手软件。这款软件能够帮助你批量查询快递动态,一...

从复杂到简单的单号查询,一键清除单号中的符号并批量查快递信息

在繁忙的商务与日常生活中,快递查询已成为不可或缺的一环。然而,面对海量的单号,逐一查询不仅耗时费力,还容易出错。现在,有了快递批量查询高手软件,一切变得简单明了。只需一键,即可搞定单号查询,一键处理单...

物流单号查询,在哪里查询快递

如果在快递单号多的情况,你还在一个个复制粘贴到官网上手动查询,是一件非常麻烦的事情。于是乎今天小编给大家分享一个新的技巧,下面一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号怎么快速查询?...

取消回复欢迎 发表评论: