43.Linux 消息队列

news/2024/7/5 19:37:44

msgget(message get)

msgctl  (message contorl)

msgsnd  (message send)      

msgrcv (message receive)

(1)msgget(创建消息队列)

所需头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h> 

函数原型int msgget(key_t key,int flag); 
函数参数key:和消息队列关联的key值
flag:消息队列的访问权限
函数返回值成功:消息队列ID
失败:-1

创建一个消息队列:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <signal.h>
#include <unistd.h>
int main()
{
	int msgid;
	msgid=msgget(IPC_PRIVATE,0777);
	if(msgid<0)
	{
		printf("creat message queue failure\n");
		return -1; 
	}
	printf("creat message queue sucess msgid=%d\n",msgid);
	system("ipcs -q");
	return 0;
}

执行结果如下:

 key值为0,因为是通过IPC_PRIVATE的值来创建的。

(2)msgctl

所需头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

函数原型int msgctl(int msgqid,int cmd,struct msqid_ds *buf);
函数参数msgqid:消息队列的队列ID
cmdIPC_STAT:读取消息队列的属性,并将其保存在buf指向的缓冲区中
IPC_SET:设置消息队列的属性。这个值取自buf参数
IPC_RMID:从系统中删除消息队列
buf:消息队列缓冲区
函数返回值成功:0
失败:-1

 

msgctl函数的使用例程

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <signal.h>
#include <unistd.h>
int main()
{
	int msgid;
	msgid=msgget(IPC_PRIVATE,0777);
	if(msgid<0)
	{
		printf("creat message queue failure\n");
		return -1; 
	}
	printf("creat message queue sucess msgid=%d\n",msgid);
	system("ipcs -q");

	//delete message queue
	msgctl(msgid,IPC_RMID,NULL);	
	system("ipcs -q");
	return 0;
}

 执行结果如下:

(3)msgsnd函数

所需头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

函数原型int msgsnd(int msqid,const void *msgp,size_t size,int flag);
函数参数msqid:消息队列id

msgp:指向消息的指针。常用消息结构msgbuf如下:

struct msgbuf

{

        long mtype;    //消息类型

        char mtext[N]; //消息正文

};

size:发送消息正文的字节数

flag:IPC_NOWAIT 消息没有发送完成函数也会立即返回。(非阻塞)

        0:直到发送完成函数才返回(阻塞

函数返回值成功:0
失败:-1

(4)msgrcv

所需头文件

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/msg.h>

函数原型int msgrcv(int msgid,void *msgp,size_t size,long msgtype,int flag);
函数参数msgid:消息队列的ID
msgp:接收消息的缓冲区
size:要接收的消息的字节
msgtype0:接收消息队列中第一个消息
大于0:接收消息队列中第一个类型为msgtyp的消息
小于0:接收消息队列中类型值不大于msgtyp的绝对值且类型值又最小的消息
flag0:若无消息函数会一直阻塞
IPC_NOWAIT(非阻塞):若无消息 ,进程会立即返回ENOMSG。
函数返回值成功:接收到的消息的长度
出错:-1

消息队列读完节点数据会被删除

#include <stdlib.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
struct msgbuf
{
        long type;
        char text[124];
        char ID[4];
};
int main()
{
        int msgid;
        int readret;
        struct msgbuf sendbuf,recvbuf;
        msgid=msgget(IPC_PRIVATE,0777);
        if(msgid<0)
        {
                printf("creat message queue failure\n");
                return -1;
        }
        printf("creat message queue sucess msgid=%d\n",msgid);
        system("ipcs -q");
        //init sendbuf
        sendbuf.type=100;
        printf("please input message:\n");
        fgets(sendbuf.text,124,stdin);
        //start wirte message to message queue
        msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.text),0);

        //start read message from message queue
        memset(recvbuf.text,0,124);
        readret=msgrcv(msgid,(void *)&recvbuf,124,100,0);
        printf("recv:%s",recvbuf.text);
        printf("readret=%d\n",readret);
        //second read message queue
        msgrcv(msgid,(void *)&recvbuf,124,100,0);
        printf("second read after\n");
        //delete message queue
        msgctl(msgid,IPC_RMID,NULL);
        system("ipcs -q");
        return 0;
}

 

执行结果如下:

例程:实现消息队列的双向通信

服务器程序

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
struct msgbuf
{
	long type;
	char text[124];
	char ID[4];
};
int main()
{
	int msgid;
	int readret;
	int key;
        pid_t pid;	
	struct msgbuf sendbuf,recvbuf;
	key=ftok("./b.c",'a');
	if(key<0)
	{
		printf("creat key failure\n");
	}

	msgid=msgget(key,IPC_CREAT|0777);
	if(msgid<0)
	{
		printf("creat message queue failure\n");
		return -1; 
	}
	printf("creat message queue sucess msgid=%d\n",msgid);
	system("ipcs -q");
	pid=fork();
	if(pid>0)//father process write 100
	{	 	
		sendbuf.type=100;
		//WRITE MESSAGE QUEUE 
		while(1)
		{
			memset(sendbuf.text,0,124);
			printf("please input message:\n");
			fgets(sendbuf.text,124,stdin);
			msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.text),0);	
		}
	}
	if(pid==0)//son process
	{
		while(1)
		{
			memset(recvbuf.text,0,124);
			msgrcv(msgid,(void *)&recvbuf,124,200,0);
			printf("receive message form message queue:%s\n",recvbuf.text);
		}
	}

	msgctl(msgid,IPC_RMID,NULL);	
	system("ipcs -q");
	return 0;
}

