用管道(pipe)使消息队列通知(mq_notify)可以在Select和poll中使用

来源:互联网 发布:知乎 父母的爱 编辑:程序博客网 时间:2024/05/29 04:03
这是在Unix网络编程第二卷进程间通信中看到的一个技巧。它使得posix消息队列的mq_notify可以在select中使用。具体方法为:
1、建立管道;
2、在主线程中用select监听管道的读事件;
3、在mq_notify的时间处理程序中往管道里写数据,通知主线程
只是不知道这样做,效率怎么样。

UNP-IPC有一段实例代码,如下:
1 #include    "unpipc.h" 2  3 int        pipefd[2]; 4 static void    sig_usr1(int); 5 /* $$.bp$$ */ 6 int 7 main(int argc, char **argv) 8 { 9     int        nfds;10     char    c;11     fd_set    rset;12     mqd_t    mqd;13     void    *buff;14     ssize_t    n;15     struct mq_attr    attr;16     struct sigevent    sigev;17 18     if (argc != 2)19         err_quit("usage: mqnotifysig5 <name>");20 21         /* 4open queue, get attributes, allocate read buffer */22     mqd = Mq_open(argv[1], O_RDONLY | O_NONBLOCK);23     Mq_getattr(mqd, &attr);24     buff = Malloc(attr.mq_msgsize);25 26     Pipe(pipefd);27 28         /* 4establish signal handler, enable notification */29     Signal(SIGUSR1, sig_usr1);30     sigev.sigev_notify = SIGEV_SIGNAL;31     sigev.sigev_signo = SIGUSR1;32     Mq_notify(mqd, &sigev);33 34     FD_ZERO(&rset);35     for ( ; ; ) {36         FD_SET(pipefd[0], &rset);37         nfds = Select(pipefd[0] + 1, &rset, NULL, NULL, NULL);38 39         if (FD_ISSET(pipefd[0], &rset)) {40             Read(pipefd[0], &c, 1);41             Mq_notify(mqd, &sigev);            /* reregister first */42             while ( (n = mq_receive(mqd, buff, attr.mq_msgsize, NULL)) >= 0) {43                 printf("read %ld bytes\n", (long) n);44             }45             if (errno != EAGAIN)46                 err_sys("mq_receive error");47         }48     }49     exit(0);50 }51 52 static void53 sig_usr1(int signo)54 {55     Write(pipefd[1], "", 1);    /* one byte of 0 */56     return;57 }58 
转自http://www.cppblog.com/mildforest/archive/2011/02/24/140611.aspx