首页 > 其他分享 >消息队列

消息队列

时间:2024-05-28 21:22:06浏览次数:17  
标签:队列 进程 消息 key msg include

消息队列

​ Linux系统中消息队列(Message Queue)是进程间通信的一种方式,这种通信机制的好处是可以传输指定类型(用户可以自行定义)的数据,相同类型的数据根据到达顺序在队列中进行排队。

​ 不同类型的数据不能处于同一个队列中,也就是说系统中可能存在多个消息队列,每个消息队列中的数据类型都是不同的,所以用户打算读取消息队列中的数据时也需要指定数据类型,才可以从存储该类型数据的消息队列中读取有效数据。

​ Linux系统中有很多消息队列,Linux系统是如何管理消息队列的呢,因为每个创建消息队列都具有唯一的键值key,进程可以通过指定消息队列的键值对指定的消息队列发送数据,,且提供了一个shell命令:ipcs -a来查看系统所有的ipc对象的消息。

​ 今日练习:要求进程A创建一条消息队列之后向进程B发送SIGUSR1信号,进程B收到该信号之后打开消息队列并把进程的PID作为消息写入到消息队列中,要求进程B在写入消息之后,发SIGUSR2信号给进程A,进程A收到该信号则从消息队列中读取消息并输出消息正文的内容。

目录

进程A

​ 设计一个函数,通过msgget函数接口来获取消息队列的ID,并向消息队列中接收字符串

/*****************************************************************
*
*      file name :main.c
*      authour   :[email protected]
*      date      :2024.05.27 
*      function  :设计一个函数,通过msgget函数接口来获取消息队列的ID,并向消息队列中接收字符串。
*      note      :为防止重复创建,需要先判断共享内存和信号量集是否存在。
*      CopyRight (c)   2024   [email protected]   All Right Reseverd
*
******************************************************************/

#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/msg.h>
#include <features.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>

struct mymsg{

    long mtype;
    int mtext;
};

struct mymsg msg;
int msg_id;
//接收到信号后的自定义处理函数的参数只能为信号,所以想在此函数中调用其他参数需要定义为全局变量
void sig_handler(int signo)
{  
    if(signo == SIGUSR2)
    {
        //用于接收消息队列里面的内容,4:消息队列正文字节数,0:是接收消息选项,如果设置为0则是默认模式,当无指定类型消息时阻塞
        msgrcv(msg_id,&msg,4,1,0);       
        printf("msg.mtext is %d\n",msg.mtext);
    }   
}

int main()
{
    //获取“.”文件的key值
    key_t key = ftok(".",3);
    if(-1 == key)
    {
        fprintf(stderr,"msgget failed,errno is %d,%s\n",errno,strerror(errno));
        return -1;
    }
    //获取消息队列的ID,如果没有创建消息队列则创建
    msg_id = msgget(key,IPC_CREAT|0644);
    if(-1 == msg_id)
    {
        fprintf(stderr,"msgget failed,errno is %d,%s\n",errno,strerror(errno));
        return -1;
    }
    //消息队列函数接口提供的结构体,mtype是消息类型,mtext是消息内容
    struct mymsg msg;
    msg.mtype = 1;
    
    //kill是系统提供可以向另一个进程发送信号,getpid()是获取进程号,+1是为了获取另一个通信进程的ID,因为那个进程在进程A后立马创建则+1
    kill(getpid()+1,SIGUSR1);  
    while(1) 
    //对于收到的信号进行自定义处理,设计一个子函数,用于接受到信号后此进程的行为
    signal(SIGUSR2,sig_handler);
    return 0;
}

​ ftok()函数可以把一个指定路径的文件和一个指定的项目id转换为一个system-V IPC对象使用的键值key。

​ 此key用于msgget来获取消息队列的ID。

进程B

设计一个函数,通过msgget函数接口来获取消息队列的ID,并向消息队列中发送字符串。

/*****************************************************************
*
*      file name :main.c
*      authour   :[email protected]
*      date      :2024.05.27 
*      function  :设计一个函数,通过msgget函数接口来获取消息队列的ID,并向消息队列中发送字符串。
*      note      :为防止重复创建,需要先判断共享内存和信号量集是否存在。
*      CopyRight (c)   2024   [email protected]   All Right Reseverd
*
******************************************************************/

#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/msg.h>
#include <features.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>

struct mymsg{

    long mtype;
    int mtext;
};
struct mymsg msg;
int msg_id;
//接收到信号后的自定义处理函数的参数只能为信号,所以想在此函数中调用其他参数需要定义为全局变量
void sig_handler(int signo)
{  
  
    printf("成功\n");
    //mtype指的是消息类型,必须是一个大于0的正整数 
    msg.mtype = 1;
    msg.mtext = getpid();  
    printf("msg.mtext is %d\n",msg.mtext);
}

