Linux下进程间的通信--消息队列

news2024/11/14 19:47:27

System V IPC的概念

System V IPC(System V Interprocess Communication)是Unix和类Unix操作系统中一套传统的进程间通信机制,它包括三种主要的通信方式:消息队列、信号量和共享内存。这些机制提供了一种在不同进程之间交换数据和同步操作的手段。

System V IPC 是由内核维护的若干个对象,在Linux系统下可以通过 ipcs 命令查询

ftok() 函数用于生成一个IPC(进程间通信)对象(如消息队列、信号量或共享内存)的唯一标识符(key)。这个key用于后续的IPC操作,如创建或访问这些IPC资源。

ftok()函数

函数描述:

函数头文件
#include <sys/types.h>
#include <sys/ipc.h>

函数原型
key_t ftok(const char *pathname, int proj_id);

函数参数
pathname:指向一个存在的文件的路径。ftok()会使用该文件的inode号来帮助生成 key。这个文件不必与IPC通信有任何直接关系,但它必须存在于文件系统中。
proj_id:是一个用户定义的值,用于进一步确保key的唯一性。这是一个非负整数,但通常是一个小于 256 的正整数。

函数返回值
成功 返回一个key_t类型的值。
错误 返回-1,并设置errno以指示错误原因。

示例代码: 

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>

int main() {
    key_t key;
    const char *path = "/etc/passwd";  // 一个存在的文件
    int proj_id = 123;  // 标识符

    key = ftok(path, proj_id);
    if (key == -1) {
        perror("ftok error");
        exit(1);
    }

    printf("The key value is %d\n", key);
    return 0;
}

消息队列

消息队列简介

在Linux系统中,消息队列是一种进程间通信(IPC)机制,允许不同进程向队列中添加消息,其他进程可以从队列中读取消息。消息队列可以跨多个进程共享,支持多种数据类型,并且可以设置消息优先级。

消息队列具有FIFO的特性,具有无名管道与有名管道各自的优势,可以支持任意两个进程的进程间通讯

消息队列的操作步骤:

创建消息队列

使用msgget()函数创建一个新的消息队列或访问一个现有的消息队列。

msgget()函数

函数描述:

函数头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

函数原型
int msgget(key_t key, int msgflg);

函数功能
获取System V消息队列标识符

函数参数
key:由ftok函数合成
msgflg:消息队列标志      I
       PC_CREAT 创建标志      
       IPC_EXCL  如果消息队列存在,则报错, errno设置为EEXIST      
       权限控制标志

函数返回值
成功:返回消息队列id
失败:返回-1,并设置errno

发送消息

使用msgsnd()函数将消息发送到消息队列。

函数描述:

msgsnd()函数
函数头文件
#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:消息队列ID    
msgp:消息结构体指针    
msgsz:消息内容的长度    
msgflg:消息队列标志,默认可以填0,IPC_NOWAIT,可以设置非阻塞

函数返回值
成功:返回0
失败:-1,并设置errno

接收消息

使用msgrcv()函数从消息队列中接收消息。

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:消息队列id    
msgp:消息结构指针    
msgsz:最大读取的字节数    
msgtyp:消息类型    
msgflg:消息队列标志,默认可以填0,IPC_NOWAIT,可以设置非阻塞

函数返回值
成功:返回实际读取消息内容的字节数
失败:-1,并设置 errno

删除消息队列

使用msgctl()函数删除消息队列

msgctl()函数

msgctl()对标识符为msqid的System V消息队列执行cmd指定的控制操作

函数头文件
#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:删除消息队列,用此命名时,第三个参数为NULL
buf:消息队列属性结构体对象指针

函数返回值
成功:IPC_STAT, IPC_SET, and IPC_RMID 返回0
失败:返回-1,并设置 errno
 消息队列属性结构体定义
struct ipc_perm {
               key_t          __key;       /* Key supplied to msgget(2) */
               uid_t          uid;         /* Effective UID of owner */
               gid_t          gid;         /* Effective GID of owner */
               uid_t          cuid;        /* Effective UID of creator */
               gid_t          cgid;        /* Effective GID of creator */
               unsigned short mode;        /* Permissions */
               unsigned short __seq;       /* Sequence number */
           };
struct msqid_ds {
               struct ipc_perm msg_perm;   /* Ownership and permissions */
               time_t          msg_stime;  /* Time of last msgsnd(2) */
               time_t          msg_rtime;  /* Time of last msgrcv(2) */
               time_t          msg_ctime;  /* Time of creation or last
                                              modification by msgctl() */
               unsigned long   msg_cbytes; /* # of bytes in queue */
               msgqnum_t       msg_qnum;   /* # number of messages in queue */
               msglen_t        msg_qbytes; /* Maximum # of bytes in queue */
               pid_t           msg_lspid;  /* PID of last msgsnd(2) */
               pid_t           msg_lrpid;  /* PID of last msgrcv(2) */
           };

总结:

消息队列整体代码示例:

#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <unistd.h>

// 定义消息结构体
struct my_msg {
    long mtype; // 消息类型,必须大于0
    char mtext[100]; // 消息数据
};

