1

我有一个 kqueue 正在监视一个项目:一个空的 Mach 端口集。kevent64表示没有可用的事件,并select表示 kqueue 尚未准备好读取。但是poll说 kqueue可读的!kevent64- 尽管在随后调用以读取假定准备好的事件时,情况似乎并非如此。

我正在使用的代码如下。你可以用类似的东西来构建它gcc -Wall -std=c99 -o test test.c,然后用它./test或其他东西运行它。它打印出以下返回值kevent64:(在尝试读取 1 而无需等待后实际检索到的事件计数)、select(轮询后准备读取的文件描述符计数)和poll(轮询后准备读取的文件描述符计数)。

我期望的输出是这样的,表明kevent64select并且poll所有人都同意 kqueue 是空的。

$ ./kqueue_poll_machport
kevent64: 0
select: 0
poll: 0 (revents: 0)
kevent64: 0

但我实际上得到的是这个,显示kevent64select说一件事,poll另一件事 - 而且,即使在poll表明 kqueue 是可读的之后,kevent64仍然说没有要读取的事件(这是第二次kevent64调用的原因)。

$ ./kqueue_poll_machport
kevent64: 0
select: 0
poll: 1 (revents: 1)
kevent64: 0

revents( is的 1 值POLLIN,据说,表示可以在没有阻塞的情况下读取数据。如果我单独指定POLLRDNORM,结果是相同的POLLRDBAND。)

为什么会出现差异?

我的测试代码:

#include <stdio.h>
#include <assert.h>
#include <mach/mach.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <sys/select.h>
#include <poll.h>

int main(void) {
    kern_return_t kr;
    int rc;

    int kq=kqueue();
    assert(kq!=-1);

    mach_port_name_t port_set;
    kr=mach_port_allocate(mach_task_self(),MACH_PORT_RIGHT_PORT_SET,&port_set);
    assert(kr==KERN_SUCCESS);

    {
        const struct kevent64_s events[]={
            {
                .flags=EV_ADD|EV_ENABLE,
                .filter=EVFILT_MACHPORT,
                .ident=port_set,
            },
        };

        rc=kevent64(kq,events,sizeof events/sizeof events[0],NULL,0,0,NULL);
        assert(rc==0);
    }

    /* Events available? */
    {
        const struct timespec NO_TIMEOUT={0,0};
        struct kevent64_s event;
        rc=kevent64(kq,NULL,0,&event,1,0,&NO_TIMEOUT);
        printf("kevent64: %d\n",rc);
    }

    /* Test readability with select. */
    {
        const struct timeval NO_TIMEOUT={0,0};
        fd_set rd;
        FD_ZERO(&rd);
        FD_SET(kq,&rd);
        rc=select(kq+1,&rd,NULL,NULL,&NO_TIMEOUT);
        printf("select: %d\n",rc);
    }

    /* Test readibility with poll. */
    {
        struct pollfd fds[]={
            {
                .fd=kq,
                .events=POLLIN,
            },
        };
        rc=poll(fds,sizeof fds/sizeof fds[0],0);
        printf("poll: %d (revents: %d)\n",rc,fds[0].revents);
    }

    /* Events available? */
    {
        const struct timespec NO_TIMEOUT={0,0};
        struct kevent64_s event;
        rc=kevent64(kq,NULL,0,&event,1,0,&NO_TIMEOUT);
        printf("kevent64: %d\n",rc);
    }
}
4

0 回答 0