进程间通信(2)-消息队列

news/发布时间2024/5/16 19:05:20
Linux 中的消息队列是一种进程间通信(IPC)机制,允许不同进程之间通过消息进行通信。
 

消息队列中的相关函数:

msgget:创建或打开一个消息队列。
函数原型:int msgget(key_t key, int msgflg);
参数:
key:消息队列的键值,用于标识消息队列。
msgflg:标志参数,用于指定消息队列的创建方式和权限。
返回值:成功时返回消息队列的标识符(非负整数),失败时返回 -1。msgctl:对消息队列进行控制。
函数原型:int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数:
msqid:消息队列的标识符。
cmd:控制命令,用于指定执行的操作。
buf:指向 struct msqid_ds 结构的指针,用于传递或接收消息队列的状态信息。
返回值:成功时返回0,失败时返回 -1。msgsnd:向消息队列发送消息。
函数原型:int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数:
msqid:消息队列的标识符。
msgp:指向要发送的消息的指针。
msgsz:消息的大小(以字节为单位)。
msgflg:标志参数,用于指定发送消息的行为。
返回值:成功时返回0,失败时返回 -1。msgrcv:从消息队列接收消息。
函数原型:ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
参数:
msqid:消息队列的标识符。
msgp:指向存储接收消息的缓冲区的指针。
msgsz:缓冲区的大小(以字节为单位)。
msgtyp:指定所接收消息的类型。
msgflg:标志参数,用于指定接收消息的行为。
返回值:成功时返回接收到的消息的大小(以字节为单位),失败时返回 -1
对于ftok补充一点,ftok 函数是一个用于生成 System V IPC(Inter-Process Communication,进程间通信)中键值的函数。在 System V IPC 中,诸如消息队列、共享内存和信号量等资源都需要一个唯一的键值来标识。
ftok 函数的原型如下:
key_t ftok(const char *pathname, int proj_id);它接受两个参数:
pathname:一个指向文件的路径名的指针。通常情况下,你可以选择一个现有的文件,该文件的存在与否对 ftok 函数的结果不会产生影响,因为它只关注文件的索引节点号(inode number)和项目 ID(proj_id)。
proj_id:一个用户定义的整数,用于生成键值的低8位。通常情况下,你可以为不同的 IPC 资源设置不同的项目 ID,以确保它们的键值不冲突。
ftok 函数将 pathname 参数指定的文件的索引节点号和 proj_id 参数合并起来,然后通过一系列位操作生成一个唯一的键值。这个键值将作为 System V IPC 中资源的标识符,用于创建或获取相应的资源。
需要注意的是,ftok 函数的返回值是一个键值 key_t,这个键值会传递给 msgget、shmget 或 semget 等函数,用于创建或获取对应的消息队列、共享内存或信号量。
更多关于ftok函数的解析可见:ftok()函数深度解析
说白了ftok函数就是根据文件生成一个key_t类型的值,key_t一般是一个长整型,那完全可用用一个长整型的数进行替换即可,前提是该长整型数没有作为key_t使用
 

发送消息的程序msg1.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>#define MAX_MSG_SIZE 1024
#define MSG_TYPE 1// 定义消息结构体
struct msg_buffer {long msg_type;char msg_text[MAX_MSG_SIZE];
};int main() {int i;int msg_id;key_t key;struct msg_buffer message;// 生成一个唯一的键值if ((key = ftok("lethe1203", 'B')) == -1) {perror("ftok");exit(EXIT_FAILURE);}// 创建一个消息队列,如果不存在则创建,否则打开if ((msg_id = msgget(key, 0666 | IPC_CREAT)) == -1) {    // 这里完全可用把key替换为12345678等,去掉"生成一个唯一的键值"的步骤perror("msgget");exit(EXIT_FAILURE);}printf("Sending multiple messages to the queue...\n");// 发送多条消息到队列for (i = 1; i <= 5; ++i) {// 设置消息的类型为 MSG_TYPEmessage.msg_type = MSG_TYPE;// 构造消息内容sprintf(message.msg_text, "This is message %d from sender", i);// 发送消息if (msgsnd(msg_id, &message, sizeof(message.msg_text), 0) == -1) {perror("msgsnd");exit(EXIT_FAILURE);}printf("Message %d sent to queue.\n", i);// 为了演示,发送完一条消息后暂停五秒sleep(5);}printf("All messages sent to the queue.\n");return 0;
}

 