int main() {
    int msqid;
    struct my_msg msg;

    // 创建消息队列
    msqid = msgget(IPC_PRIVATE, 0666 | IPC_CREAT);
    if (msqid == -1) {
        perror("msgget");
        exit(1);
    }

    // 向消息队列发送消息
    msg.mtype = 1;
    strcpy(msg.mtext, "Hello, World!");
    if (msgsnd(msqid, &msg, sizeof(msg.mtext), 0) == -1) {
        perror("msgsnd");
        exit(1);
    }

    // 从消息队列接收消息
    if (msgrcv(msqid, &msg, sizeof(msg.mtext), 1, 0) == -1) {
        perror("msgrcv");
        exit(1);
    }

    printf("Received: %s\n", msg.mtext);

    // 删除消息队列
    if (msgctl(msqid, IPC_RMID, NULL) == -1) {
        perror("msgctl");
        exit(1);
    }

    return 0;
}

代码解读:

  • 定义了一个结构体my_msg,用于存储消息队列中的消息。
  • mtype是消息的类型,它必须是一个大于0的长整型数,用于区分不同的消息类型。
  • mtext是消息的数据部分,这里定义为一个100字符的数组
  • 定义了一个消息队列标识符msqid和一个消息结构体变量msg
  • 使用msgget函数创建一个消息队列,IPC_PRIVATE作为键值参数表示创建一个只对当前进程可见的私有消息队列。0666 | IPC_CREAT设置了消息队列的权限,并指示如果队列不存在则创建它。
  • 如果创建失败,使用perror打印错误信息并退出
  • 设置消息的类型为1,并设置消息文本为"Hello, World!"。
  • 使用msgsnd函数向消息队列发送消息。msgsnd的第四个参数0表示消息按类型排序。
  • 如果发送失败,使用perror打印错误信息并退出。
  • 使用msgrcv函数从消息队列接收类型为1的消息。sizeof(msg.mtext)指定了消息数据的最大长度。
  • 如果接收失败,使用perror打印错误信息并退出
  • 打印接收到的消息。
  • 使用msgctl函数删除消息队列,IPC_RMID是控制命令,指示删除消息队列。
  • 如果删除失败,使用perror打印错误信息并退出。

结语:

无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

llamaindex+Internlm2 RAG实践 #书生谱语大模型实战营#

1.打卡任务&#xff1a; 本次的打卡任务是llamaindexInternlm2 RAG实践&#xff0c;我们需要基于 LlamaIndex 构建自己的 RAG 知识库&#xff0c;寻找一个问题 A 在使用 LlamaIndex 之前InternLM2-Chat-1.8B模型不会回答&#xff0c;借助 LlamaIndex 后 InternLM2-Chat-1.8B 模…

Axure设计之下拉单选框教程(中继器)

在Axure RP中&#xff0c;使用中继器&#xff08;Repeater&#xff09;可以实现许多复杂而动态的用户界面组件&#xff0c;比如下拉单选框。本文将详细介绍如何通过中继器创建一个美观且功能丰富的下拉单选框。 一、案例预览 预览地址&#xff1a;https://1zvcwx.axshare.com …

如何使用ssm实现基于JAVA的网上药品售卖系统

TOC ssm133基于JAVA的网上药品售卖系统jsp 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;规…

什么是堡垒机

堡垒机&#xff0c;即在一个特定的网络环境下&#xff0c;为了保障网络和数据不受来自外部和内部用户的入侵和破坏&#xff0c;而运用各种技术手段监控和记录运维人员对网络内的服务器、网络设备、安全设备、数据库等设备的操作行为&#xff0c;以便集中报警、及时处理及审计定…

鹏城杯 2022 取证writeup

简单取证 我们进去首先使用imageinfo pslist screenshot clipboard filescan 等等插件查看相关信息。 这里找到一个password姑且先留着 然后使用filescan找到了一个jpg文件 我们先dump下来 vol -f file.raw --profileWinXPSP2x86 dumpfiles -Q 0x000000000207e3d8 -D . 然…

Generating Query Recommendations via LLMs 【阅读笔记】

背景 主要去进行query的相关搜索补充&#xff1b; 例如 我们引入生成查询推荐&#xff08;GQR&#xff09;系统。 GQR以大语言模型为基础&#xff0c;利用大语言模型的提示能力&#xff0c;通过提示中提供的几个例子&#xff08;检索或手工&#xff09;来理解推荐任务。 方案…

主机监控与审计系统是什么?这个功能让您的效率翻倍!

天下之事&#xff0c;皆需明察秋毫&#xff0c;方能运筹帷幄&#xff0c;决胜千里。 于信息之海&#xff0c;主机者&#xff0c;犹若疆土之基石&#xff0c;承载着数据之重&#xff0c;运行着系统之脉。 然&#xff0c;世事如棋局局新&#xff0c;网络之域&#xff0c;暗流涌…

惠海H6432 dcdc升压恒压支持IC 3.7V 7.4V升压9V12V15V24V3A大电流 摄影灯光电源

