2

如何将 ev_io 与 mqueue 一起使用?我正在尝试做以下没有运气的事情。

#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "ev.h"

#define MAX_Q_SIZE 255
#define MY_QUEUE "/test_queue"

typedef struct __test_ctxt_t
{
    ev_timer    timeout_watcher[32];
    ev_io       stdin_watcher;
    struct ev_loop *loop;
    mqd_t       mq;
    int         data;
}test_ctxt_t;

static test_ctxt_t *g_ctxt = NULL;

static void mq_callback(EV_P_ struct ev_io *w, int revents)
{
    test_ctxt_t *ctxt = (test_ctxt_t *)w;
    struct      mq_attr attr;
    char        msg[256];
    int         rcvd_msg_size;

    rcvd_msg_size = mq_receive(ctxt->mq, msg, MAX_Q_SIZE, NULL);
    if (rcvd_msg_size >= 0)
    {
        msg[rcvd_msg_size] = '\0';
        printf("Received: %s\n", msg);
        if (strcmp(msg, "stop") == 0)
        {
            printf("Exiting....\n");
            ev_unloop (EV_A_ EVUNLOOP_ONE);
        }
    }
}

static void timeout_cb1 (EV_P_ struct ev_timer *w, int revents)
{
  puts ("timeout timeout_cb1");
  //ev_unloop (EV_A_ EVUNLOOP_ONE);
}

static void timeout_cb2 (EV_P_ struct ev_timer *w, int revents)
{
  puts ("timeout timeout_cb2");
  //ev_unloop (EV_A_ EVUNLOOP_ONE);
}
static void timeout_cb3 (EV_P_ struct ev_timer *w, int revents)
{
  puts ("timeout timeout_cb3");
  //ev_unloop (EV_A_ EVUNLOOP_ONE);
}

int main (void)
{
    struct      mq_attr attr;

    g_ctxt = (test_ctxt_t *)calloc(1, sizeof(test_ctxt_t));

    g_ctxt->loop = ev_default_loop (0);

    /* initialize the queue attributes */
    attr.mq_flags = 0;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = 255;
    g_ctxt->mq = mq_open(MY_QUEUE, O_CREAT | O_RDONLY, 0644, &attr);
    if (g_ctxt->mq == -1)
    {
        printf("Unable to open Queue");
        return -1;
    }

    ev_io_init(&g_ctxt->stdin_watcher, mq_callback, g_ctxt->mq, EV_READ);
    ev_io_start(g_ctxt->loop, &g_ctxt->stdin_watcher);

    ev_timer_init (&g_ctxt->timeout_watcher[0], timeout_cb1, 10, 0.);
    ev_timer_start (g_ctxt->loop, &g_ctxt->timeout_watcher[0]);

    ev_loop (g_ctxt->loop, 0);

    return 0;
}

我能够得到计时器回调,但是在向队列发送消息时永远不会调用 io 回调。是否可以将 POSIX mqueue 与 libev 一起使用?

4

1 回答 1

0

基本上有三种方法,如何做到这一点:

1) 在 Linux 平台上,消息队列处理程序是一个有效的文件描述符。

轮询消息队列描述符

在 Linux 上,消息队列描述符实际上是一个文件描述符,可以使用 select(2)、poll(2) 或 epoll(7) 进行监控。这不是便携式的。

mq_overview手册页

您可以利用ev_io观察者来收听传入的消息。

这是 LINUX 特定且不可移植的代码。

2)您可以使用函数mq_notify配置一个信号,该信号将在消息队列收到新消息时发送。这个信号可以ev_signal由 libev 的观察者处理。

这似乎是更便携的代码,但由于信号交互,性能会有点低。

请参见mq_notify手册页。

3) 切换到面向数据报的套接字、UNIX网络。这些提供了大致相同的发送消息(又名数据报)的能力。您将获得无连接、尽力而为、不可靠的消息传递服务。

这种方法非常便携。

Macintosh 注意:
macOS 中没有 POSIX 消息队列实现,因此此类代码的可移植性在此 Apple 平台方面受到限制。有可能在 NSOperationQueue 或 Grand Central Dispatch 上模仿相同的功能,但这肯定会导致大量工作。

于 2017-06-18T10:43:42.053 回答