Linux学习笔记之消息队列

进程间通信之IPC 对象:

IPC: 进程间通信

IPC对象: 内核维护的一组共享数据对象;
消息队列对象 共享内存对象 信号量集对象

IPC 通用操作框架:
创建key值 》申请IPC对象 》打开对象》读写对象
关闭对象 ==》卸载对象

1、唯一key值的创建:
1.1 私有键值 ==》IPC_PRIVATE 只给亲缘关系进程使用;
1.2 临时键值 ==》ftok() 临时创建键值
1.3 自定义键值 ==》 0x12345678 0x888 0x666

#include <sys/types.h>
#include <sys/ipc.h>

key_t ftok(const char *pathname, int proj_id);
功能:该函数可以根据指定的路径和id唯一生成一个key值;
参数: pathname 指定一个不能被删除重建的路径
id 指定一个128 以内的任意数字;
返回值:成功 唯一key值
失败 -1;

2、消息队列操作框架:
申请/打开消息队列对象 ===》读写对象 ===》卸载对象
msgget() msgsnd() msgctl()
msgrcv()

#include <sys/msg.h>

int msgget(key_t key, int msgflg);
功能:该函数可以根据key值向操作系统内核提出消息队列使用申请;
参数:key 唯一键值
msgflg 申请消息队列的方式以及权限
如果是第一次申请用IPC_CREAT 来创建对象
如果不是第一次申请用IPC_EXCL 来检测判断
权限使用八进制的默认权限
返回值:成功 msgid 的消息队列对象id
失败 -1

注意要验证申请的对象是否创建成功可以通过一下shell命令查看;

ipcs -a ===> 可以查看所有IPC对象信息
ipcs -q ====》只查看消息队列对象信息

删除:
ipcrm -q msgid
eg: ipcrm -q 0

读写消息队列:===》进程间通信

写操作:msgsnd()
int msgsnd(int msqid, const void msgp, size_t msgsz, int msgflg);
功能:该函数可以将指定的格式的数据写入目标消息队列对象中。
参数:msqid 要存储消息的消息队列id
msgp 要存储消息的消息格式,一般如下格式:
struct msgbuf {
long mtype; /
message type, must be > 0 /
char mtext[128]; /
message data */
};
msgsz 要存储消息的大小,一般是参数2的大小
msgflg 存储消息的方式,0 表示阻塞存储,IPC_NOWAIT 表示非阻塞;
返回值:成功 0
失败 -1;

读操作: msgrcv()
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);
功能:该函数可以从指定的消息队列对象中获取数据到本地内存。
参数: msqid 消息队列id
msgp 获取消息后存储到本地的本地内存,一般和发送数据结构一样;
msgsz 预计获取数据的长度
msgtyp 要获取数据的类型
msgflg 获取数据的方式,0 表示阻塞获取;
返回值:成功 返回实际获取的数据长度
失败 -1;

删除消息队列对象: msgctl
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:该函数可以修改指定消息队列的属性,也可以删除消息队列;
属性一般不做调整,多用于删除操作。
参数:msqid 要删除的目标消息队列id
cmd IPC_RMID 表示删除消息队列
buf NULL 表示属性不做调整;
返回值:成功 0
失败 -1;

//消息队列接受消息
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>

#define SIZE sizeof(struct msgbuf)-sizeof(long)

struct msgbuf
{
      long mtype;
      //消息正文
      int a;
      char b;
};

int main()
{
      //获得key值
      key_t key;
      if(key=ftok(".",'q')<0)
      {
           perror("key error\n");
           return -1;      
      }
      //创建获打开消息队列
      int msqid;
      struct msgbuf msgbuf;      
      if(msqid=msgget(key,IPC_CREAT|IPC_EXCL|0664)<0)
      {
           if(errno!=EEXIST)
           {
                perror("msgget error\n");
                return -1;                 
           }
           else
           {    
                //如果存在,则打开消息队列
                msqid=msgget(key,0664);
           }
      }
      //接受消息
      msgrcv(msqid,&msgbuf,SIZE,100,0);
      
      printf("a=%d b=%c\n",msgbuf.a,msgbuf.b);
      
      //删除消息队列
      msgctl(msqid,IPC_RMID,NULL);
      system("ipcs -q");      
      return 0;
}
//消息队列发送消息
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define SIZE sizeof(struct msgbuf)-sizeof(long)

struct msgbuf
{
      long mtype;
      //消息正文
      int a;
      char b;
};
int main()
{
      //获得key值
      key_t key;
      if(key=ftok(".",'q')<0)
      {
           perror("key error\n");
           return -1;      
      }
      //创建获打开消息队列
      int msqid;
      struct msgbuf msgbuf;
      if(msqid=msgget(key,IPC_CREAT|IPC_EXCL|0664)<0)
      {
           if(errno!=EEXIST)
           {
                perror("msgget error\n");
                return -1;                 
           }
           else
           {    
                //如果存在,则打开消息队列
                msqid=msgget(key,0664);
           }
      }
      msgbuf.mtype=100;
      msgbuf.a=10;
      msgbuf.b='q';
      
      msgsnd(msqid,&msgbuf,SIZE,0);
      
      system("ipcs -q");
      return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值