进程通信之消息队列

博客主要围绕消息队列展开,首先介绍了消息队列是内核地址空间的内部链表,用于在Linux各进程间传递消息,通过ipc标识符区分,还说明了队列上消息结构可自定义且大小在msg.h有限制。此外,还提及了消息队列的操作函数,如键值构建、获取、发送、接收和控制函数等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.测试代码

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

void msg_show(int msg_id,struct msqid_ds msg_info)
{
        int ret=-1;
        sleep(1);
        ret=msgctl(msg_id,IPC_STAT,&msg_info);//get message
        if(ret==-1)
        {
                printf("get message failed!!");
                return ;
        }
        printf("\n");
/*show msg_info*/
        printf("the uid of msg is %d\n",msg_info.msg_perm.uid);

        printf("the gid of msg is %d\n",msg_info.msg_perm.gid);

        printf("现在消息队列中的字节数: %ld\n",msg_info.msg_cbytes);

        printf("现在队列中的消息数: %d\n",msg_info.msg_qnum);

        printf("现在消息队列中的最大字节数: %d\n",msg_info.msg_qbytes);

        printf("最后发送消息的进程: %d\n",msg_info.msg_lspid);

        printf("最后接受消息的进程: %d\n",msg_info.msg_lrpid);

        printf("最后发送消息的时间: %s\n",ctime(&(msg_info.msg_stime)));

        printf("最后接受消息的时间: %s\n",ctime(&(msg_info.msg_rtime)));

        printf("最后消息变化的时间: %s\n",ctime(&(msg_info.msg_ctime)));


}
int main()
{
        int ret=-1;
        int msg_flags,msg_id;
        key_t key;
        struct msgmbuf
        {
                int mtype;
                char mtext[20];
        };
        struct msqid_ds msg_info;  /*creat msg queue*/
        struct msgmbuf msg_mbuf;        /*消息缓冲结构*/
        char *rpath="/home/18/";
        int msg_sflags,msg_rflags;
        key=ftok(rpath,'b');  /*create key*/
        if(-1!=key)
        {
                printf("success!!\n");
        }
        else{
                printf("create key failed!\n");
        }
        msg_flags=IPC_CREAT|IPC_EXCL;
        msg_id=msgget(key,msg_flags);
        if(-1==msg_id)
        {
                printf("create msg faided!!\n");
        }
        msg_show(msg_id,msg_info);
        memcpy(msg_mbuf.mtext,"test message",sizeof("test message"));
        ret=msgsnd(msg_id,&msg_mbuf,sizeof("test message!!"),IPC_NOWAIT);
        if(ret==-1)
                printf("send failed!\n");

        msg_show(msg_id,msg_info);
        msg_rflags=IPC_NOWAIT|MSG_NOERROR;
        ret=msgrcv(msg_id,&msg_mbuf,20,0,msg_rflags);
        if(-1==ret)
                printf("mes receive failed!!\n");
        msg_show(msg_id,msg_info);


        msg_info.msg_perm.uid=8;
        msg_info.msg_perm.gid=8;
        msg_info.msg_qbytes=12345;
        ret=msgctl(msg_id,IPC_SET,&msg_info);/*set the property of msg*/
        if(-1==ret)
        {
                printf("set failed!!\n");
        }
        msg_show(msg_id,msg_info);
        ret=msgctl(msg_id,IPC_RMID,NULL);
        if(ret==-1)
                printf("delete failed!!\n");

        return 0;
}

2.消息队列结构

什么是消息队列?

消息队列是内核地址空间的内部链表,通过linux各个进程之间传递消息。消息队列通过ipc标识符区分

队列上一个消息的结构

#include<linux/msg.h>
struct msgbuf
{
    long mtype;  //消息类型
    char mtext[1];  //消息内容
}

该结构可以自己定义

消息的大小在msg.h中有限制

#define MSGMAX 8192

消息队列结构

#include<linux/msg.g>

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
{
    key_t key;    //函数msgget()使用的key
    uid_t uid;      //用户的uid
    gid_t gid ;       //用户的gid
    uid_t cuid;    //建立者的uid
    gid_t cgdid;    //建立者的gid
    unsigned short mode;    //权限
    unsigned short seq;    //序列号
};

3.操作函数

键值构建函数

#include<sys/types.h>
#include<sys/ipc.h>
key_t ftok(const char *pathname,int proj_id);

//如:
key_t key;
char *rpath="/ipc/msg/"
key=ftok(rpath,'a');
//第一个参数是已经存在的目录
//第二个参数一般是‘a’,'b'

从队列中获取消息

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
int msgget(key_t key,int msgflag);
//第一个参数是键值,用ftok()生成,拿来与内核中消息队列的值比较
//megflag取值如下:
IPC_CREAT:如果比较过后内核空间没有该消息队列,就创建它
IPC_EXCL:通常与IPC_CREAT一起使用,如msgflag=IPC_CREAT|IPC_EXCL;
//返回值:meg_id==>队列标识符

发送消息函数

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
int msgsnd(int msgqid,const void *msgp,size_t msgsz,int msgflag);
//第一个参数是用msgget得到的标识符
//第二个是指向消息缓冲区
//第三个是消息的大小(以字节为单位),不包含消息类型
//可取值:
0:表示忽略
IPC_NOWAIT:
//返回值:-1表示发送消息失败

接收消息函数

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
ssize_t msgrcv(int msqid,void* msgp,size_t msgsz,logn msgtyp,int msgflg);
//第一个参数指定消息队列
//第二个指向存放消息缓冲区
//第三个缓冲区大小(不包括mtype)
//第四个消息类型(如果为0返回队列中最老的消息)
//第五个

消息控制函数

#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
int msgctl(int msqid,int cmd,struct msqid_ds *buf);
//函数用途:向内核发送一个cmd命令,buf为应用层和内核空间数据交换的指针
cmd取值为:
IPC_STAT:获取队列的msqid_ds结构,并把它存在buf地址中
IPC_SET:设置队列的ipc_perm成员值,这个值先存在buf里
IPC_RMID:删除队列

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不要绝望总会慢慢变强

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值