我最近从使用kqueue切换到GCD dispatch sources来监视文件更改。这已经很好地完成了,并且导致了一个简单得多的API。我记录了我的开关here。我唯一的问题是,现在我无法通过kqueue访问事件中的标志。例如,使用kqueue,我可以检查文件是否已删除,重命名,或者其属性是否已更改,如下所示:

struct kevent event;

...

if(event.flag & EV_DELETE)
{
    printf("File was deleted\n");
}

该API是否在GCD中不可用,还是我需要为我想听的每个标志设置调度源。还是最好使用kqueue,因为它可以提供更大的可见性。

最佳答案

我在Concurrency Programming Guide中找到了答案。我最初看过GCD Reference,但是没有运气。指南中的相关内容是



这是一个如何使用它的示例。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
int fildes = open("path/to/some/file", O_EVTONLY);
__block dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE,fildes,
                                                  DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_ATTRIB | DISPATCH_VNODE_LINK | DISPATCH_VNODE_RENAME | DISPATCH_VNODE_REVOKE,
                                                  queue);
dispatch_source_set_event_handler(source, ^
{
    unsigned long flags = dispatch_source_get_mask(source);
    if(flags & DISPATCH_VNODE_DELETE)
        printf("DISPATCH_VNODE_DELETE\n");
    if(flags & DISPATCH_VNODE_WRITE)
        printf("DISPATCH_VNODE_WRITE\n");
    if(flags & DISPATCH_VNODE_EXTEND)
        printf("DISPATCH_VNODE_EXTEND\n");
    if(flags & DISPATCH_VNODE_ATTRIB)
        printf("DISPATCH_VNODE_ATTRIB\n");
    if(flags & DISPATCH_VNODE_LINK)
        printf("DISPATCH_VNODE_LINK\n");
    if(flags & DISPATCH_VNODE_RENAME)
        printf("DISPATCH_VNODE_RENAME\n");
    if(flags & DISPATCH_VNODE_REVOKE)
        printf("DISPATCH_VNODE_REVOKE\n");
});
dispatch_source_set_cancel_handler(source, ^(void)
{
    close(fildes);
});
dispatch_resume(source);

07-26 09:38