客户端程序

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
struct msgbuf
{
	long type;
	char text[124];
	char ID[4];
};
int main()
{
	int msgid;
	int readret;
	int key;
        pid_t pid;	
	struct msgbuf sendbuf,recvbuf;
	key=ftok("./b.c",'a');
	if(key<0)
	{
		printf("creat key failure\n");
	}

	msgid=msgget(key,IPC_CREAT|0777);
	if(msgid<0)
	{
		printf("creat message queue failure\n");
		return -1; 
	}
	printf("creat message queue sucess msgid=%d\n",msgid);
	system("ipcs -q");
	pid=fork();
	if(pid==0)//son process write 100
	{	 	
		sendbuf.type=200;
		//WRITE MESSAGE QUEUE 
		while(1)
		{
			memset(sendbuf.text,0,124);
			printf("please input message:\n");
			fgets(sendbuf.text,124,stdin);
			msgsnd(msgid,(void *)&sendbuf,strlen(sendbuf.text),0);	
		}
	}
	if(pid>0)//father process read 100
	{
		while(1)
		{
			memset(recvbuf.text,0,124);
			msgrcv(msgid,(void *)&recvbuf,124,100,0);
			printf("receive message form message queue:%s\n",recvbuf.text);
		}
	}

	msgctl(msgid,IPC_RMID,NULL);	
	system("ipcs -q");
	return 0;
}

执行结果如下:

 


http://www.niftyadmin.cn/n/2432903.html

相关文章

Lombok快速上手(安装、使用与注解参数)

目录 Lombok插件安装与使用说明常见参数lombok的依赖于安装依赖管理IDEA插件的安装Data小例子扩展ToString构造器注解扩展Log及其他日志注解资料链接Lombok插件安装与使用说明 在实习中发现项目中IDE一直报检查错误&#xff0c;原来是使用了Lombok注解的黑科技&#xff0c;这里…

log4j配置每天生成一个日志文件

log4j配置每天生成一个日志文件 2017-02-14 11:52 1712人阅读 评论(0) 收藏 举报分类&#xff1a;java&#xff08;58&#xff09; 版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 本文仅记录tomcat下配置成功的记录&#xff0c;不作log4j配置的详…

24.C语言 结构体与链表

结构体变量分为数据域和指针域 结构体变量和数组变量一样都是由大到小开始分配存储单元 0FFFFNode110FFF00FFF0Node220FF000FF00Node33NULL 静态链表 动态链表 ①创建一个表头去表示整个链表 struct Node *creatListHead() { //1.赋值结构体变量//2.动态内存申请struct Node …

LaTeX 常见错误汇总及解决方案

2019独角兽企业重金招聘Python工程师标准>>> fwrite: Broken pipe xelatex.exe: 生成的pdf已打开 XeTeX is required to compile this document 需要XeLaTeX来编译此文档 &#xff01;LaTeX Error: Too many unprocessed floats. 老大&#xff1a;那是有图片出现了浮…

44.Linux 管道

管道的概念&#xff1a; 管道是一种最基本的IPC机制&#xff0c;作用于有血缘关系的进程之间&#xff0c;完成数据传递。调用pipe系统函数即可创建一个管道。有如下特质&#xff1a; 1.其本质是一个伪文件&#xff08;实为内核缓冲区&#xff09;。 2.由两个文件描述符&#…

从零单排学Redis【黄金】

前言 只有光头才能变强 好的&#xff0c;今天我们要上黄金段位了&#xff0c;如果还没经历过青铜和白银阶段的&#xff0c;可以先去蹭蹭经验再回来&#xff1a; 从零单排学Redis【青铜】从零单排学Redis【白银】看过相关Redis基础的同学可以知道Redis是单线程的&#xff0c;很多…

部署war包到Tomcat

部署war包到Tomcat 1. 开发给到一个war包&#xff0c;假设叫 a-b-c.war。 2. 打开Tomcat安装路径 &#xff0c;假设是“D:\Tomcat\apache-tomcat-7.0.68”&#xff0c;然后进入到 webapps文件夹。 3. 把 a-b-c.war丢到 webapps文件夹。 4. 启动Tomcat。 如果不需要更改配置文件…

MyEclipse2014搭建SSH框架

MyEclipse2014搭建SSH框架 2016-06-28 22:16 4868人阅读 评论(0) 收藏 举报版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 一. 创建一个Web Project 点击 “Next >”&#xff0c;默认设置&#xff0c;然后再点击“Next >”&#xff0c;勾选…