这是linux下inotify的一个demo程序,inotify 是一种文件系统的变化通知机制,如文件增加、删除等事件可以立刻让用户态得知, 這裏主要去监控/work/test目录下的文件增加、删除事件
1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>
4 #include <sys/mman.h>
5 #include <stdio.h>
6 #include <sys/inotify.h>
8 #define BUF_LEN 1024
9 #define PATH "/work/test"
10
11 struct EventMask {
12 int flag;
13 const char* name;
14 };
16 struct EventMask event_masks[] = {
17 {IN_ACCESS , "IN_ACCESS"} ,
18 {IN_ATTRIB , "IN_ATTRIB"} ,
19 {IN_CLOSE_WRITE , "IN_CLOSE_WRITE"} ,
20 {IN_CLOSE_NOWRITE , "IN_CLOSE_NOWRITE"} ,
21 {IN_CREATE , "IN_CREATE"} ,
22 {IN_DELETE , "IN_DELETE"} ,
23 {IN_DELETE_SELF , "IN_DELETE_SELF"} ,
24 {IN_MODIFY , "IN_MODIFY"} ,
25 {IN_MOVE_SELF , "IN_MOVE_SELF"} ,
26 {IN_MOVED_FROM , "IN_MOVED_FROM"} ,
27 {IN_MOVED_TO , "IN_MOVED_TO"} ,
28 {IN_OPEN , "IN_OPEN"} ,
29 {IN_DONT_FOLLOW , "IN_DONT_FOLLOW"} ,
30 {IN_EXCL_UNLINK , "IN_EXCL_UNLINK"} ,
31 {IN_MASK_ADD , "IN_MASK_ADD"} ,
32 {IN_ONESHOT , "IN_ONESHOT"} ,
33 {IN_ONLYDIR , "IN_ONLYDIR"} ,
34 {IN_IGNORED , "IN_IGNORED"} ,
35 {IN_ISDIR , "IN_ISDIR"} ,
36 {IN_Q_OVERFLOW , "IN_Q_OVERFLOW"} ,
37 {IN_UNMOUNT , "IN_UNMOUNT"} ,
38 };
39
40 int main()
41 {
42
43 char buf[BUF_LEN];
44 struct inotify_event *event;
45 int fd = inotify_init(); //初始化inotify
//監控PATH目錄下的IN_DELETE | IN_CREATE事件
46 int state = inotify_add_watch(fd, PATH,IN_DELETE | IN_CREATE);
47 while (state > 0) {
// 通过 read 调用可以一次获得多个事件,只要提供的 buf 足够大;如果沒有事件會一直阻塞在這
48 size_t len = read (fd, buf, BUF_LEN);
49 event = (struct inotify_event *)buf;
50 int i = 0;
51 for (i=0; i <22; ++i) {
52 if (event->mask & event_masks[i].flag) {
53 printf("\t%s\n", event_masks[i].name);
54 }
55 }
56 }
57 }
15
Android中PackageManagerService來監控目錄中的apk的更新以及刪除就是用linux下的inotify來實現的,不過它是調用class FileObserver提供的接口, FileObserver也只是對inotify的封裝。
frameworks/base/core/java/android/os/FileObserver.java
42 public abstract class FileObserver {
......
88 public int startWatching(String path, int mask, FileObserver observer) {
89 int wfd = startWatching(m_fd, path, mask);
90
91 Integer i = new Integer(wfd);
92 if (wfd >= 0) {
93 synchronized (m_observers) {
94 m_observers.put(i, new WeakReference(observer));
95 }
96 }
97
98 return i;
99 }
101 public void stopWatching(int descriptor) {
102 stopWatching(m_fd, descriptor);
103 }
131 private native int startWatching(int fd, String path, int mask);
132 private native void stopWatching(int fd, int wfd);
line 89调用startWatching添加一個m_fd監控,line 102调用stopWatching刪除一個m_fd監控,它們都是Jni method
105 static jint android_os_fileobserver_startWatching(JNIEnv* env, jobject object, jint fd, jstring pathString, jint mask)
106 {
107 int res = -1;
108
109 #ifdef HAVE_INOTIFY
110
111 if (fd >= 0)
112 {
113 const char* path = env->GetStringUTFChars(pathString, NULL);
114
115 res = inotify_add_watch(fd, path, mask);
116
117 env->ReleaseStringUTFChars(pathString, path);
118 }
119
120 #endif // HAVE_INOTIFY
121
122 return res;
123 }
124
125 static void android_os_fileobserver_stopWatching(JNIEnv* env, jobject object, jint fd, jint wfd)
126 {
127 #ifdef HAVE_INOTIFY
128
129 inotify_rm_watch((int)fd, (uint32_t)wfd);
130
131 #endif // HAVE_INOTIFY
132 }
133
134 static JNINativeMethod sMethods[] = {
135 /* name, signature, funcPtr */
136 { "init", "()I", (void*)android_os_fileobserver_init },
137 { "observe", "(I)V", (void*)android_os_fileobserver_observe },
138 { "startWatching", "(ILjava/lang/String;I)I", (void*)android_os_fileobserver_startWatching },
139 { "stopWatching", "(II)V", (void*)android_os_fileobserver_stopWatching }
140
141 };
startWatching對應的Jni method是android_os_fileobserver_startWatching ,line 115也是调用inotify_add_watch去添加一个fd监控,同樣的stopWatching對應的Jni method是android_os_fileobserver_stopWatching,line 129调用inotify_rm_watch來刪除fd監控。