首页 > 系统相关 >【linux system V 消息队列】

【linux system V 消息队列】

时间:2024-03-15 18:02:02浏览次数:25  
标签:IPC 队列 system int MSG key linux msg

#简介

消息队列就是一些消息的列表,或者说是一些消息组成的队列。消息队列与管道有些类似,消息队列可以认为是管道的改进版。相较于管道的先进先出准则,消息队列在读取时可以按照消息的类型进行读取,这也是消息队列的特点,它可以实现消息随机查询。消息发送时,需要将消息封装,然后添加到队列的末尾即可,而消息接收时则可以根据需求进行选择的读取(读取即将封装的消息从队列中移除)

#函数说明

/*************************************************************
函 数 名  : ftok
功能描述  : 生成IPC KEY
输入参数  : const char *pathname 存在的文件或文件夹
		   int proj_id 项目代号
		   pathname和proj_id对应一个IPC KEY
返 回 值  : key_t -1 失败  其它 IPC KEY(用于msgget(2), semget(2), or shmget(2))
*************************************************************/
key_t ftok(const char *pathname, int proj_id);
/*************************************************************
函 数 名  : msgget
功能描述  : 根据key标识生成消息队列,key可以为ftok得到,也可以自定义整数
输入参数  : key_t key ICP KEY或自定义整数
		   int msgflg
		   IPC_CREAT | 权限 (IPC_CREAT | 0777)
		   IPC_CREAT | IPC_EXCL | 权限 (IPC_EXCL 消息队列已存在返回-1)
返 回 值  : int 消息队列ID -1 失败 并设置错误码
int msgget(key_t key, int msgflg);
*************************************************************/
/*************************************************************
struct msgbuf {
    long mtype;       /消息类型,必须大于0/
    char mtext[1];    /发送的数据,柔性数组,可为数组或结构体/
};
函 数 名  : msgsnd
功能描述  : 发送数据到消息队列
输入参数  : int msqid 消息队列标识
		   const void *msgp 待发送数据
		   size_t msgsz 待发送数据长度,**不包括消息类型**
		   int msgflg 0 阻塞模式 **如果待写入的数据量超过当前所剩大小,则阻塞等待直到可写**
		   IPC_NOWAIT 非阻塞模式 写失败返回失败
返 回 值  : int -1 失败 0 成功
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
*************************************************************/
函 数 名  : msgrcv
功能描述  : 接收消息队列数据
输入参数  : int msqid 消息队列标识
		   void *msgp 接收数据缓存
		   size_t msgsz **接收数据缓存大小(必须大于等于发送的数据,否则会读取失败)**
		   long msgtyp 待接收数据类型
		   int msgflg 0 **阻塞 直到有数据**
		   IPC_NOWAIT 非阻塞模式 读失败返回失败
返 回 值  : int -1 失败 >=0 读取的字节数
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
*************************************************************/
/*************************************************************
struct msqid_ds {
        struct ipc_perm msg_perm;     /* Ownership and permissions */
        time_t          msg_stime;    /* Time of last msgsnd(2) */
        time_t          msg_rtime;    /* Time of last msgrcv(2) */
        time_t          msg_ctime;    /* Time of last change */
        unsigned long   __msg_cbytes; /* Current number of bytes in
                                         queue (nonstandard) */
        msgqnum_t       msg_qnum;     /* Current number of messages
                                         in queue */
        msglen_t        msg_qbytes;   /* Maximum number of bytes
                                         allowed in queue */
        pid_t           msg_lspid;    /* PID of last msgsnd(2) */
        pid_t           msg_lrpid;    /* PID of last msgrcv(2) */
    };
The ipc_perm structure is defined as follows (the highlighted fields are settable using IPC_SET):

    struct ipc_perm {
        key_t          __key;       /* Key supplied to msgget(2) */
        uid_t          uid;         /* Effective UID of owner */
        gid_t          gid;         /* Effective GID of owner */
        uid_t          cuid;        /* Effective UID of creator */
        gid_t          cgid;        /* Effective GID of creator */
        unsigned short mode;        /* Permissions */
        unsigned short __seq;       /* Sequence number */
    };

函 数 名  : msgctl
功能描述  : 消息队列属性操作
输入参数  : int msqid 消息队列标识符
		   int cmd   操作指令
		   struct msqid_ds *buf 属性
返 回 值  : int -1 失败 并设置错误码 0 成功
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
*************************************************************/

