Last active
December 11, 2020 14:28
-
-
Save luowei/08de72d67dda439ae52acafe86571cc8 to your computer and use it in GitHub Desktop.
dispatch source 非阻塞读写文件、监听文件、子进程
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//非阻塞读 | |
dispatch_source_t ProcessContentsOfFile(const char *filename) { | |
// Prepare the file for reading. | |
int fd = open(filename, O_RDONLY); | |
if (fd == -1) | |
return NULL; | |
fcntl(fd, F_SETFL, O_NONBLOCK); // Avoid blocking the read operation | |
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); | |
dispatch_source_t readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, queue); | |
if (!readSource) { | |
close(fd); | |
return NULL; | |
} | |
// Install the event handler | |
dispatch_source_set_event_handler(readSource, ^{ | |
size_t estimated = dispatch_source_get_data(readSource) + 1; | |
// Read the data into a text buffer. | |
char *buffer = (char *) malloc(estimated); | |
if (buffer) { | |
ssize_t actual = read(fd, buffer, (estimated)); | |
Boolean done = MyProcessFileData(buffer, actual); // Process the data. | |
free(buffer); // Release the buffer when done. | |
if (done) // If there is no more data, cancel the source. | |
dispatch_source_cancel(readSource); | |
} | |
}); | |
dispatch_source_set_cancel_handler(readSource, ^{ | |
close(fd); | |
}); // Install the cancellation handler | |
dispatch_resume(readSource); // Start reading the file. | |
return readSource; | |
} | |
//非阻塞写文件 | |
dispatch_source_t WriteDataToFile(const char* filename) { | |
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, (S_IRUSR | S_IWUSR | S_ISUID | S_ISGID)); | |
if (fd == -1) | |
return NULL; | |
fcntl(fd, F_SETFL); // Block during the write. | |
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); | |
dispatch_source_t writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, fd, 0, queue); | |
if (!writeSource) { | |
close(fd); | |
return NULL; | |
} | |
dispatch_source_set_event_handler(writeSource, ^{ | |
size_t bufferSize = MyGetDataSize(); | |
void* buffer = malloc(bufferSize); | |
size_t actual = MyGetData(buffer, bufferSize); | |
write(fd, buffer, actual); | |
free(buffer); | |
dispatch_source_cancel(writeSource); // Cancel and release the dispatch source when done. | |
}); | |
dispatch_source_set_cancel_handler(writeSource, ^{close(fd);}); | |
dispatch_resume(writeSource); | |
return (writeSource); | |
} | |
//监听文件变化 | |
dispatch_source_t MonitorNameChangesToFile(const char* filename) { | |
int fd = open(filename, O_EVTONLY); | |
if (fd == -1) | |
return NULL; | |
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); | |
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE,fd, DISPATCH_VNODE_RENAME, queue); | |
if (source) { | |
// Copy the filename for later use. | |
int length = strlen(filename); | |
char* newString = (char*)malloc(length + 1); | |
newString = strcpy(newString, filename); | |
dispatch_set_context(source, newString); | |
// Install the event handler to process the name change | |
dispatch_source_set_event_handler(source, ^{ | |
const char* oldFilename = (char*)dispatch_get_context(source); | |
MyUpdateFileName(oldFilename, fd); | |
}); | |
// Install a cancellation handler to free the descriptor | |
// and the stored string. | |
dispatch_source_set_cancel_handler(source, ^{ | |
char* fileStr = (char*)dispatch_get_context(source); | |
free(fileStr); | |
close(fd); | |
}); | |
// Start processing events. | |
dispatch_resume(source); | |
} | |
else | |
close(fd); | |
return source; | |
} | |
//监控子进程 | |
void MonitorParentProcess() { | |
pid_t parentPID = getppid(); | |
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); | |
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC,parentPID, DISPATCH_PROC_EXIT, queue); | |
if (source) { | |
dispatch_source_set_event_handler(source, ^{ | |
MySetAppExitFlag(); | |
dispatch_source_cancel(source); | |
dispatch_release(source); | |
}); | |
dispatch_resume(source); | |
} | |
} | |
//添加信号处理器,处理信号 | |
void InstallSignalHandler() { | |
// Make sure the signal does not terminate the application. | |
signal(SIGHUP, SIG_IGN); | |
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); | |
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGHUP, 0, queue); | |
if (source) { | |
dispatch_source_set_event_handler(source, ^{ | |
MyProcessSIGHUP(); | |
}); | |
// Start processing signals | |
dispatch_resume(source); | |
} | |
} | |
//取消dispatch source | |
void RemoveDispatchSource(dispatch_source_t mySource) { | |
dispatch_source_cancel(mySource); | |
dispatch_release(mySource); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment