我使用
David Hamrick的代码示例来使用GCD监视文件.
int fildes = open("/path/to/config.plist",O_RDONLY); dispatch_queue_t queue = dispatch_get_global_queue(disPATCH_QUEUE_PRIORITY_DEFAULT,0); 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,^ { //Reload the config file }); dispatch_source_set_cancel_handler(source,^ { //Handle the cancel }); dispatch_resume(source);
解决方法
您确实可以在收到disPATCH_VNODE_DELETE时重新打开文件并重新注册源(删除前一个).或者您可以使用专为此类场景设计的调用,即dispatch_io_create_with_path() – 它不仅会按路径观看,还会为您打开文件并让您以异步方式读取内容.
既然你问(不知道你要求哪种技术,但这里最简单)这里有一个独立的代码示例:
#include <dispatch/dispatch.h> #include <stdio.h> int main(int ac,char *av[]) { int fdes = open("/tmp/pleasewatchthis",O_RDONLY); dispatch_queue_t queue = dispatch_get_global_queue(0,0); void (^eventHandler)(void),(^cancelHandler)(void); unsigned long mask = disPATCH_VNODE_DELETE | disPATCH_VNODE_WRITE | disPATCH_VNODE_EXTEND | disPATCH_VNODE_ATTRIB | disPATCH_VNODE_LINK | disPATCH_VNODE_RENAME | disPATCH_VNODE_REVOKE; __block dispatch_source_t source; eventHandler = ^{ unsigned long l = dispatch_source_get_data(source); if (l & disPATCH_VNODE_DELETE) { printf("watched file deleted! cancelling source\n"); dispatch_source_cancel(source); } else { // handle the file has data case printf("watched file has data\n"); } }; cancelHandler = ^{ int fdes = dispatch_source_get_handle(source); close(fdes); // Wait for new file to exist. while ((fdes = open("/tmp/pleasewatchthis",O_RDONLY)) == -1) sleep(1); printf("re-opened target file in cancel handler\n"); source = dispatch_source_create(disPATCH_SOURCE_TYPE_VNODE,fdes,mask,queue); dispatch_source_set_event_handler(source,eventHandler); dispatch_source_set_cancel_handler(source,cancelHandler); dispatch_resume(source); }; source = dispatch_source_create(disPATCH_SOURCE_TYPE_VNODE,queue); dispatch_source_set_event_handler(source,eventHandler); dispatch_source_set_cancel_handler(source,cancelHandler); dispatch_resume(source); dispatch_main(); }