linuxC多进程通讯---POSIX消息队列

posix与system v对比

•POSIX IPC
•POSIX接口更简单:使用类似于文件I/O的open、close、unlink等接口
•POSIX使用名字代替键来标识IPC对象
•对 IPC 对象引用计数,简化了对 IPC 对象的删除
–跟文件类似,删除操作也仅仅是删除了IPC对象的名字
–只有当IPC对象的引用计数变成0之后才真正销毁IPC对象
•System V IPC
•System V IPC 可移植性更好:几乎所有的UNIX系统都支持system V,POSIX在UNIX系统中只是一个可选组件,有些UNIX系统并不支持
•Linux系统一般都会支持system V
•Linux 2.6开始陆续支持POSIX…

POSIX 编程注意事项

•使用POSIX 消息队列和共享内存时,需要实时库librt链接,编译时需指定 $ -lrt
•使用POSIX 信号量时,需要和线程库libpthread链接起来,编译时需指定$ -lpthread

相关API

•mq_open: 创建或打开一个消息队列
•mq_send: 向消息队列写入一条消息
•mq_receive:从消息队列中读取一条消息
•mq_close: 关闭进程打开的消息队列
•mq_unlink: 删除一个消息队列
•mq_setattr:设置消息队列一些额外的属性
•mq_getattr:获取消息队列一些额外的属性
•mq_nofity: 异步通知

创建或打开 IPC 对象

•函数原型:

–mqd_t mq_open (const char *name, int oflag);
–mqd_t mq_open (const char *name, int oflag, mode_t mode,
struct mq_attr *attr);

•函数功能:

使用指定名字创建或打开一个对象,返回该对象的句柄

•函数参数:

–name:用来标识要创建或打开的对象
–Oflag:O_CREAT/O_EXCL /O_RDONLY /O_WRONLY /O_RDWR /O_NONBLOCK
–Mode:位掩码,权限设置
–Attr:设置消息队列的属性,若为NULL,使用默认属性。Linux3.5以后版本也可通过/proc查看设置

•函数返回值

–成功:返回消息队列的IPC对象描述符
–失败:返回-1,并设置errno

关闭POSIX 消息队列

•函数原型:

int mq_close(mqd_t mqdes);

•函数功能:

通过描述符关闭消息队列

•TIPS:

–POSIX 消息队列在进程终止或执行exec()时会自动被关闭

•删除一个POSIX 消息队列

•函数原型:

int mq_unlink (const char *name);

•函数功能:

–删除通过 name 标识的消息队列
–在所有进程使用完该队列之后销毁该队列。
–若打开该队列的所有进程已经关闭该队列,立即删除

•向 POSIX 消息队列写入消息

•函数原型:

int mq_send(mqd_t mqdes, const char *msg_ptr,
size_t msg_len, unsigned int msg_prio);

•函数功能:

将msg_ptr指向的缓冲区中的消息添加到描述符mqdes所引 用的消息队列中

•函数参数:

–mqdes: 消息队列描述符
–msg_ptr:指向存放消息的缓冲区指针
–msg_len:消息的长度[10,8192]
–msg_prio:消息对队列中按优先级排列,设置为0表示无需优先级

•从 POSIX 消息队列读取消息

•ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);

•函数功能:

–从mqdes引用的消息队列中删除一条优先级最高、存放时间最长的消息
–将删除的消息保存在msg_ptr指针指向的缓冲区

•函数参数:

–mqdes: 消息队列描述符
–msg_ptr:指向存放消息的缓冲区指针
–msg_len:msg_ptr所指向的缓冲区长度,要大于消息队列的mq_msgsize
–msg_prio:如不为空,接收到的消息的优先级会被复制到指针指向处

•函数返回值

–成功:返回接收的消息的字节数
–失败:-1,并设置errno

父子进程通过POSIX消息队列通讯

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <mqueue.h>

