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

《UNIX网络编程:卷2》P75:图5-13

-------------------------------------------------------------------

/*
 * mqnotifysig4.c
 * P75 图5-13 伴随sigwait使用mq_notify 
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <mqueue.h>

int main(int argc, char *argv[])
{
	int			signo;
	mqd_t		mqd;
	void		*buff;
	ssize_t		n;
	sigset_t	newmask;
	struct mq_attr	attr;
	struct sigevent	sigev;

	if (argc != 2) {
		fprintf(stderr, "usage: mqnotifysig1 <name>\n");
		exit(0);
	}

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

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

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

	sigemptyset(&newmask);						// 初始化信号集
	sigaddset(&newmask, SIGUSR1);				// 在newmask中打开SIGUSR1的位
	sigprocmask(SIG_BLOCK, &newmask, NULL);		// 阻塞SIGUSR1

	sigev.sigev_notify = SIGEV_SIGNAL;			// 队列由空变为非空时,产生信号
	sigev.sigev_signo = SIGUSR1;				// 希望产生的信号编号

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

	for ( ; ; ) {

		sigwait(&newmask, &signo);				// 阻塞,等待newmask中的信号

		if (signo == SIGUSR1) {

			// 当通知被发送给它的注册进程时,其注册被撤销,所以再次注册 
			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("SIGUSR1 received, read %ld types\n", n);
			}
			if (errno != EAGAIN)			// EAGAIN,意味着暂时没有消息可读
				fprintf(stderr, "mq_receive error\n");
		}
	}

	exit(0);
}

运行程序:

$ ./mqcreate /test1
$ ./mqnotifysig4 /test1

从另一个窗口中运行:

$ ./mqsend /test1 50 16

程序mqnotifysig4输出为:

SIGUSR1 received, read 50 types

sigwait往往在多线程的进程中使用。在多线程化的进程中不能使用sigprocmask,而必须调用pthread_sigmask,它只是改变调用多线程的信号掩码。

大多数多线程的书籍,推荐在多线程化的进程中使用sigwait来处理所有信号,而绝不要使用异步信号处理程序。

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