I recently switched from using kqueue to GCD dispatch sources to monitor file changes. This has worked out well and resulted in a much simpler API. I documented my switch here. The only issue I have is that now I cannot access the flags on the event that I was able to in kqueue. For example with kqueue I was able to check if the file was deleted, renamed, or it's attributes were changed with the following:
我最近从使用kqueue切换到GCD调度源来监视文件更改。这已经很好地完成了,并且产生了一个更简单的API。我在这里记录了我的开关。我唯一的问题是,现在我无法访问我能够以kqueue进行的事件的标志。例如,使用kqueue,我能够检查文件是否已被删除,重命名,或者其属性是否已更改,具体如下:
struct kevent event;
...
if(event.flag & EV_DELETE)
{
printf("File was deleted\n");
}
Is this API not available with GCD or do I need to set up dispatch sources up for each flag I would like to listen to. Or is it best to use kqueue since it provides greater visibility to the event that has occurred.
这个API不适用于GCD,还是我需要为每个我想听的标志设置调度源。或者最好使用kqueue,因为它为已发生的事件提供了更大的可见性。
2 个解决方案
#1
8
I found the answer in the Concurrency Programming Guide. I had first looked in the GCD Reference but without luck. The relevant line from the guide was
我在“并发编程指南”中找到了答案。我第一次看了GCD参考,但没有运气。该指南的相关内容是
For a descriptor dispatch source that monitors file system activity, this function returns a constant indicating the type of event that occurred. For a list of constants, see the dispatch_source_vnode_flags_t enumerated type.
对于监视文件系统活动的描述符分派源,此函数返回一个常量,指示发生的事件类型。有关常量列表,请参阅dispatch_source_vnode_flags_t枚举类型。
Here is an example of how you can use it.
以下是如何使用它的示例。
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);
#2
3
You may change *dispatch_source_get_mask(source)* to *dispatch_source_get_data(source)*, as dispatch_source_get_mask(source) returns all the flags you passed in the creation of the handler instead of the event generated.
您可以将* dispatch_source_get_mask(source)*更改为* dispatch_source_get_data(source)*,因为dispatch_source_get_mask(source)返回您在创建处理程序时传递的所有标志,而不是生成的事件。
#1
8
I found the answer in the Concurrency Programming Guide. I had first looked in the GCD Reference but without luck. The relevant line from the guide was
我在“并发编程指南”中找到了答案。我第一次看了GCD参考,但没有运气。该指南的相关内容是
For a descriptor dispatch source that monitors file system activity, this function returns a constant indicating the type of event that occurred. For a list of constants, see the dispatch_source_vnode_flags_t enumerated type.
对于监视文件系统活动的描述符分派源,此函数返回一个常量,指示发生的事件类型。有关常量列表,请参阅dispatch_source_vnode_flags_t枚举类型。
Here is an example of how you can use it.
以下是如何使用它的示例。
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);
#2
3
You may change *dispatch_source_get_mask(source)* to *dispatch_source_get_data(source)*, as dispatch_source_get_mask(source) returns all the flags you passed in the creation of the handler instead of the event generated.
您可以将* dispatch_source_get_mask(source)*更改为* dispatch_source_get_data(source)*,因为dispatch_source_get_mask(source)返回您在创建处理程序时传递的所有标志,而不是生成的事件。