读书笔记:第5章 Posix消息队列 (9)

《UNIX网络编程:卷2》P78:图5-15

/*
 * mqnotifythread1.c
 * P78 图5-15 启动一个线程的mq_notify
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <mqueue.h>
#include <pthread.h>

static void notify_thread(union sigval arg);	// 线程处理函数

mqd_t	mqd;
struct mq_attr	attr;
struct sigevent	sigev;

int main(int argc, char *argv[])
{
	if (argc != 2) {
		fprintf(stderr, "usage: mqnotifysig1 <name>\n");
		exit(0);
	}

	// 打开一个消息队列
	if ((mqd = mq_open(argv[1], O_RDONLY)) < 0) {
		fprintf(stderr, "mq_open error: %s\n", strerror(errno));
		exit(1);
	}

	// 获取消息队列的属性
	mq_getattr(mqd, &attr);

	sigev.sigev_notify = SIGEV_THREAD;		// 队列由空变为非空时,生成新线程
	sigev.sigev_value.sival_ptr = NULL;				// 线程函数参数
	sigev.sigev_notify_function = notify_thread;	// 线程函数
	sigev.sigev_notify_attributes = NULL;			// 线程属性

	//  为指定队列建立异步通知
	if (mq_notify(mqd, &sigev) < 0) {
		fprintf(stderr, "mq_notify error: %s\n", strerror(errno));
		exit(1);
	}

	for ( ; ; )
		pause();

	exit(0);
}

static void notify_thread(union sigval arg)
{
	ssize_t	n;
	void	*buff;

	printf("notify_thread started\n");

	// 分配缓冲区
	if ((buff = malloc(attr.mq_msgsize)) == NULL) {
		fprintf(stderr, "malloc error: %s\n", strerror(errno));
		exit(1);
	}   

	// 当通知被发送给它的注册进程时,其注册被撤销,所以再次注册 
	if (mq_notify(mqd, &sigev) < 0) {
		fprintf(stderr, "mq_notify error: %s\n", strerror(errno));
	}

	// 从消息队列中取出消息,使用循环
	while ((n = mq_receive(mqd, buff, attr.mq_msgsize, NULL)) >= 0) {
		printf("read %ld bytes\n", n);
	}

	if (errno != EAGAIN)            // EAGAIN,意味着暂时没有消息可读
		fprintf(stderr, "mq_receive error\n");

	free(buff);

	pthread_exit(NULL);
}

运行程序:

$ ./mqcreate /test01
5$ ./mqnotifythread1 /test01

从另一个窗口中运行:

$ ./mqsend /test1 50 16

程序mqnotifythread1输出为:

notify_thread started
read 100 bytes

你可能感兴趣的:(读书笔记,《UNIX网络编程》)