1. 产品描述 H6432是一款电流模式B00ST异步升压恒压控制驱动芯片&#xff0c;适用于2.7-24V输入电压范 围的升压恒压电源应用领域&#xff0c;启动电压低至2. 5V。芯片根据负载的大小自动切换PWM&#xff0c;PFM和BURST模式以提高各个负载端的电源系统效率。芯片通过EN脚实现…

kali2022重置密码

在如下系统选择界面&#xff0c;按‘E’&#xff0c; 进入到编辑界面&#xff0c;将“ro quiet”修改为“rw init/bin/bash”。修改完成后ctrl X保存编辑并继续引导ctrlx进行引导&#xff0c;passwd修改密码&#xff0c;成功后重启&#xff0c;用root和新密码登录。

Adversarial Diffusion Distillation

sd turbohttps://static1.squarespace.com/static/6213c340453c3f502425776e/t/65663480a92fba51d0e1023f/1701197769659/adversarial_diffusion_distillation.pdf#page5.83https://github.com/Stability-AI/generative-models 问题引入 1-4 steps fast diffusion model samp…

软件测试最全面试题,了解一下

一、前言 近期有不少同学&#xff0c;朋友问我什么是软件测试&#xff0c;它是干什么的&#xff0c;我适不适合做、这行发展前景、工资怎么样等等等…在这里我把问题总结一下&#xff0c;整理一篇文章出来。 我也看过很多贴吧、论坛&#xff0c;在入行之前对这块都是迷茫的&a…

os 虚拟内存

虚拟内存不仅能隔离进程&#xff0c;还能提高内存利用率&#xff0c;请解释虚拟内存如何提高内存利用率&#xff1f;&#xff1f;&#xff1f; 虚拟内存&#xff08;Virtual Memory&#xff09;通过以下几个机制来提高内存利用率&#xff1a; 1. 内存分页&#xff08;Paging&…

20240824给飞凌OK3588-C的核心板刷Ubuntu22.04并安装iperf3测试网速

20240824给飞凌OK3588-C的核心板刷Ubuntu22.04并安装iperf3测试网速 2024/8/24 9:24 缘起&#xff0c;通过千兆交换机接入外网&#xff0c;开机之后发现以太网异常&#xff0c;多上电几次就会发现以太网也能用。 缘由&#xff1a;由于自制的飞凌的OK3588-C的核心板的底板对空间…

五子棋理解C++思想

双人五子棋项目目录&#xff1a; class Game { public:Game();void init();bool waitPlayerPutChess(Player* player, int& oldi, int& oldj);void draw();void play();bool isOver(int playerId);public:int whoWin -1; // 谁赢了&#xff08;0&#xff1a;白棋&a…

【题解】【模拟】—— [CSP-J 2023] 一元二次方程

【题解】【模拟】—— [CSP-J 2023] 一元二次方程 [CSP-J 2023] 一元二次方程题目背景题目描述输入格式输出格式输入输出样例输入 #1输出 #1 提示 1.题意解析2.AC代码 [CSP-J 2023] 一元二次方程 戳我查看题目&#xff08;洛谷&#xff09; 题目背景 众所周知&#xff0c;对…

共享文件操作记录如何查看?这种方法帮你轻松实现

查看共享文件操作记录&#xff0c;可以通过以下几种方法实现&#xff1a; 一、利用操作系统的文件访问记录功能 在Windows操作系统中&#xff0c;可以利用“事件查看器”来查看共享文件的访问记录。事件查看器是Windows内置的一个工具&#xff0c;用于记录系统中发生的各种事…

50个必知的ChatGPT学术论文指令:提升研究效率,强烈推荐收藏!

随着AI技术的发展&#xff0c;AI已经成为学术创作的强大工具。如果你还不了解如何利用AI润色你的论文&#xff0c;那么这篇文章将为你提供极大的帮助。我们精心整理了50个顶级ChatGPT学术论文指令&#xff0c;强烈建议你加以利用&#xff01; 这些指令非常实用&#xff0c;能显…

线性表的顺序表示—插入操作

线性表的顺序表示—插入操作 插入代码 #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define InitSize 15 // 初始化扩容长度 #define MaxSize 100typedef struct {int data[MaxSize]; // 申请空间&#xff08;静态&#xff09;int lengt…

探索ISP自动曝光技术:工作原理与应用(一)

在现代数码相机和智能手机中&#xff0c;图像信号处理器&#xff08;ISP&#xff09;是负责将传感器捕捉到的原始数据转换成高质量图像的重要组件。而在ISP的众多功能中&#xff0c;自动曝光&#xff08;Auto Exposure, AE&#xff09;是确保拍摄出清晰、明亮且细节丰富照片的关…

QT Quick QML 实例之定制 TableView

QT Quick QML 实例之定制 TableView 一、演示二、C关键步骤1. beginInsertRows()&#xff08;用户插入行&#xff09;2. roleNames() &#xff08;表格中列映射&#xff09;3. data() &#xff08;用户获取数据&#xff09;4. headerData() &#xff08;表头&#xff09;5. fla…