系统编程-消息队列

消息队列

目录

消息队列

引入

一、消息队列的特点

二、使用指令查看消息队列

三、使用消息队列进行通信的步骤

1、获取键值

2、创建或获取消息队列 id

3、使用消息队列进行数据的传输

4、msgrcv -- 从消息队列中读取数据

5、消息队列的多种操作函数


引入

-- 进程间通信 (IPC)是指在不同进程之间传播或交换信息。IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等。

-- 这章讲消息队列

  • 相当于系统级别的链表(系统开着,消息队列在。系统关,消息队列关)-- 所有进程都可使用

  • 多个进程间进行数据传输           -- 消息队列

一、消息队列的特点

-- 类似于管道

  • (1)先进先出,数据读出来会从消息队列中消失。

  • (2)要进行消息的读取,必须有消息否则会读阻塞。

  • (3)消息队列满了,会产生写阻塞。

  • (4)有消息类型之分,用来确定读取的消息类型

-- 消息队列可以解决的问题:多个进程间进行数据的传输

二、使用指令查看消息队列

-- 指令:ipcs

  • ipas可以查看系统下的system V的状态 

    alt text

-- 指令:ipcs -q 只查看消息队列 

alt text

-- 消息队列的相关信息:

  • 键值:获取消息队列 id 的唯一标识符,一个键值对应一个消息队列的 id,是八位的十六进制,例如 0x12345678

  • msqid:用于区分不同的消息队列 也代表该消息队列的号(id)

  • 拥有者:谁创建的

  • 权限:对该消息队列的操作权限
    例:666 可读可写

  • 已用字节数:消息队列中一共存放了多少个字节的信息

  • 消息:存放了消息的个数


三、使用消息队列进行通信的步骤

alt text

1、获取键值

(1)函数获取:

-- 函数头文件

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

-- 函数原型

  • key_t ftok(const char *pathname, int proj_id)

-- 函数的作用:

  • 通过传入的参数来获取指定的键值(ftok的两个参数一样,获取的键值就一样)

-- 函数的参数:

  • pathname:必须是存在的路径
  • proj_id:0~255

-- 函数的返回值:

  • 会根据函数的参数来返回一个键值

alt text

(2)自己定义:

  • #define my_key 0x12345678

-- 键值的作用:

  • 一样的键值可以让不同进程来获取到同一个消息队列的id号
  • 一个键值对应一个id号,是一一对应的。具有唯一性。

2、创建或获取消息队列 id

-- 函数头文件

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

-- 函数原型

  • int msgget(key_t key, int msgflg)

-- 函数的作用:

  • 创建或获取消息队列的 id 用于进程间通信

-- 函数的参数:

  • key:键值 相同的键值可以获取相同的消息队列 id
  • msgflg:固定填写    IPC_CREAT|0666

-- 函数的返回值:

  • 成功返回 消息队列的 id >= 0
  • 失败返回 -1

alt text

alt text

3、使用消息队列进行数据的传输

-- 收发的数据类型必须为结构体

-- 函数的头文件

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

-- 函数原型

  • int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

-- 函数的作用:

  • 向指定的消息队列中发送一条消息

-- 函数的参数:

  • msqid:要将消息发送到哪一个消息队列中去

  • msgsz:填写 mtext 的大小 ,填写:第二个参数的结构体大小 - 8

  • msgflg:填0是阻塞发送,如果消息队列空间不够,会阻塞,直到有空间可以进行写入
    -- IPC_NOWAIT 非阻塞发送

  • msgp:发送的消息的首地址

-- 这里必须要用结构体 需要自己在程序中定义(发送和接收的结构体必须定义的一模一样)

struct msgbuf {
    long mtype;
    /* message type, must be > 0 */
    char mtext[1];
    /* message data */
    xxxx;
    .....;
};

-- 结构体中的第一个成员必须为 long 类型,赋值时必须给大于 0 的值

-- 函数的返回值:

  • 成功返回 0
  • 失败返回 -1
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>

#define key 0x12345678

struct student
{
	long mtype;  -- 第一个数据类型必须是long型
	int id;
	char name[20];
};

int main()
{

	//key_t  key = ftok("/home/pimouren/learn", 55);
	printf("%x\n",key);
	
	int id = msgget(key,IPC_CREAT|0666);
	if(id == -1)
	{
		perror("msgget");
		return -1;
	}
	printf("id = %d\n",id);
	
	struct student stu;
	printf("请输入学生的学号!\n");
	scanf("%d",&stu.id);
	printf("请输入学生的名字!\n");
	scanf("%s",stu.name);
	
	int  mm = msgsnd(id, &stu,sizeof(stu)-8, 0);
	if(mm == -1)
	{
		perror("msgsnd");
		return -1;
	}
	
	
	return 0;
}

alt text

-- 再次向消息队列中写入数据,已用字节数发生改变

alt text

4、msgrcv         -- 从消息队列中读取数据

-- 函数头文件

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

-- 函数的原型

  • ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

-- 函数的作用:

  • 从消息队列中进行数据的读取

-- 函数的参数:

  • msqid:要从哪一个消息队列读取消息
  • msgp:读取到的消息保存的首地址
  • msgsz:要读取的消息字节数,填写结构体大小 - 8
  • msgtyp:要接受的消息类型

"> 0"
-- 接收指定的消息类型中的第一条消息
"0"
-- 接收消息队列中的第一条消息
"<0"
-- 接收小于 msgtyp 绝对值的消息类型
例如 填写-3, |-3| == 3 ,那么可以读取 1 或2 的消息类型

  • msgflg: 0 阻塞接收 如果没有 msgtyp 指定消息类型会一直阻塞 直到有该消息类型来到 IPC_NOWAIT 非阻塞

-- 函数的返回值:

  • 成功返回 实际读取到的字节数
  • 失败返回 -1

alt text

alt text

alt text

5、消息队列的多种操作函数

-- 函数头文件

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

-- 函数原型

  • int msgctl(int msqid, int cmd, struct msqid_ds *buf);

-- 函数的作用:

  • 对消息队列进行多种操作 例如:获取消息队列的信息, 更改消息队列设置, 删除消息队列

-- 函数的参数:

  • msqid:消息队列的 id 你要对哪一个消息队列进行操作
  • cmd:要进行的具体操作

IPC_STAT 获取消息队列的信息
IPC_SET 更改消息队列的设置
IPC_RMID 删除消息队列
当 cmd 为 IPC_RMID 时 第三个参数给 NULL buf:结构体指针 用于传出和设置消息队列属性

-- 函数的返回值:

  • 成功 返回 0
  • 失败 返回 -1

-- 这个函数主要用来删除消息队列

alt text

-- 使用指令删除消息队列

  • 指令:ipcrm -q msgid

alt text

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值