当前位置:   article > 正文

Linux内核编程 消息队列使用案例_消息队列编程

消息队列编程

目录

一:IPC进程间通信

二:消息队列

三:消息队列的使用

四:进程间通信 消息队列编程

五:msgsnd函数 

六:消息队列的发送与接收


一:IPC进程间通信

现在linux使用的进程间通信方式:

1 管道(pipe)和命名管道(FIFO)

2 信号(signal)

3 消息队列【系统管理】

4 共享内存【系统管理】

5 信号量【系统管理】

6 套接字(socket)

socket套接字就是网络,网络编程也是IPC技术

利用网络实现两个应用程序之间的通信 【客户端和服务器】【两个进程间通信】

上面IPC技术中的 1-5都是本机操作,而6是两台计算机操作

二:消息队列

消息队列提供了一个 从一个进程向另外一个进程发送一块数据【一块数据 结构体】的方法

每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值

消息队列也有管道一样的不足,就是每个数据块的最大长度是有上限的[结构体有一定大小],系统上全体队列的最大总长度也有一个上限[系统管理着消息队列]

内存三剑客:

消息队列 、 共享内存 、 信号量

Linux操作系统可以通过命令查看      ipcs

消息队列 共享内存 信号量都是由操作系统直接管理的

信号和管道是由代码编写的main函数的主进程来管理

由操作系统管理的,那么它的整个内存区域不算做是进程间的;

信号和管道 的 内存区域是在 进程中的

消息队列 共享内存和信号量的内存区域在操作系统中【也就是在当前的要通信的两个进程的外部,内存空间不在进程中,不属于任何进程

消息队列、共享内存、信号量 不属于任何进程 

消息队列是消息的链表,存放在内核中并由消息队列标识符表示

三:消息队列的使用

包含头文件:<sys/msg.h><sys/types.h>和<sys/ipc.h>

int msgctl(int msqid, int cmd, struct msqid_ds *buf);//操作【如增删】

int msgget(key_t key, int msgflg);//【创建消息队列】

msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz,   long msg_typ, int msgflg);//接收

msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);//发送

msgget函数

作用:用来创建和访问一个消息队列

key: 某个消息队列的名字
msgflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
如果操作成功,msgget将返回一个非负整数,即该消息队列的标识码;如果失败,则返回“-1”

四:进程间通信 消息队列编程

查看msgget使用说明

返回:

成功(> -1)返回消息队列ID号/类型

-1则是出错/错误码

main.cpp

  1. #include<iostream>
  2. #include <sys/types.h>
  3. #include <sys/ipc.h>
  4. #include <sys/msg.h>
  5. #include<stdio.h>
  6. using namespace std;
  7. int main()
  8. {
  9. if (msgget((key_t)1001, IPC_CREAT | 0777) == -1)
  10. {
  11. perror("msgget error");
  12. }
  13. else
  14. {
  15. cout << "消息队列创建成功" << endl;
  16. }
  17. return 0;
  18. }

ipcs查看内存三剑客   可以看到消息队列创建成功

拥有者root 权限777 ,msqid是0  消息是0

将VS关闭程序运行,再次ipcs查看,消息队列的数据还在

说明了消息队列是由操作系统来管理 ,其内存空间也是由操作系统来管理,虽然进程关闭,但是消息队列还在

如果想要删除,使用 ipcrm,通过命令可以删除

ipcrm -h 可以查看 对于内存三剑客的操作

一般采取 ipcrm -a 初始化操作系统内存

根据手册提示 输入命名 ipcrm -q 0【按id号移除消息队列】

ipcs查看操作系统的内存,可以看出原先创建的消息队列已经被成功删除

对共享内存 消息队列 信号量 使用命令 ipcrm -a 来删除 最容易 

ipcrm -a 初始化操作系统内存

有些属于操作系统的内存不可被删除,如上图中 那些操作权限600,状态 2 的都是操作系统本身自带的 ,是不允许删除的

可以删除的只能是代码创建的,系统本身的内存是不可以被删除的

五:msgsnd函数 

msgsnd函数 

函数作用:把一条消息添加到消息队列里去

函数原型

int msgsnd(int msgid,const void *msg_ptr,size_t msg_sz,int msgflg);

msgid:由msgget函数返回的消息队列标识码

msg_ptr:是一个指针,指针指向准备发送的消息,

msg_sz:是msg_ptr指向的消息长度,这个长度不能保存消息类型的那个“long int”长整型计算在内

msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情

操作成功,返回“0”,如果失败,则返回“-1”

查看msgsnd使用说明 

msgbuf:必须指向固定要求的结构体

并且结构体  消息类型long型必须是>0   

同时 消息数据(char数据类型)

