Linux 进程间通信:消息队列 queue

1,Linux 中的消息队列

        消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法,在Linux 系统中消息队列本质上是内核空间的链表【链表型队列】,每一个节点代表一个消息,每一个消息都有自己的类型【long type】。

消息队列与命名管道一样的不足,Linux用宏:
   MSGMAX  来限制一条消息的最大长度;
   MSGMNB  一个消息队列的最大长度(总的字节数是有上限的);
   MSGMNI  系统上消息队列的总数也有一个上限

2,LINUX 消息队列 API

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

//创建和访问一个消息队列
int msgget( key_t key, int msgFlg );
    key: 某个消息队列的名字;
    msgFlg:
        IPC_CREAT :创建消息队列
        IPC_EXCl :存在该消息队列,就报错
        mode :访问权限(0644) (只需要设置读写权限,执行权限无效)
注:如果key = IPC_PRIVATE ,则自动产生一个随机未用的新键值

rertun:
    ERROR   -1
    SUCCESS  消息队列的ID 

//发送一个消息
int msgsnd( int msgID, const void *msgp, size_t msgsz, int msgflg )
    msgsnd :消息队列的ID
    msgp: 要发送的数据的地址
    msgsz : 要发送的数据大小(不包括标识msg类型的长度)
    msgflg :
         IPC_NOWAIT  非阻塞读出、写入消息
         MSG_EXCEPT  读取标识不是msgtype的第一个消息 (msgrcv)
         MSG_NOERROR 消息尺寸比msgsz大时,截断消息而不报错
return
    ERROR  < 0
    success 0

//接收一个消息
int msgrcv( int msgID, void *msgp, size_t msgsz, long msgtype, int msgflg)
    
    同上:
    msgtype  :接收的消息标识符
    msgsz :为一个消息的完整大小包括标识

注:
    参数 msgtyp:指定获取哪种类型的消息

    msgtyp = 0:获取消息队列中的第一条消息

    msgtyp > 0:获取类型为 msgtyp 的第一条消息,
        除非指定了 msgflg 为MSG_EXCEPT,这表示获取除了 msgtyp 类型以外的第一条消息。

    msgtyp < 0:获取类型 ≤|msgtyp|≤|msgtyp| 的第一条消息。(-5 < msgtype < 5)
            发送时的消息标识一般不能为 0

//删除 ipc
int msgctl( int msgID, int cmd, struct msgid_ds *buf)
    
cmd:
    IPC_RMID  删除消息队列,忽略buf  ==>success 0 ,ERROR < 0
    
    IPC_STAT  获取该MSG的信息,存储到buf
    IPC_SET  设置该MSG的信息
    IPC_INFO 获取当前系统中MSG的限制信息
    MSG_INFO 获取当前系统中MSG的资源消耗情况
    MSG_STAT 。。。
        

3,消息队列的实例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <error.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>


#define MSG_key "/tmp/1.txt"
key_t msgKey = 0;

struct staff{
	char Name[20];
	int age;
};

struct msgbuf{
	long mtype;
	struct staff data;
};

void *recv_msgQueue(void *arg)
{
	struct msgbuf buf;
	int ret = 0;
	key_t key = 0; 
	int msg_fd = 0;
	int i = 0;
	/*
	if(0 > (key = ftok( MSG_key, 0)))
	{
	printf("pthread ftok error\n");
	//return -1;
	}
	*/
	if(0 > (msg_fd = msgget( msgKey, IPC_CREAT | 0666 )))
	{
		printf("pthread create msgget is error\n");
		//return -1;
	}
	bzero( &buf, sizeof(buf));
	while(1)
	{
		i++;
		printf("msgrcv is waitting....[%d]\n", msg_fd);
		ret = msgrcv( msg_fd, (void *)&buf, sizeof(buf), 1,0);

		if(ret == -1)
		{
			printf("msg recv error\n");
		}
		printf("pthread is get msg,id [%d], Name [%s] , Age [%d]\n", buf.mtype, buf.data.Name,  buf.data.age);
		bzero( &buf, sizeof(buf));
		if(i > 7)
		{
			msgctl(msg_fd,IPC_RMID,NULL);
			exit(0);
		}
		sleep(2);
	}
}

int main()
{
	pthread_t tid = -1;
	int ret = -1 , msg_fd = -1 ,i=0;
	struct msgbuf Mymsg[5]={{ 1, "Jack", 27},{ 1, "Alice", 30},{ 1, "Lura", 35},\
			{2, "Kang", 40},{2, "Wang", 45}};

	//get key
	msgKey = ftok( MSG_key, 0);
	//create msgQueue
	msg_fd = msgget(msgKey , IPC_CREAT | 0666);
	if(msg_fd < 0)
	{
		printf("msgget create is error\n");
		return -1;
	}
	//printf("Mymsg[0]:[%d][%s]\n", Mymsg[0].mtype, Mymsg[0].Name);
	ret = pthread_create( &tid, NULL, recv_msgQueue , NULL );
	if(ret < 0)
	{
		printf("pthread_create is error\n");
		return -1;
	}
	ret = 0;
	while(1) //不断发送消息
	{
		ret = msgsnd( msg_fd, (void *)&Mymsg[i], sizeof(Mymsg[i].data), 0);
		if(i == 4)
		{
			ret = 0;
			i=0;
			continue;
		}
		if(ret < 0) printf("msg send error\n");
		i++;
		printf("msgsnd to msg [%d][%d]\n", i, msg_fd);
		sleep(3);
	}
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值