消息队列
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