返回值:-1/错误码 是 失败 

main.cpp

  1. #include<iostream>
  2. #include <sys/types.h>
  3. #include <sys/ipc.h>
  4. #include <sys/msg.h>
  5. #include<stdio.h>
  6. #include<string.h>
  7. using namespace std;
  8. typedef struct msgsendbuf {
  9. long mtype; /* message type, must be > 0 */
  10. char mtext[50]; /* message data */
  11. }MSGBUF;
  12. int main()
  13. {
  14. //key_t如果不存在则创建,key_t如果存在则访问
  15. int msgid = msgget((key_t)1001, IPC_CREAT | 0777);
  16. if (msgid == -1)
  17. {
  18. perror("msgget error");
  19. }
  20. else
  21. {
  22. cout << "消息队列创建成功" << endl;
  23. }
  24. MSGBUF buf;
  25. buf.mtype = 1;//设置消息类型
  26. strcpy(buf.mtext, "hello world");
  27. //发送消息
  28. if (msgsnd(msgid, &buf, sizeof(MSGBUF), 0) == -1)
  29. {
  30. perror("msgsnd error");
  31. }
  32. return 0;
  33. }

已用字节数64 消息 1 ,已经发送消息成功

在VS中运行程序关闭进程,通过ipcs命令查看操作系统内存三剑客,消息队列仍然存在

做个测试:若消息队列不删除,再次运行一次程序

可以看出

字节数 128【发送一次64 发送二次128】   

消息 2 【发送2次】

对于msgget:key_t 如果不存在则创建,key_t 如果存在则访问

消息队列顺序 

队列:先进先出

尾部追加 头部删除

六:消息队列的发送与接收

消息队列的发送和接收,案例学习

初始化处理消息队列: 

命令 ipcrm -a            初始化操作系统内存       

命令 ipcs                   查看操作系统内存

查看msgcrv函数使用说明


消息队列的发送与接收,案例实现

发送 进程

main.cpp 

  1. #include<iostream>
  2. #include <sys/types.h>
  3. #include <sys/ipc.h>
  4. #include <sys/msg.h>
  5. #include<stdio.h>
  6. #include<string.h>
  7. using namespace std;
  8. typedef struct msgsendbuf {
  9. long mtype; /* message type, must be > 0 */
  10. char mtext[50]; /* message data */
  11. }MSGBUF;
  12. int main()
  13. {
  14. //key_t如果不存在则创建,key_t如果存在则访问
  15. int msgid = msgget((key_t)1001, IPC_CREAT | 0777);
  16. if (msgid == -1)
  17. {
  18. perror("msgget error");
  19. }
  20. else
  21. {
  22. cout << "消息队列创建成功" << endl;
  23. }
  24. for (int i = 0; i < 3; i++)
  25. {
  26. MSGBUF buf;
  27. buf.mtype = 1;//设置消息类型
  28. sprintf(buf.mtext, "hello world %d", i);
  29. //发送消息
  30. if (msgsnd(msgid, &buf, sizeof(MSGBUF), 0) == -1)
  31. {
  32. perror("msgsnd error");
  33. }
  34. }
  35. return 0;
  36. }

接收 进程

main.cpp

  1. #include<iostream>
  2. #include <sys/types.h>
  3. #include <sys/ipc.h>
  4. #include <sys/msg.h>
  5. #include<stdio.h>
  6. #include<string.h>
  7. using namespace std;
  8. typedef struct msgsendbuf {
  9. long mtype; /* message type, must be > 0 */
  10. char mtext[50]; /* message data */
  11. }MSGBUF;
  12. int main()
  13. {
  14. //key_t如果不存在则创建,key_t如果存在则访问
  15. int msgid = msgget((key_t)1001, IPC_CREAT | 0777);
  16. if (msgid == -1)
  17. {
  18. perror("msgget error");
  19. }
  20. else
  21. {
  22. cout << "消息队列创建成功" << endl;
  23. }
  24. MSGBUF buf = { 0 };
  25. for (int i = 0; i < 3; i++)
  26. {
  27. if (msgrcv(msgid, &buf, sizeof(MSGBUF), 1, 0) < 0)
  28. {
  29. perror("msgrcv error");
  30. }
  31. else {
  32. cout << "buf.mtext = " << buf.mtext << endl;
  33. }
  34. }
  35. return 0;
  36. }

g++ main.cpp -o main

./main

运行程序 生成进程 

消息队列创建成功 发送消息队列

ipcs查看内存

可以看出

消息队列 发送成功 

g++ main.cpp -o main

./main

运行程序 生成进程

可以看出

接收 消息队列 成功 

接收后  ipcs查看消息队列 

  

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/601598
推荐阅读
相关标签
  

闽ICP备14008679号