接收消息的程序msg2.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>#define MAX_MSG_SIZE 1024
#define MSG_TYPE 1// 定义消息结构体
struct msg_buffer {long msg_type;char msg_text[MAX_MSG_SIZE];
};int main() {int msg_id;key_t key;struct msg_buffer message;// 生成一个唯一的键值if ((key = ftok("lethe1203", 'B')) == -1) {perror("ftok");exit(EXIT_FAILURE);}// 获取现有的消息队列,如果不存在则创建if ((msg_id = msgget(key, 0666 | IPC_CREAT)) == -1) {    // 这里完全可用把key替换为12345678等,去掉"生成一个唯一的键值"的步骤perror("msgget");exit(EXIT_FAILURE);}printf("Receiving messages from the queue...\n");// 从队列中接收消息while (1) {// 接收消息if (msgrcv(msg_id, &message, sizeof(message.msg_text), MSG_TYPE, 0) == -1) {perror("msgrcv");exit(EXIT_FAILURE);}// 打印接收到的消息printf("Message received: %s\n", message.msg_text);}return 0;
}
 

代码执行结果:

0
 
 
 
 
 
 
 
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ulsteruni.cn/article/07208755.html

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

进程间通信(1)-管道

匿名管道(Anonymous Pipe)和有名管道(Named Pipe,也称为FIFO)是两种不同的进程间通信方式,它们有以下主要区别:命名和使用方式:匿名管道没有名字,只能在具有亲缘关系的进程之间使用,通常是在调用pipe()函数后直接使用,无需其他步骤。 有名管道有一个文件名,它在文件…

异常编译代码分析

异常编译代码分析 https://lowlevelbits.org/compiling-ruby-part-5/ 调用堆栈、堆栈帧和程序计数器 在程序执行期间,机器维护指向正在执行的指令的指针。它被称为程序计数器(或指令指针)。 当调用一个方法时,程序计数器被设置为被调用函数(被调用者)上的第一条指令。一旦…

Flask 框架启动无法改变端口

避坑! 相信大家使用flask框架的时候有时候会出现无法修改启动端口的情况. 在这里一共有两种解决办法(目前发现)1- 如果你使用的是flask Server 方式启动的你的项目的话, 可以Pycharm的环境变量中指定:FLASK_RUN_PORT=[PORT]2- 如果你使用的Python的话, 可以在代码中手动修改端口…

Java软件安装以及环境配置

Java软件安装以及环境配置 一、JDK安装 JDK官网:https://www.oracle.com/java/technologies/downloads/#java8 根据自己的电脑配置,安装对应平台,对应操作系统的JDK。 本人下载的是Windows x64版本的JDK。

defer 延迟调用【GO 基础】

本文通过示例代码讲解了 defer 的用法和值的注意的点。〇、前言 在 Go 语言中,defer 是一种用于延迟调用的关键字。 defer 在 Go 语言中的地位非常重要,它是确保资源正确释放和程序健壮性的关键字。 本文将通过示例对其进行专门的详解。 一、defer 简介 defer 的主要用途是在…

2024/4/3

1、今天中润稳步上涨,然后涨停,没有一字涨停或者高开低走,因为明天是清明假期,有连续四天的休市时间,因为怕夜长梦多的避险情绪,所以今天资金流出明显,尤其是小盘股和游资,导致今天很多股票炸板 所以假期之前一定要考虑好,除非前景大好,假期的消息预期可控且假期之前…