栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

linux -- System V 消息队列

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

linux -- System V 消息队列

目录
    • 一、相关函数
      • 1.1、创建:msgget()
      • 1.2、发送:msgsend()
      • 1.3、接收:msgrcv()
      • 1.4、操作:msgctl()
    • 二、简单测试
      • 2.1、用单进程来测试消息队列的所有操作

一、相关函数
  • 头文件
#include 
#include 
#include 
1.1、创建:msgget()

功能:返回与键值对应的消息队列id,若没有则创建新的消息队列

int msgget(key_t key, int msgflg);
key_t ftok(const char *pathname, int proj_id);

msgget

  • key:消息队列的键值
    可以自定义(>0),也可以由ftok生成
    key 为 IPC_PRIVATE时将创建新的消息队列,且只能创建
  • msgflg:消息队列的权限
    IPC_CREAT:创建新的消息队列
    IPC_EXCL:与IPC_CREAT一同使用,表示如果要创建的消息队列已经存在,则返回 -1。
    IPC_NOWAIT:读写消息队列要求无法满足时,不阻塞。
  • 返回值
    成功:消息队列id (msqid)
    失败:-1

ftok:返回消息队列键值

  • pathname:文件名
  • projid:项目ID,必须为非0整数(0-255).
    pathname通常设置为当前目录“.” ,若projid为’a’,则为"./a"文件

创建新的消息队列会初始化msqid_ds结构体

1.2、发送:msgsend()

功能:往消息队列发送数据

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
  • msqid:消息队列的id
  • msgp:要发送消息的指针
  • msgsz:消息的长度
  • msgflg:当消息队列已满时的处理方式
    IPC_NOWAIT:若消息队列已满,使用msgsend直接返回-1
    0:若消息队列已满,则调用msgsend被挂起,直到可写入
  • 返回值:
    0 成功
    -1 失败

msgp指向的结构为

 struct msgbuf {
     long mtype;       
     char mtext[1];    
 };
1.3、接收:msgrcv()

功能:从消息队列读取一个消息。如果读取成功,队列中的该消息将被删除。

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
  • msqid:消息队列id
  • msgp:要存放消息的指针
  • msgsz:消息内容的长度(字节)
  • msgtyp:消息的读取类型
    0:返回队列中的第一个消息
    >0:返回队列中种类(mtype)为msgtyp的第一个消息
    <0:返回队列中小于等于负msgtyp类型值最小的一个
  • msgflg:消息不存在时的处理方式
    IPC_NOWAIT:若没有符合的消息,则返回-1
    MSG_NOERROR:若返回的消息比msgsz多,则消息就会截短,且不通知消息发送进程.
    0:挂起调用进程直到有对应的消息
  • 返回值:
    -1 失败
    > -1 返回成功读出消息的字节数
1.4、操作:msgctl()

功能·:控制消息队列

int msgctl(int msqid, int cmd, struct msqid_ds *buf);
  • msqid:消息队列id
  • cmd:要执行的操作
    IPC_STAT:将当前队列msqid_ds的结构存放在buf所指向的结构中
    IPC_SET:按buf所指向的结构设置当前队列的msqid_ds
    IPC_RMID:删除消息队列和其中的数据.
  • buf:存放消息队列属性
  • 返回值
    -1 失败
    0 成功
  • struct msqid_ds
 struct msqid_ds {
     struct ipc_perm msg_perm;     
     time_t          msg_stime;    
     time_t          msg_rtime;    
     time_t          msg_ctime;    
     unsigned long   __msg_cbytes; 
     msgqnum_t       msg_qnum;     
     msglen_t        msg_qbytes;   
     pid_t           msg_lspid;    
     pid_t           msg_lrpid;    
 };
  • struct ipc_perm
 struct ipc_perm {
     key_t          __key;       
     uid_t          uid;         
     gid_t          gid;         
     uid_t          cuid;        
     gid_t          cgid;        
     unsigned short mode;        
     unsigned short __seq;       
 };
