进程通信 二、XSI进程间通信之消息队列

由内核负责管理的一个管道,可以按顺序发送消息包(消息类型+消息内容),可以全双工工作。可以不按消息的顺序接收消息

用到的函数
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
Int  msgget(key_t  key, int  msgflg);
    功能:创建/获取消息队列
    key:IPC键值,由ftok函数自动生成
    msgflg:
        0        获取消息队列
        IPC_CREAT    创建消息队列
        IPC_EXCL        如果存在则创建失败
    返回值:消息队列标识
    
int  msgsnd(int  msqid, const void  *msgp, size_t  msgsz, int  msgflg);
    功能:向消息队列发送消息
    msqid:消息队列标识,msgget的返回值
    msgp:结构指针
        struct msgbuf 
        {
            long mtype;       消息类型     /* message type, must be > 0 */
            char mtext[1];    消息内容     /* message data */
                };
     msgsz:消息的长度,不包括消息类型,sizeof(msgbuf)-4    ( 要-4 否则会内存奔溃)
     msgflg:
        0     阻塞,当消息队列满时,等待
        1    不阻塞,当消息队列满时,不等待
        IPC_NOWAIT     不阻塞,当消息队列满时,不等待
    返回值:成功发送返回0,失败返回-1
    
ssize_t  msgrcv(int  msqid, void  *msgp, size_t  msgsz, long  msgtyp,int  msgflg);
    功能:从消息队列中按类型获取消息
    msqid:消息队列标识,msgget的返回值
    msgp:
        struct msgbuf 
        {
            long mtype;       消息类型             /* message type, must be > 0 */
            char mtext[1];    消息内容             /* message data */
                };
    msgsz:消息的长度,不包括消息类型,可以长一些。
    msgtyp:要接收的消息类型
    msgflg:
        0     阻塞,消息队列中是否有对应类型的消息,没有则等待
        1     不阻塞,消息队列中没有对应类型的消息则返回 
        MSG_NOERROR    消息类型正确,而消息的实际长度大于msgsz,则不接收消息并返回-1。
            如果msgflg带MSG_NOERROR标志,则把多余的消息截取,成功接收。
        IPC_NOWAIT    如果消息队列没有要接收的消息,则不等待,返回-1。
        MSG_EXCEPT    接收消息队列中第一个消息类型不是msgtyp的消息,编译时添加-D_GNU_SOURCE参数。
    返回值:成功接收到的字节数
    
int  msgctl(int  msqid, int  cmd, struct msqid_ds  *buf);
    功能:删除消息队列,设置或获取消息队列的属性
    msqid:消息队列标识,msgget的返回值
    cmd:
        IPC_STAT        获取消息队列的属性
        IPC_SET        设置消息队列的属性
        IPC_RMID        删除消息队列 buf = NULL
    返回值:成功返回0,失败返回-1
 
    struct msqid_ds 
    {
        struct ipc_perm     msg_perm;    // 权限
        time_t              msg_stime;    // 最后一个消息发送时间
        time_t              msg_rtime;  // 最后一次消息接收时间
        time_t              msg_ctime;  // 最后一次修改时间
        unsigned long     __msg_cbytes; // 消息队列中的字节数
        msgqnum_t           msg_qnum;   // 消息队列中消息的个数
        msglen_t            msg_qbytes; // 消息队列中容纳的最大字节数
        pid_t               msg_lspid;  // 最后一次发送消息进程
        pid_t               msg_lrpid;  // 最后一次接收消息进程
    }
    
    ***编程模型***
      进程A                                      进程B
    生成IPC键值     ftok                   生成IPC键值        ftok
    创建消息队列    msgget            获取消息队列        msgget
    发送消息           msgsnd            接收消息               msgrev
    删除消息队列    msgctl                          ...
 

#include "struct.h" 头文件定义结构体:

#ifndef STRUCT_H
#define STRUCT_H

typedef struct Msg
{
	long type;
	char data[256];

}Msg;

#endif//STRUCT_H

进程A实现接收 :

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "struct.h"

int main()
{
	//1.创建IPC键值
	key_t key = ftok(".",888);
	
	//2.创建消息队列
	int msgid = msgget(key,IPC_CREAT|0644);
	if(0 > msgid)
	{
		perror("msgget");
		return -1;
	}
	Msg msg = {666};//定义类型
	//3. 开始通信
	while(1)
	{
		printf(">");
		gets(msg.data);
		msgsnd(msgid,&msg,sizeof(Msg)-sizeof(msg.type),0);
		if(0 == strcmp(msg.data,"quit"))
		{
			printf("通信结束\n");
			break;
		}
	}
	//3.删除消息队列
	if(0 > msgctl(msgid,IPC_RMID,NULL))
	{
	 	perror("msgctl");
		return -1;
	}

	return 0;	
}

进程B实现发送消息: 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include "struct.h"

int main()
{
	//1.创建IPC键值
	key_t key = ftok(".",888);
	
	//2. 获取消息队列
	int msgid = msgget(key,0);
	if(0 > msgid)
	{
		perror("msgget");
		return -1;
	}
	Msg msg = {};
	//3. 接收消息
	while(1)
	{
		msgrcv(msgid,&msg,sizeof(Msg),666,0);
		printf("read: %s\n",msg.data);
		if(0 == strcmp(msg.data,"quit"))
		{
			printf("通讯结束\n");
			break;
		}
	}

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值