linux 消息队列状态:struct msqid_ds

2023-11-11

Linux的消息队列(queue)实质上是一个链表, 它有消息队列标识符(queue ID). msgget创建一个新队列或打开一个存在的队列; msgsnd向队列末端添加一条新消息; msgrcv从队列中取消息, 取消息是不一定遵循先进先出的, 也可以按消息的类型字段取消息. 


1. 标识符(des)和键(key):


    消息队列, 信号量和共享存储段, 都属于内核中的IPC结构, 它们都用标识符来描述. 这个标识符是一个非负整数, 与文件描述符不同的是, 创建时并不会重复利用通过删除回收的整数, 而是每次+1, 直到整数最大值回转到0.


    标识符是IPC对象的内部名, 而它的外部名则是key(键), 它的基本类型是key_t, 在头文件<sys/types.h>中定义为长整型. 键由内核变换成标识符.


2. 消息队列状态msqid_ds:


    每个消息队列都有一个msqid_ds结构与其关联:




struct msqid_ds
  {
    struct msqid_ds {
    struct ipc_perm msg_perm;
    struct msg *msg_first;      /* first message on queue,unused  */
    struct msg *msg_last;       /* last message in queue,unused */
    __kernel_time_t msg_stime;  /* last msgsnd time */
    __kernel_time_t msg_rtime;  /* last msgrcv time */
    __kernel_time_t msg_ctime;  /* last change time */
    unsigned long  msg_lcbytes; /* Reuse junk fields for 32 bit */
    unsigned long  msg_lqbytes; /* ditto */
    unsigned short msg_cbytes;  /* current number of bytes on queue */
    unsigned short msg_qnum;    /* number of messages in queue */
    unsigned short msg_qbytes;  /* max number of bytes on queue */
    __kernel_ipc_pid_t msg_lspid;   /* pid of last msgsnd */
    __kernel_ipc_pid_t msg_lrpid;   /* last receive pid */
};




3. 由路径名和项目ID产生一个key:


    如果客户进程和服务器进程认同一个路径名和项目ID(0~255间的字符值), 接着调用ftok将这两个值变换为一个key.


原型: key_t ftok(const char *path, int id); 
头文件: <sys/ipc.h> 
返回值: 成功则返回key, 出错则返回(key_t)-1. 
参数: path参数必须引用一个现存文件. 当产生key时 只使用id参数的低8位. 
说 明: 如果两个路径名引用两个不同的文件, 对这两个路径名调用ftok通常返回不同的key. 但是, 因为i节点号和key通常存放在长整型中, 于是创建key时可能会丢失信息. 这意味着, 如果使用同一项目ID, 那么对于不同文件的两个路径名可能产生相同的key. 该函数的工作方式为: 
按给定的路径名取得其stat结构. 
从该结构中取出部分st_dev和st_ino字段, 与项目ID组合起来. 
4. 创建/打开消息队列:


    msgget可以创建一个新队列或打开一个存在的队列.


原型: int msgget(key_t key, int flag); 
头文件: <sys/msg.h> 
返回值: 成功则返回消息队列ID, 出错则返回-1. 
参数: 
key: 消息队列的key值. 
flag: 标志位. 
说明: 
创建队列有两种方法: 
key是IPC_PRIVATE. 
key当前未与特定类型的IPC结构相结合, 并且flag中指定了IPC_CREAT位. 
初始化msqid_ds成员: 
ipc_perm中的mode成员按flag进行设置. 
msg_qnum, msg_lspid, msg_lrpid, msg_stime和msg_rtime都设置为0. 
msg_ctime设置为当前时间. 
msg_qbytes设置为系统限制值. 
5. 消息队列的垃圾桶函数:


    msgctl类似于驱动程序中的ioctl函数, 可对消息队列执行多种操作.


原型: int msgctl(int msqid, int cmd, struct msgqid_ds *buf); 
头文件: <sys/msg.h> 
返回值: 成功则返回0, 出错则返回-1. 
参数: cmd参数说明对msqid指定的队列要执行的命令: 
IPC_STAT: 取此队列的msqid_ds结构, 并将它存放在buf指向的结构中. 
IPC_SET: 按由buf指向结构中的值, 设置与此队列相关结构中的msg_perm.uid, msg_perm.gid, msg_perm.mode和msg_qbytes. 该命令只有下列两种进程可以执行: 
有效用户ID等于msg_perm.cuid或msg_per.uid. 
具有超级用户特权的进程. 
IPC_RMID: 从系统中删除该消息队列以及仍在该队列中的所有数据. 执行权限同上. 
6. 将数据放到消息队列:


    调用msgsnd将数据放到消息队列中.


原型: int msgsnd(int msqid, const void *ptr, size_t nbytes, int flag); 
头文件: <sys/msg.h> 
返回值: 成功则返回0, 出错则返回-1. 
说 明: 可以定义一个消息结构, 结构中带类型, 这样就可用非先进先出顺序取消息了. 当msgsnd成功返回, 与消息队列相关的msqid_ds结构得到更新, 以标明发出该调用的进程ID(msg_lsqid), 进行该调用的时间(msg_stime), 并指示队列中增加了一条消息(msg_qnum). 
7. 从消息队列中取消息:


    调用msgrcv将从消息队列中取消息.


原型: ssize_t msgrcv(int msqid, void *ptr, size_t nbytes, long type, int flag); 
头文件: <sys/msg.h> 
返回值: 成功则返回消息的数据部分的长度, 出错则返回-1. 
参数: 
ptr: 指向一个长整型数(返回的消息类型存放在其中), 跟随其后的是存放实际消息数据的缓冲区. 
nbytes: 数据缓冲区的长度. 若返回的消息大于nbytes, 且在flag中设置了MSG_NOERROR, 则该消息被截短. 
type: 
type == 0: 返回队列中的第一个消息. 
type > 0: 返回队列中消息类型为type的第一个消息. 
type < 0: 返回队列中消息类型值小于或等于type绝对值的消息, 如果这种消息有若干个, 则取类型值最小的消息. 
说明: 当msgrcv成功返回时, 与消息队列相关的msqid_ds结构被更新, 以指示调用者的进程ID(msg_lrpid), 调用时间(msg_rtime)和队列中的消息数(msg_qnum)减1. 
四、消息队列应用实例
消息队列应用相对较简单,下面实例基本上覆盖了对消息队列的所有操作,同时,程序输出结果有助于加深对前面所讲的某些规则及消息队列限制的理解。


#include <sys/types.h>
#include <sys/msg.h>
#include <unistd.h>
void msg_stat(int,struct msqid_ds );
main()
{
int gflags,sflags,rflags;
key_t key;
int msgid;
int reval;
struct msgsbuf{
        int mtype;
        char mtext[1];
    }msg_sbuf;
struct msgmbuf
    {
    int mtype;
    char mtext[10];
    }msg_rbuf;
struct msqid_ds msg_ginfo,msg_sinfo;
char* msgpath="/unix/msgqueue";
key=ftok(msgpath,'a');
gflags=IPC_CREAT|IPC_EXCL;
msgid=msgget(key,gflags|00666);
if(msgid==-1)
{
    printf("msg create error\n");
    return;
}
//创建一个消息队列后,输出消息队列缺省属性
msg_stat(msgid,msg_ginfo);
sflags=IPC_NOWAIT;
msg_sbuf.mtype=10;
msg_sbuf.mtext[0]='a';
reval=msgsnd(msgid,&msg_sbuf,sizeof(msg_sbuf.mtext),sflags);
if(reval==-1)
{
    printf("message send error\n");
}
//发送一个消息后,输出消息队列属性
msg_stat(msgid,msg_ginfo);
rflags=IPC_NOWAIT|MSG_NOERROR;
reval=msgrcv(msgid,&msg_rbuf,4,10,rflags);
if(reval==-1)
    printf("read msg error\n");
else
    printf("read from msg queue %d bytes\n",reval);
//从消息队列中读出消息后,输出消息队列属性
msg_stat(msgid,msg_ginfo);
msg_sinfo.msg_perm.uid=8;//just a try
msg_sinfo.msg_perm.gid=8;//
msg_sinfo.msg_qbytes=16388;
//此处验证超级用户可以更改消息队列的缺省msg_qbytes
//注意这里设置的值大于缺省值
reval=msgctl(msgid,IPC_SET,&msg_sinfo);
if(reval==-1)
{
    printf("msg set info error\n");
    return;
}
msg_stat(msgid,msg_ginfo);
//验证设置消息队列属性
reval=msgctl(msgid,IPC_RMID,NULL);//删除消息队列
if(reval==-1)
{
    printf("unlink msg queue error\n");
    return;
}
}
void msg_stat(int msgid,struct msqid_ds msg_info)
{
int reval;
sleep(1);//只是为了后面输出时间的方便
reval=msgctl(msgid,IPC_STAT,&msg_info);
if(reval==-1)
{
    printf("get msg info error\n");
    return;
}
printf("\n");
printf("current number of bytes on queue is %d\n",msg_info.msg_cbytes);
printf("number of messages in queue is %d\n",msg_info.msg_qnum);
printf("max number of bytes on queue is %d\n",msg_info.msg_qbytes);
//每个消息队列的容量(字节数)都有限制MSGMNB,值的大小因系统而异。在创建新的消息队列时,//msg_qbytes的缺省值就是MSGMNB
printf("pid of last msgsnd is %d\n",msg_info.msg_lspid);
printf("pid of last msgrcv is %d\n",msg_info.msg_lrpid);
printf("last msgsnd time is %s", ctime(&(msg_info.msg_stime)));
printf("last msgrcv time is %s", ctime(&(msg_info.msg_rtime)));
printf("last change time is %s", ctime(&(msg_info.msg_ctime)));
printf("msg uid is %d\n",msg_info.msg_perm.uid);
printf("msg gid is %d\n",msg_info.msg_perm.gid);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux 消息队列状态:struct msqid_ds 的相关文章

随机推荐

  • 低门槛+低成本大学生宿舍物联网门锁系统(APP+小程序+Stm32)

    系统简介 本物联网门锁由 Stm32F103开发板 微信小程序 手机APP Wcf服务后端 vbnet辅助服务程序 sqlite数据库组成 适合软件 控制 通信等相关专业的同学练手 所有代码无偿公开 经测试能保证长时间稳定运行 实际部署时有
  • AlexNet VGGNet ResNet 对比 简介

    AlexNet 网络结构 多GPU Relu Dropout 层叠池化 图片的随机采样 其他 VGGNet 网络结构 3 3 卷积核 1 1 卷积核 LRN 其他 ResNet 退化问题 残差学习 残差网络子结构 网络结构 referenc
  • oracle 修改数据库的字符集编码为UTF-8

    转 http www cnblogs com rootq articles 2049324 html Oracle 字符集的查看和修改 一 什么是Oracle字符集 Oracle字符集是一个字节数据的解释的符号集合 有大小之分 有相互的包容
  • 网站服务器挂了几天排名恢复,网站恢复排名方法

    身为一名seo行业的优化人员 必须要掌握的一点就是要时刻关注搜索引擎的算法规则更新 否则网站的一些架构跟内容难免的被新算法出来给打击了 严重的情况一般会导致降权甚至K站 下面站优云的小编就针对网站被降权如何恢复排名做个简单的介绍 一 提高友
  • bash循环得到日期目录

    1 bin bash 2 today date Y m d 3 echo today is today 4 single input raw data 5 6 7 startday date Y m d d 90 days ago 8 en
  • 计算机毕业设计之基于tensorflow-lstm的股票爬虫+预测及可视化

    1 简介 博主介绍 全网粉丝30W csdn特邀作者 博客专家 CSDN新星计划导师 编程领域优质创作者 博客之星 各平台优质作者 专注于Java python等技术领域和毕业项目实战 文末获取源码联系 计算机毕业设计之基于tensorfl
  • 最短路径A*算法原理及java代码实现(看不懂是我的失败)

    算法只要懂原理了 代码都是小问题 先看下面理论 尤其是红色标注的 要源码请留下邮箱 有测试用例 直接运行即可 A 算法 百度上的解释 A 1 A Star 算法是一种静态路网中求解最短路最有效的直接搜索方法 公式表示为 f n g n h
  • 图像边缘检测

    文章目录 前言 一 图像边缘检测 二 边缘检测算子 1 Roberts算子 2 Prewitt算子 3 Sobel算子 三 代码实现 总结 前言 有了图像放大缩小 图像灰度化处理等相关基础知识过后 就可以进行图像边缘检测了 边缘检测最后也会
  • 全屋智能家居搭建初级指南(装修用户)

    环境 小M等智能设备 新装修用户 稳定网络环境 规划好电路布局 问题描述 全屋智能家居如何搭建 初级指南 装修用户 下面部分内容摘自小M智能家居 解决方案 一 装修中需要注意什么 句话概括 需在水电进场前考虑智能家居设计 主要准备两件事 铺
  • jdbc,jpa,springjdbc,springdatajpa,mybatis之间的区别

    jdbc jdbc是Java提供的原生态接口 操作数据库的唯一技术 缺点 重复写代码 代码写死 耦合性高 开发效率低换数据库比较苦难 优点 运行速度最快 所有操作数据库的技术底层都是jdbc写的 jpa java persistence a
  • 汉诺塔(Hanoi)理解(递归函数)

    1 编程求解汉诺塔问题 汉诺塔 Hanoi 是必须用递归方法才能解决的经典问题 它来自于印度神话 上帝创造世界时作了三根金刚石柱子 在第一根柱子上从下往上按大小顺序摞着64片黄金圆盘 如图7 3所示 上帝命令婆罗门把圆盘从下面开始按大小顺序
  • Postman使用Get请求和Post请求

    今天写了很多新活动接口文档 然后使用了Postman 主要总结一下postman的用法 1 Get请求 对应你方法中的getmapping 这种方法只要把参数拼上去就可以了 拼参数有两种格式 A在 中放入的参数 PathVariable 直
  • 业务架构·应用架构·数据架构实战~TOGAF理论全景解读

    1 解读TOGAF 9 2的BA DA AA TA内容模型 企业架构 Enterprise Architecture 包含如下四种架构 BA Business Architecture 业务架构 DA Data Architecture 数
  • 使用Linux脚本更新Weblogic部署的应用程序

    在利用Jenkins实现Weblogic应用自动部署的功能时 如何通过Shell 脚本自动更新Weblogic部署的应用程序呢 可以使用weblogic jar包中的weblogic Deployer这个class 命令如下 java we
  • 移动电源/充电管理设计

    移动电源 充电管理设计 简述 伴随着智能手机的兴起 智能手机的续航成了较大的问题 因此移动电源 充电宝 成为不时之需 而近来的各类无线耳机的兴起 无线耳机的续航又成为新的问题 为此针对无线耳机充电的各大厂商又一次成为热门 而这些都需要类似于
  • Windows11如何使用安卓子系统的Amazon Appstore

    这个月更新了Windows11以后 已经可以在微软应用商店下载安卓子系统并且安装安卓应用了 但是安卓子系统默认使用的是亚马逊的Amazon Appstore 目前这个商店只限制在美国使用 如果直接打开的话会提示Amazon AppStore
  • python学习日记【13 - 面向对象三】

    面向对象三 继承简介 方法重写 super 多重继承 多态 属性和方法 继承简介 继承是面向对象三大特性之一 通过继承我们可以使一个类获取到其他类中的属性和方法 在定义类时 可以在类名后面的括号中指定当前类的父类 超类 基类 继承提高了类的
  • 拥抱你的zsh,Linux下速通zsh&oh-my-zsh配置(附常用插件&主题)

    zsh oh my zsh配置 为什么要使用zsh 功能强大插件 丰富酷炫的主题 对bash完全兼容 这意味着与bash语法一致 功能更 健全 的Tab补全 代码高亮 相信你在阅读完本文以及用上zsh一段时间过后之后 可能并不需要很久 能对
  • 移动端适配方案之postcss-px-to-viewport

    之前做移动端适配时 基本上是采用rem方案 现在发现了一个新的方案 就是用viewport单位 现在viewport单位越来越受到众多浏览器的支持 postcss px to viewport 将px单位自动转换成viewport单位 用起
  • linux 消息队列状态:struct msqid_ds

    Linux的消息队列 queue 实质上是一个链表 它有消息队列标识符 queue ID msgget创建一个新队列或打开一个存在的队列 msgsnd向队列末端添加一条新消息 msgrcv从队列中取消息 取消息是不一定遵循先进先出的 也可以