二、简单测试 2.1、用单进程来测试消息队列的所有操作
#include 
#include 
#include 
#include 
#include 
#include 
#include 


typedef struct MsgBuf{
    long mtype;
    char mtext[10];
}MsgBuf;

void MsgStat(int, struct msqid_ds,char *);//打印消息队列属性

int main() {
    pid_t pid;
    key_t key;
    int ret;
    int msg_id,msg_flg;
    struct msqid_ds msginfo;
    MsgBuf msgbuf;

    
    key = ftok(".",'a');
    printf("key = %dn",key);
    printf("pid = %dn",getpid());

    
    msg_flg = IPC_CREAT|IPC_EXCL;
    msg_id = msgget(key,msg_flg|0666);
    if(msg_id == -1){
        printf("msgget errorn");
        return 0;
    }
    printf("msgid = %dn",msg_id);
    memset(&msginfo,0, sizeof(struct msqid_ds));
    MsgStat(msg_id,msginfo,"msgget");

    
    memset(&msgbuf,0, sizeof(MsgBuf));
    msgbuf.mtype = 16;
    memcpy(msgbuf.mtext,"abcde",5);
    msg_flg = IPC_NOWAIT;
    ret = msgsnd(msg_id,&msgbuf, sizeof(msgbuf.mtext),msg_flg);
    if(ret == -1){
        printf("msgsnd errorn");
        msgctl(msg_id,IPC_RMID,NULL);
        return 0;
    }
    MsgStat(msg_id,msginfo,"msgsnd");

    
    memset(&msgbuf,0, sizeof(MsgBuf));
    msg_flg = MSG_NOERROR|IPC_NOWAIT;
    ret = (int)msgrcv(msg_id,&msgbuf,4,16,msg_flg);
    if(ret == -1){
        printf("msgrcv errorn");
        msgctl(msg_id,IPC_RMID,NULL);
        return 0;
    }
    else{
        printf("从消息队列读到 %d 个字节t",ret);
        printf("消息是:%sn",msgbuf.mtext);
    }
    MsgStat(msg_id,msginfo,"msgrcv");

    
    msginfo.msg_perm.uid = 8;
    msginfo.msg_perm.gid = 8;
    msginfo.msg_qbytes = 16386;
    ret = msgctl(msg_id,IPC_SET,&msginfo);
    if(ret == -1){
        printf("msgctl errorn");
        msgctl(msg_id,IPC_RMID,NULL);
        return 0;
    }
    MsgStat(msg_id,msginfo,"msgctl");

    
   ret = msgctl(msg_id,IPC_RMID,NULL);

    return 0;
}

void MsgStat(int msg_id, struct msqid_ds msg_info,char *buf){
    int ret;
    sleep(2);//方便观察
    printf("n******************************************n");
    printf("after %s: nn",buf);
    ret = msgctl(msg_id,IPC_STAT,&msg_info);
    if(ret == -1){
        printf("get msg info errorn");
        printf("******************************************n");
        return;
    }

    printf("msg uid:%dt",msg_info.msg_perm.uid);
    printf("msg gid:%dn",msg_info.msg_perm.gid);
    printf("上一次使用msgsnd时间:%s",ctime(&(msg_info.msg_stime)));
    printf("上一次使用msgrcv时间:%s",ctime(&(msg_info.msg_rtime)));
    printf("上一次修改时间:%s",ctime(&(msg_info.msg_ctime)));
    printf("当前队列里的字节数为:%ldn",msg_info.msg_cbytes);
    printf("当前队列里的消息数量:%ldn",msg_info.msg_qnum);
    printf("队列的最大容量(字节数):%ldn",msg_info.msg_qbytes);
    printf("上次使用msgsnd的进程pid:%dn",msg_info.msg_lspid);
    printf("上次使用msgrcv的进程pid:%dn",msg_info.msg_lrpid);
    printf("******************************************n");
}


参考:man手册、《高质量嵌入式Linux C编程》梁庚 陈明 马小陆 编著 第265 -273页

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/923785.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号