int main()
{
    //获取“.”文件的key值
    key_t key = ftok(".",3);
    if(-1 == key)
    {
        fprintf(stderr,"msgget failed,errno is %d,%s\n",errno,strerror(errno));
        return -1;
    }
    //获取消息队列的ID,如果没有创建消息队列则创建
    msg_id = msgget(key,IPC_CREAT|0644);
    if(-1 == msg_id)
    {
        fprintf(stderr,"msgget failed,errno is %d,%s\n",errno,strerror(errno));
        return -1;
    }

    while(1)
    {
        //对于收到的信号进行自定义处理,设计一个子函数,用于接受到信号后此进程的行为
        signal(SIGUSR1,sig_handler);
        //用于发送消息队列里面的内容,4:消息队列正文字节数,0:msgsnd函数的第四个参数msgflg指的是消息队列的标志,如果该标志设置为IPC_NOWAIT,则表示不阻塞,此时如果待写入的消息的长度大于消息队列剩余空间,则直接返回并报错。
        msgsnd(msg_id,&msg,4,0);
         //kill是系统提供可以向另一个进程发送信号,getpid()是获取进程号,+1是为了获取另一个通信进程的ID,因为那个进程在进程A后立马创建则+1
        kill(getpid()-1,SIGUSR2);
    }
        
    return 0;

}

标签:队列,进程,消息,key,msg,include
From: https://www.cnblogs.com/xiaobaibudongjiuwen/p/18218942

相关文章

  • python 队列生产者消费者爬虫
    当使用Python编写一个基于队列的生产者消费者爬虫时,我们通常会使用threading或multiprocessing模块来处理并发,并使用queue模块来管理数据队列。下面是一个详细的示例,该示例展示了如何使用生产者线程生成URL,消费者线程爬取这些URL的内容。请注意,这里为了简化示例,我们将不会实际进......
  • 进程间通信(队列和生产消费模型)
    【一】引入【1】什么是进程间通信进程间通信(Inter-ProcessCommunication,IPC)是指两个或多个进程之间进行信息交换的过程【2】如何实现进程间通信借助于消息队列,进程可以将消息放入队列中,然后由另一个进程从队列中取出这种通信方式是非阻塞的,即发送进程不需要等待接收进......
  • 消息队列
    进程A:#include<stdio.h>#include<stdlib.h>#include<signal.h>#include<unistd.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/msg.h>#include<errno.h>#include<string.h>intmsgid;......
  • 数据结构:队列
    目录队列的概念和结构队列的实现结构定义初始化判空入队列出队列返回队头元素返回队尾元素返回size销毁 队列的概念和结构队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(FirstInFirstOut)入队列:进行插入操......
  • kafka 保证消息有序性
    具体需要从生产者和消费者两个方面来讲:生产者:1.分区机制:Kafka的核心机制之一是分区(Partition)。每个主题(Topic)可以被分割成多个分区,而消息在发布时会被追加到特定的分区中。在每个分区内部,消息是按照它们被追加的顺序来存储的,因此保证了分区内的消息顺序性。 2.分区器:生......
  • FolkMQ v1.5.1 发布(“新式” 国产消息中间件)
    FolkMQ是个“新式”的消息中间件。强调:“小而巧”、“简而强”。功能简表角色功能生产者(客户端)发布普通消息、Qos0消息、定时消息、顺序消息、可过期消息、事务消息、广播消息消费者(客户端)订阅、取消订阅。消费-ACK(自动、手动)服务端发布-Confirm、订......
  • 消息队列练习题
    消息队列练习题进程A/**********************************************************************filename:mesqa.c*author:[email protected]*date:2024/5/28*function:接收进程b的信号,读出消......
  • 如果任务过多,队列积压怎么处理?
    如果任务过多,队列积压怎么处理?1、内存队列满了应该怎么办2、问题要治本——发短信导致吞吐量降低的问题不能忽略!!3、多路复用IO模型的核心组件简介1、内存队列满了应该怎么办如图:大家可以看到,虽然现在发短信和广告投递,彼此之间的执行效率不受彼此影响,但是请......
  • netty建立数万客户端连接,并主动发消息
    @Slf4jpublicclassNettyClientTest{publicstaticvoidmain(String[]args)throwsException{EventLoopGroupworkerEventLoopGroup=newNioEventLoopGroup();try{Bootstrapbootstrap=newBootstrap();boo......
  • 消息队列练习题
    题目:要求进程A创建一条消息队列之后向进程B发送SIGUSR1信号,进程B收到该信号之后打开消息队列并把进程的PID作为消息写入到消息队列中,要求进程B在写入消息之后,发SIGUSR2信号给进程A,进程A收到该信号则从消息队列中读取消息并输出消息正文的内容。进程A的代码://构造用于接收消息......