Linux 进程间通讯-消息队列mqueue

在linux下的多个进程间的通信机制叫做IPC(Inter-Process Communication)
进程间通信可以有多种方式

  • 管道 (PIPE)
  • 命名管道 (FIFO)
  • 消息队列 (Message queues)
  • 信号 (signal)
  • 信号量 (Semaphore)
  • 共享内存 (Share Memory)
  • 内存映射文件 (Memory Map)
  • 套接字(socket)

每种方式各有利弊,比如管道(PIPE)只能在父子进程中使用,并且仅限半双工模式。
本节主要介绍比较灵活的 消息队列mqueue

主要函数:

mqd_t mq_open (const char *__name, int __oflag, ...);

name:"/mq_test" ,创建消息队列的名字
oflag:文件属性,和open函数的类似。有必须的选项:O_RDONLY,O_WRONLY,O_RDWR,还有可选的选项:O_NONBLOCK,O_CREAT,O_EXCL。
…:附加参数,主要用户创建时候,描述队列的大小以及允许的个数。也可以为空,系统则采用默参数

int mq_close (mqd_t __mqdes);
int mq_unlink (const char *__name);

mq_close :关闭消息队列文件描述,但不能删除
mq_unlink :删除消息队列文件

ssize_t mq_receive (mqd_t __mqdes, char *__msg_ptr, size_t __msg_len,
			   unsigned int *__msg_prio);
int mq_send (mqd_t __mqdes, const char *__msg_ptr, size_t __msg_len,
		    unsigned int __msg_prio);

__msg_prio:消息优先级,数据越大,优先级越大!
mq_receive :如果open设置了O_NONBLOCK参数,则读取失败后,会立即返回-1,不会阻塞。

消息队列是以文件的形式存在
当新建了一个消息队列后,mq_open("/mq_test", O_CREAT|O_RDWR, FILE_MODE);
可以在系统中查看,该消息队列对应的文件

eric@eric-PC:/dev/mqueue$ ls -l
总用量 0
-rw-r--r-- 1 eric eric 80 57 14:47 mq_test

发送程序
send.c

#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <mqueue.h>

#define FILE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)

// send 线程
void thread_send(void *arg)
{
	int i,ret;
	char buf[128];
	printf("%s,PID=%d\n",__func__,getpid());
	
	struct mq_attr attr, new_attr, old_attr;
	attr.mq_maxmsg = 10;		//最大消息10个
	attr.mq_msgsize = 128;	//每个消息限制大小128字节
	attr.mq_flags = 0;
	mqd_t mqd = mq_open("/mq_test", O_CREAT|O_RDWR, FILE_MODE, &attr);
	if(-1 == mqd)
	{
		perror("mq_open error");
		return 0;
	}
	
	//测试:发送8次数据
	for ( i=0; i<8; i++)
	{
		printf("Thread working...! %d \n",i);
		
		sprintf(buf,"send-%d",i);
		ret = mq_send(mqd, buf, strlen(buf), 2);
		if(ret == -1)
		{
			perror("mq_send error");
		}
		sleep(2);
	}
	mq_close(mqd);
	
	printf("[%s]end\n",__func__);
	
	exit(0);
}


int main(void)
{
	pthread_t mythread1,mythread2;
	
	if ( pthread_create( &mythread1, NULL, thread_send, &mqd) )
	{
		printf("error creating thread.");
		abort();
	}
	
	if ( pthread_join ( mythread1, NULL ) )
	{
		printf("error join thread.");
		abort();
	}
	
	printf("thread done! \n");
	exit(0);
}

接收程序
receive.c

#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <mqueue.h>

#define FILE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)

// receive线程
void thread_receive(void *arg)
{
	 int i,ret;
	 char buf[128];
	 int prio=0;
	 printf("%s,PID=%d\n",__func__,getpid());
  
	struct mq_attr attr, new_attr, old_attr;
	attr.mq_maxmsg = 10;
	attr.mq_msgsize = 128;
	attr.mq_flags = 0;
	mqd_t mqd = mq_open("/mq_test", O_CREAT|O_RDWR|O_NONBLOCK, FILE_MODE, &attr);
	if(-1 == mqd)
	{
		perror("mq_open error");
		return 0;
	}
  
	do
	{
		memset(buf,0,sizeof(buf));
		ret = mq_receive(mqd, buf, sizeof(buf), &prio);
		if (ret !=-1)
		{
			printf("ret=%d\n",ret);
			printf("read:%s\n",buf);
		}
	} while (ret);
	mq_close(mqd);
	
	printf("[%s]end\n",__func__);
}


int main(void)
{
	pthread_t mythread1,mythread2;
	
	if ( pthread_create( &mythread2, NULL, thread_receive, &mqd) )
	{
		printf("error creating thread.");
		abort();
	}
	
	if ( pthread_join ( mythread2, NULL ) )
	{
		printf("error join thread.");
		abort();
	}
	
	printf("thread done! \n");
	exit(0);
}

测试现象
发送:

eric@eric-PC:~/Documents/work/linux-c/mq/mq_send$ ./main 
thread_send,PID=14976
Thread working...! 0 
Thread working...! 1 
Thread working...! 2 
Thread working...! 3 
Thread working...! 4 
Thread working...! 5 
Thread working...! 6 
Thread working...! 7 
[thread_send]end

接收:

eric@eric-PC:~/Documents/work/linux-c/mq/mq_receive$ ./main 
thread_receive,PID=14972
ret=6
read:send-0
ret=6
read:send-1
ret=6
read:send-2
ret=6
read:send-3
ret=6
read:send-4
ret=6
read:send-5
ret=6
read:send-6
ret=6
read:send-7
^C

----------------------------------------------------仅此记录------------------------------------------------

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值