#define handle_error(msg) \
   do{perror(msg);exit(EXIT_FAILURE);}while(0)

int main (void)
{
	mqd_t mq_id;
	if ((mq_id = mq_open("/posix_msg_queue", O_RDWR | O_CREAT, 0644, NULL)) == -1)
        handle_error("mq_open");

    struct mq_attr mq_attribute;
	if (mq_getattr (mq_id, &mq_attribute) == -1)
        handle_error("mq_getattr");
	printf ("mq_flags: %ld\n", mq_attribute.mq_flags);
	printf ("mq_maxmsg: %ld\n", mq_attribute.mq_maxmsg);
	printf ("mq_msgsize: %ld\n", mq_attribute.mq_msgsize);
	printf ("mq_curmsgs: %ld\n", mq_attribute.mq_curmsgs);

	int ret_from_fork;
	ret_from_fork = fork ();
	if (ret_from_fork == 0) // child process
	{
		char msg_buf[mq_attribute.mq_msgsize];
		memset (msg_buf, 0, mq_attribute.mq_msgsize);
        int count = 0;
		while (1)
		{
			if (mq_receive (mq_id, msg_buf, mq_attribute.mq_msgsize, NULL) == -1)
                handle_error("mq_receive");
			printf ("child process received msg: %s\n", msg_buf);
			sleep (1);
            if (++count % 10 == 0)
                break;
		}
	}
	else if (ret_from_fork > 0) //parent process
	{
        int count = 0;
		while (1)
		{
			if (mq_send (mq_id, "hello world", sizeof ("hello world"), 1) == -1)
                handle_error("mq_send");
			printf ("parent process: send msg to mqueue success\n");
			sleep (1);
            if (++count % 10 == 0)
                break;
		}
	}
	else
        handle_error("fork");
    
    mq_close (mq_id);
    sleep (5);

	if (mq_unlink ("/posix_msg_queue") == -1)
        handle_error("mq_unlink");
	return 0;
}

两个独立进程通过POSIX消息队列通讯

receive

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <mqueue.h>

int main (void)
{
	mqd_t mq_id;
	if ((mq_id = mq_open("/posix_msg_queue", O_RDONLY | O_CREAT, 0644, NULL)) == -1)
	{
		perror ("mq_open");
		exit (EXIT_FAILURE);
	}
    struct mq_attr mq_attribute;
	if (mq_getattr (mq_id, &mq_attribute) == -1)
	{
		perror ("mq_getattr");
		exit (EXIT_FAILURE);
	}

	char msg_buf[mq_attribute.mq_msgsize];
	memset (msg_buf, 0, mq_attribute.mq_msgsize);

	while (1)
	{
		if (mq_receive (mq_id, msg_buf, mq_attribute.mq_msgsize, NULL) == -1)
		{
			perror ("mq_receive");
			exit (EXIT_FAILURE);
		}
		printf ("%s\n", msg_buf);
		sleep (1);
	}

    mq_close (mq_id);

	if (mq_unlink ("/posix_msg_queue") == -1)
	{
		perror ("mq_unlink");
		exit (EXIT_FAILURE);
	}
	return 0;
}

send

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <mqueue.h>

int main (void)
{
	mqd_t mq_id;
	if ((mq_id = mq_open("/posix_msg_queue", O_WRONLY | O_CREAT, 0644, NULL)) == -1)
	{
		perror ("mq_open");
		exit (EXIT_FAILURE);
	}
	while (1)
	{
		if (mq_send (mq_id, "hello world", sizeof("hello world"), 1) == -1)
		{
			perror ("mq_receive");
			exit (EXIT_FAILURE);
		}
		printf ("msg send success--------\n");
		sleep (1);
	}
    mq_close (mq_id);
	return 0;
}

发布了349 篇原创文章 · 获赞 6 · 访问量 9734

猜你喜欢

转载自blog.csdn.net/qq_23929673/article/details/100075126