Có, có thể trong C. Bạn nên tìm kiếm Kernel Queues.
Dưới đây là một mẫu nhỏ để xem các thư mục:
#include <errno.h> // for errno
#include <fcntl.h> // for O_RDONLY
#include <stdio.h> // for fprintf()
#include <stdlib.h> // for EXIT_SUCCESS
#include <string.h> // for strerror()
#include <sys/event.h> // for kqueue() etc.
#include <unistd.h> // for close()
int main (int argc, const char *argv[])
{
int kq = kqueue();
// dir name is in argv[1], NO checks for errors here
int dirfd = open (argv[1], O_RDONLY);
struct kevent direvent;
EV_SET (&direvent, dirfd, EVFILT_VNODE, EV_ADD | EV_CLEAR | EV_ENABLE,
NOTE_WRITE, 0, (void *)dirname);
kevent(kq, &direvent, 1, NULL, 0, NULL);
// Register interest in SIGINT with the queue. The user data
// is NULL, which is how we'll differentiate between
// a directory-modification event and a SIGINT-received event.
struct kevent sigevent;
EV_SET (&sigevent, SIGINT, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 0, 0, NULL);
// kqueue event handling happens after the legacy API, so make
// sure it doesn eat the signal before the kqueue can see it.
signal (SIGINT, SIG_IGN);
// Register the signal event.
kevent(kq, &sigevent, 1, NULL, 0, NULL);
while (1) {
// camp on kevent() until something interesting happens
struct kevent change;
if (kevent(kq, NULL, 0, &change, 1, NULL) == -1) { exit(1); }
// The signal event has NULL in the user data. Check for that first.
if (change.udata == NULL) {
break;
} else {
// udata is non-null, so it's the name of the directory
printf ("%s\n", (char*)change.udata);
}
}
close (kq);
return 0;
}
Các chi tiết có thể được tìm thấy trong ch. 16 (kqueues và FSEvents) của "Lập trình Mac OSX nâng cao" của Mark Dalrymple. Thông tin bổ sung có thể được tìm thấy trong tài liệu * BSD cho kqueues.
Hoặc sử dụng API này từ FSEvents (chủ yếu dựa trên C).
FSEventStreamRef FSEventStreamCreate (CFAllocatorRef allocator,
FSEventStreamCallback callback,
FSEventStreamContext *context,
CFArrayRef pathsToWatch,
FSEventStreamEventId sinceWhen,
CFTimeInterval latency,
FSEventStreamCreateFlags flags);
để tạo luồng sự kiện FSEvents bằng gọi lại C thuần túy.
Sau đó đính kèm dòng sự kiện này để runloop của bạn bằng cách sử dụng
void FSEventStreamScheduleWithRunLoop (FSEventStreamRef streamRef,
CFRunLoopRef runLoop,
CFStringRef runLoopMode);
Vâng, đây có lẽ bạn nên sử dụng một dòng obj-C để có được xử lý runloop: lấy CFRunLoop từ một NSRunLoop bằng cách sử dụng -getCFRunLoop
CFRunLoop* loopRef = [[NSRunLoop currentRunLoop] getCFRunLoop];
hoặc sử dụng C gọi tinh khiết
CFRunLoop* loopRef = CFRunLoopGetCurrent();
Bắt đầu sự kiện dòng với
Boolean FSEventStreamStart (FSEventStreamRef streamRef);
Dừng luồng sự kiện với
void FSEventStreamStop (FSEventStreamRef streamRef);
Và sau đó unschedule nó từ runloop với điều này:
void FSEventStreamUnscheduleFromRunLoop (FSEventStreamRef streamRef,
CFRunLoopRef runLoop,
CFStringRef runLoopMode);
Vô hiệu hóa luồng (dọn dẹp):
void FSEventStreamInvalidate (FSEventStreamRef streamRef);
Hy vọng điều này sẽ giúp bạn tarted.
Trong thử nghiệm của tôi, kqueue không có chức năng tương đương với FSEvents. Cảm ơn bạn đã phác thảo bit CFRunLoop! – berkus