Skip to content

Instantly share code, notes, and snippets.

@luowei
Last active December 11, 2020 14:28
Show Gist options
  • Save luowei/08de72d67dda439ae52acafe86571cc8 to your computer and use it in GitHub Desktop.
Save luowei/08de72d67dda439ae52acafe86571cc8 to your computer and use it in GitHub Desktop.
dispatch source 非阻塞读写文件、监听文件、子进程
//非阻塞读
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