cmd 包括:IPC_STAT 查看属性
IPC_SET 设置属性
IPC_RMID 删除消息队列
其中IPC_SET可修改的属性有msg_qbytes(容量)msg_perm.uid, msg_perm.gid, msg_perm.mode 并刷新msg_ctime
消息队列属性查看:
ipcs -q 查看当前消息队列状态
1.msgctl 函数的IPC_STAT选项
2.通过指令查看
cat /proc/sys/kernel/msgmnb 消息队列容量
cat /proc/sys/kernel/msgmni 消息队列的最大数量
cat /proc/sys/kernel/msgmax 单条消息的最大字节数
消息队列属性
#msgctl实例代码

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

//MSG_PATH和MSG_PROJ_ID 共同索引一个消息队列
#define MSG_PATH    "./"  //存在的文件夹或文件
#define MSG_PROJ_ID 520   //项目代号   非0整数
#define MSG_TYPE    520   //消息类型

int main(int argc, char *argv[])
{
    int ret   = -1;
    key_t key;
    int msg_id;
    struct msqid_ds ds_info;

    key = ftok(MSG_PATH, MSG_PROJ_ID);
    if (-1 == key)                              //-1失败   并设置错误码       0成功
    {
        printf("ftok fail errno:%d, %s\n", errno, strerror(errno));
        return -1;
    }
    printf("ftok key:%d\n", key);

    msg_id = msgget(key, IPC_CREAT | 0777);
    if (-1 == key)                              //-1失败   并设置错误码 >0的整数
    {
        printf("msgget fail errno:%d, %s\n", errno, strerror(errno));
        return -1;
    }
    printf("msg_id:%d\n", msg_id);

    //查看消息队列属性
    msgctl(msg_id, IPC_STAT, &ds_info);
    printf("最后一次发送的时间:%ld, 最后一次接收的时间:%ld, 最后一次更新的时间:%ld,当前队列的数据大小:%ld, 当前队列的消息数量:%ld,队列总容量:%ld,最后一次发送的进程id:%d,最后一次接收的进程id:%d\r\n", 
           ds_info.msg_stime, ds_info.msg_rtime, ds_info.msg_ctime,
           ds_info.__msg_cbytes, ds_info.msg_qnum, ds_info.msg_qbytes,
           ds_info.msg_lspid, ds_info.msg_lrpid);
	//删除消息队列
	msgctl(msg_id, IPC_RMID, NULL);
    return 0;
}

发送端实例代码:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

//MSG_PATH和MSG_PROJ_ID 共同索引一个消息队列
#define MSG_PATH    "./"  //存在的文件夹或文件
#define MSG_PROJ_ID 520   //项目代号   非0整数
#define MSG_TYPE    520   //消息类型

#define MSG_ONE_PACKET_LEN 8*1024

typedef struct
{
    char buf[MSG_ONE_PACKET_LEN];
}MsgPrivateData_t;

typedef struct
{
    long mtype;                 //消息类型
    MsgPrivateData_t private;   //自定义数据
}MsgData_t;

int main(int argc, char *argv[])
{
    int ret   = -1;
    key_t key;
    int msg_id;
    MsgData_t data;
    struct msqid_ds info;

    memset(&data, 0, sizeof(data));

    key = ftok(MSG_PATH, MSG_PROJ_ID);
    if (-1 == key)                              //-1失败   并设置错误码       0成功
    {
        printf("ftok fail errno:%d, %s\n", errno, strerror(errno));
        return -1;
    }
    printf("ftok key:%d\n", key);

    data.mtype = MSG_TYPE;
    strncpy(data.private.buf, "msg send", strlen("msg send"));

    msg_id = msgget(key, IPC_CREAT | 0777);
    if (-1 == key)                              //-1失败   并设置错误码 >0的整数
    {
        printf("msgget fail errno:%d, %s\n", errno, strerror(errno));
        return -1;
    }
    printf("msg_id:%d\n", msg_id);

    ret = msgsnd(msg_id, (void *)&data, sizeof(data.private), 0);   //长度为不包含消息类型的自定义数据
    printf("msgsnd ret:%d\n", ret);

    return 0;
}

#接收端实例代码

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>

//MSG_PATH和MSG_PROJ_ID 共同索引一个消息队列
#define MSG_PATH    "./"  //存在的文件夹或文件
#define MSG_PROJ_ID 520   //项目代号   非0整数
#define MSG_TYPE    520   //消息类型

#define MSG_ONE_PACKET_LEN 8*1024

typedef struct
{
    char buf[MSG_ONE_PACKET_LEN];
}MsgPrivateData_t;

typedef struct
{
    long mtype;                 //消息类型
    MsgPrivateData_t private;   //自定义数据
}MsgData_t;

int main(int argc, char *argv[])
{
    int ret   = -1;
    key_t key;
    int msg_id;
    MsgData_t data;
    struct msqid_ds info;

    memset(&data, 0, sizeof(data));

    key = ftok(MSG_PATH, MSG_PROJ_ID);
    if (-1 == key)                              //-1失败   并设置错误码       0成功
    {
        printf("ftok fail errno:%d, %s\n", errno, strerror(errno));
        return -1;
    }
    printf("ftok key:%d\n", key);

    msg_id = msgget(key, IPC_CREAT | 0777);
    if (-1 == key)                              //-1失败   并设置错误码 >0的整数
    {
        printf("msgget fail errno:%d, %s\n", errno, strerror(errno));
        return -1;
    }
    printf("msg_id:%d\n", msg_id);

    while (1)
    {
        printf("before msgrcv data\r\n");
        msgrcv(msg_id, (void *)&data, sizeof(data.private), MSG_TYPE, 0);   //MSG_TYPE 如果为0表示接收最早数据 如果指定消息类型则接收对应类型的最早数据
        printf("msgrcv data type:%ld, buf:%s\r\n", data.mtype, data.private.buf);
    }

    return 0;
}

标签:IPC,队列,system,int,MSG,key,linux,msg
From: https://blog.csdn.net/weixin_43074937/article/details/136701946

相关文章

  • 学会这些指令,轻松上手Linux!
    一、Linux简介Linux是一种开源的类Unix操作系统。它的核心是Linux内核,而用户空间则由GNU项目提供的工具和其他软件组成,因此常常被称为GNU/Linux。Linux操作系统的特点包括稳定性、安全性、多用户支持和多任务处理能力,因此被广泛应用于服务器、嵌入式系统以及个人电脑等领域......
  • linux硬件管理-dmidecode命令
    dmidecode命令主要用于获取主机的硬件信息,通常是在不打开计算机机箱的情况下使用该命令来查找硬件详细信息。其输出的信息包括BIOS、系统、主板、处理器、内存、缓存等等。常用用法[root@localhost~]$dmidecode#打印所有硬件信息[root@localhos......
  • 单调队列
    题目1点击查看代码#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#definepiipair<int,int>#defineinf0x3f3f3f3fsignedmain(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);intn,m;cin>>n>>m;......
  • Linux 安装IntelAx211无线网卡
    https://blog.csdn.net/shikaiaixuexi/article/details/131565396sudoaptinstallgitmakesudoaptinstallflexbisongitclonehttps://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/backport-iwlwifi.gitcdbackport-iwlwifisudomakedefconfig-iwlwifi-......
  • RHEL 9 / Rocky Linux 9 上安装 MySQL
    MySQL 是热门的开源关系数据库(RDBMS)由Oracle开发和维护。它提供SQL(结构化查询语言)语法,用于小型和大规模企业处理数据库。在这篇文章中,我们将解释如何在RHEL9或RockyLinux9上安装MySQL数据库服务器。我们将介绍MySQL8.0和最新版本的MySQL8.3.0的安装步骤。1.......
  • Linux - 报错“Address already in use”解决方案
    报"Addressalreadyinuse",如下图所示:错误原因:某程序正在使用端口。(这里我使用的是端口“8888”)可以通过命令查看所有正在使用的端口:netstat-tunllp 解决方案1.找到占用该端口的进程号使用命令:sudonetstat-anp|grep"8888"(端口号)可以看到进程号为8888的serv......
  • TN系统 TN System
    一、电力系统有一点直接接地,电气装置的外露可导电部分通过保护线与该接地点相连接。根据中性导体(N)和保护导体(PE)的配置方式,TN系统可分为如下三类:1 TN-C系统整个系统的N、PE线是合一的;2 TN-C-S系统系统中有一部分线路的N、PE线是合一的;3 TN-S系统整个系统的N、PE线是分开......
  • 【Linux】互斥 | 死锁
    线程互斥一些概念临界资源:多线程之间共享的资源就是临界资源。通常为一些全局的变量。临界区:访问或者修改临界资源的代码就是临界区。互斥:任何时刻,保证只有一个执行流访问临界资源。原子性:不受调度机制打断的操作。操作要么完成,要么就是未完成,一步到位。锁的背景编写一个......
  • 在LINUX下,关于文件读写的操作
    对于我在做EMS的项目中需要把关键数据要保存下来,之前采用将关键数据保存在EMMC当中,结果发现会导致系统崩溃,所以还是采用将数据存储在文件的方法。下面是文件的相关操作//在嵌入式系统中,可以使用标准C库提供的文件操作函数来进行文件的读、写和删除操作。下面是对应的实现方......
  • leedcode-用队列实现栈
    利用内置的listclassMyStack:def__init__(self):#初始化一个空列表用于存储栈的元素self.li=list()defpush(self,x:int)->None:#向栈中压入元素xself.li.append(x)defpop(self)->int:#从栈顶弹......