Macos 为什么轮询指示观察单个空马赫端口集的队列是可读的?

Macos 为什么轮询指示观察单个空马赫端口集的队列是可读的?,macos,polling,kqueue,mach,Macos,Polling,Kqueue,Mach,我有一个队列在监视一个项目:一个空的马赫端口集。kevent64表示没有可用的事件,select表示kqueue尚未准备好读取。但民意调查显示,kqueue是可读的尽管在随后调用kevent64读取假定已准备好的事件时,情况似乎并非如此 下面是我正在使用的代码。您可以使用gcc-Wall-std=c99-o test test.c之类的工具构建它,然后使用./test或其他工具运行它。它打印出kevent64中的返回值。在尝试不等待读取1后,实际检索到的事件计数,选择轮询后准备读取的文件描述符计

我有一个队列在监视一个项目:一个空的马赫端口集。kevent64表示没有可用的事件,select表示kqueue尚未准备好读取。但民意调查显示,kqueue是可读的尽管在随后调用kevent64读取假定已准备好的事件时,情况似乎并非如此

下面是我正在使用的代码。您可以使用gcc-Wall-std=c99-o test test.c之类的工具构建它,然后使用./test或其他工具运行它。它打印出kevent64中的返回值。在尝试不等待读取1后,实际检索到的事件计数,选择轮询后准备读取的文件描述符计数,以及轮询后准备读取的文件描述符轮询计数

我期望的输出是这样的,表示kevent64、select和poll都同意kqueue是空的

$ ./kqueue_poll_machport
kevent64: 0
select: 0
poll: 0 (revents: 0)
kevent64: 0
但我实际得到的是,显示kevent64和select说出一件事,然后轮询另一件事——而且,即使轮询表明kqueue是可读的,kevent64仍然表示没有要读取的事件——这是第二个kevent64调用的原因

revents的1值是POLLIN,这意味着可以在不阻塞的情况下读取数据。如果我单独指定pollRDorm和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);
    }
}
#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);
    }
}