文件系統事件監控對於從文件管理器到安全工具等多種程序來說都是必要的。對於如何整理和控制Linux文件系統中的事件在實際的使用中有很多方式,inotify是比較常用的一種方法。在本文中你會學習到如何使用inotify以及他的一些相關知識。
AD:
本文主要向大家介紹瞭如何使用inotify控制Linux文件系統中的事件。在具體的學習之前我們先來看看什麼是inotify以及他的歷史簡介。我們還會向大家介紹inotify的具體應用情況以及使中遇到問題的解決方案。
inotify 介紹
文件系統事件監控對於從文件管理器到安全工具等多種程序來說都是必要的。自 2.6.13 版本內核開始,Linux 就提供 inotify 功能,這允許監控程序打開一個獨立文件描述符,並針對一系列特定的事件來監控一個或多個文件或者目錄,例如打開、關閉、移動/重命名、 刪除、創建或者改變屬性。在以後的版本中還提供更多增強功能,因此在依賴這些特性之前請先檢查系統的內核版本。
在本文中,您將學會如何在簡單的監控程序當中使用 inotify 函數。下載樣例代碼 並在系統當中進行編譯,來爲後面的研究做準備。
歷史簡介
在 inotify 之前有 dnotify 。不幸的是,dnotify 有侷限性,無法滿足用戶的需求, inotify 的優勢如下:
Inotify 採用簡單的文件描述符,而 dnotify 需要爲每個受監控的目錄打開一個文件描述符。 這使得同時監控多個目錄成本很高,而且還會遇到每進程文件描述符限制問題。
inotify 所採用的文件描述符通過系統調用獲得,並且沒有相關的設備或文件。對於 dnotify ,文件描述符與目錄關係固定,避免了相關設備未被加載的問題,這是可移動媒體的典型問題。對於 inotify ,如果受監控文件或目錄所在的文件系統未被加載, 則會產生一個事件,然後該監控會被自動移除。
Inotify 能夠監控文件或目錄。Dnotify 監控目錄, 因此程序員必須保持 stat 結構或者等效的數據結構,來反映目錄當中被監控的文件, 然後在一個事件發生時,將其與當前狀態進行對比,來知曉目錄當中的條目發生了什麼情況。
如前面所述,inotify 採用文件描述符,允許程序員採用標準 select 或者 poll 函數來對事件進行監控。 這允許高效的多重 I/O 或者與 Glib 的 mainloop 集成。相比之下,dnotify 採用信號, 這使得程序員感到難度更大或者不夠流暢。 在 2.6.25 版本內核中,inotify 也增加了 Signal-drive I.O 通告功能。
用於 inotify 的 API
Inotify 提供簡單的 API ,採用最小的文件描述符並允許細粒度監控。與 inotify 的通信通過系統調用實現。
inotify_init
是用於創建 inotify 實例的系統調用,並返回一個指向該實例的文件描述符。
inotify_init1
與 inotify_init 相似,並帶有附加標誌。如果這些標誌沒有指定,將採用與 inotify_init 相同的值。
inotify_add_watch
增加對文件或目錄的監控並指定需要監控哪些事件。 標誌用於控制是否將事件加入到已有的監控當中,是否只有路徑代表一個目錄才進行監控, 是否需要追蹤符號鏈接,是否進行一次性監控,當首次出現事件後就停止監控。
inotify_rm_watch
從監控列表中移除監控項目。
read
讀取包含一個或多個事件信息的緩存。
close
關閉文件描述符,並移除所有在該描述符上的監控。 當關於某一實例的文件描述符都關閉以後, 資源和下層的對象都將釋放,來供內核再次使用。
因此,典型的監控程序要進行如下操作:
利用 inotify_init 打開文件描述符;
增加一個或多個監控;
等待事件;
處理事件,然後返回並等待更多事件;
當沒有活躍的監控時或者基於某些信號的指示,關閉文件描述符,清空,然後退出。
在下一部分中,您將看到可以監控的事件,以及它們如何在簡單程序當中運行。最後您將看到如何進行事件監控。
通告
當應用程序讀取一個通告時,事件的順序也被讀取到緩存中。事件在一個變長結構體中被返回,見清單 1 。如果數據佔滿了緩存,可能需要對最後一個條目進行局部事件信息或者局部名處理。
清單 1. 用於 inotify 的事件結構體
- struct inotify_event
- {
- int wd; /* Watch descriptor. */
- uint32_t mask; /* Watch mask. */
- uint32_t cookie; /* Cookie to synchronize two events. */
- uint32_t len; /* Length (including NULs) of name. */
- char name __flexarr; /* Name. */
- };
注意,只有當監控對象是一個目錄並且事件與目錄內部相關項目有關,而與目錄本身無關時,才提供 name 字段。 如果 IN_MOVED_FROM 事件與相應的 IN_MOVED_TO 事件都與被監控的項目有關,cookie 就可用於將兩者關聯起來。 事件類型在掩碼字段中返回,並伴隨着能夠被內核設置的標誌。 例如,如果事件與目錄有關,則標誌 IN_ISDIR 將由內核設置。
能夠監控的事件
有幾種事件能夠被監控。有一些,比如 IN_DELETE_SELF 只應用到正在被監控的項目,然而另一些比如 IN_ATTRIB 或者 IN_OPEN 可以應用到監控過的項目, 或者如果該項目是目錄,則可以應用到其所包含的目錄或文件。
IN_ACCESS
被監控項目或者被監控目錄當中的條目被訪問過。例如,一個打開的文件被讀取。
IN_MODIFY
被監控項目或者被監控目錄當中的條目被修改過。例如,一個打開的文件被修改。
IN_ATTRIB
被監控項目或者被監控目錄當中條目的元數據被修改過。例如,時間戳或者許可被修改。
IN_CLOSE_WRITE
一個打開的,等待寫入的文件或目錄被關閉。
IN_CLOSE_NOWRITE
一個以只讀方式打開的文件或目錄被關閉。
IN_CLOSE
是可以很便捷地對前面提到的兩個關閉事件(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)進行邏輯或操作的掩碼。
IN_OPEN
文件或目錄被打開。
IN_MOVED_FROM
被監控項目或者被監控目錄當中的條目被移出監控區域。該事件還包含一個 cookie 來實現 IN_MOVED_FROM 與 IN_MOVED_TO 的關聯。
IN_MOVED_TO
文件或目錄被移入監控區域。該事件包含一個針對 IN_MOVED_FROM 的 cookie 。如果文件或目錄只是被重命名,將能看到這兩個事件,如果它只是被移入或移出非監控區域,將只能看到一個事件。 如果移動或重命名一個被監控項目,監控將繼續進行。參見下面的 IN_MOVE-SELF 。
IN_MOVE
是可以很便捷地對前面提到的兩個移動事件(IN_MOVED_FROM | IN_MOVED_TO)進行邏輯或操作的掩碼。
IN_CREATE
在被監控目錄當中創建了子目錄或文件。
IN_DELETE
被監控目錄當中有子目錄或文件被刪除。
IN_DELETE_SELF
被監控項目本身被刪除。監控被終止並收到一個 IN_IGNORED 事件。
IN_MOVE_SELF
監控項目本身被移動。
除了事件標誌以外,還可以在 inotify 頭文件(/usr/include/sys/inotify.h)中找到其他幾個標誌。 例如,如果只想監控第一個事件,可以在增加監控時設置 IN_ONESHOT 標誌。
inotify 簡單應用
這裏的簡單應用遵循以上的通用邏輯。 我們使用一個信號處理程序來監控 ctrl-c(SIGINT)並且 重置一個標誌(keep_running)使應用瞭解終止操作。 真實的 inotify 調用在 utility 例程當中完成。注意, 我們還創建了一個隊列,這樣能夠將事件從 inotify 底層對象中清除,留着稍後處理。在真實的應用當中,您可能希望用其他(具有更高優先級)的線程來完成這一操作。 這裏的列舉的應用程序,只是爲了對一般原理進行舉例說明。我們採用了一個簡單的事件鏈表, 隊列中的每一條目都包含原始事件加上用於存儲指向隊列中下一事件指針的空間。
主程序
清單 2 中展示了信號處理程序和主程序。在本例當中,對所有在命令行中出現過的文件或目錄進行監控, 並利用事件掩碼 IN_ALL_EVENTS 來監控每一對象的所有事件。 在真實的應用程序中,您可能只希望追蹤文件與目錄的創建或刪除事件,因此您可以掩去打開、關閉以及屬性改變事件。 如果您對文件或目錄的重命名和移動不感興趣,您也可以掩去各種移動事件。關於更多細節,參見 inotify 幫助信息。
清單 2. inotify-test.c 的簡單主程序
- /* Signal handler that simply resets a flag to cause termination */
- void signal_handler (int signum)
- {
- keep_running = 0;
- }
- int main (int argc, char **argv)
- {
- /* This is the file descriptor for the inotify watch */
- int inotify_fd;
- keep_running = 1;
- /* Set a ctrl-c signal handler */
- if (signal (SIGINT, signal_handler) == SIG_IGN)
- {
- /* Reset to SIG_IGN (ignore) if that was the prior state */
- signal (SIGINT, SIG_IGN);
- }
- /* First we open the inotify dev entry */
- inotify_fd = open_inotify_fd ();
- if (inotify_fd > 0)
- {
- /* We will need a place to enqueue inotify events,
- this is needed because if you do not read events
- fast enough, you will miss them. This queue is
- probably too small if you are monitoring something
- like a directory with a lot of files and the directory
- is deleted.
- */
- queue_t q;
- q = queue_create (128);
- /* This is the watch descriptor returned for each item we are
- watching. A real application might keep these for some use
- in the application. This sample only makes sure that none of
- the watch descriptors is less than 0.
- */
- int wd;
- /* Watch all events (IN_ALL_EVENTS) for the directories and
- files passed in as arguments.
- Read the article for why you might want to alter this for
- more efficient inotify use in your app.
- */
- int index;
- wd = 0;
- printf("\n");
- for (index = 1; (index < argc) && (wd >= 0); index++)
- {
- wd = watch_dir (inotify_fd, argv[index], IN_ALL_EVENTS);
- }
- if (wd > 0)
- {
- /* Wait for events and process them until a
- termination condition is detected
- */
- process_inotify_events (q, inotify_fd);
- }
- printf ("\nTerminating\n");
- /* Finish up by closing the fd, destroying the queue,
- and returning a proper code
- */
- close_inotify_fd (inotify_fd);
- queue_destroy (q);
- }
- return 0;
- }
利用 inotify_init 打開文件描述符
清單 3 展示了用於創建 inotify 實例的簡單應用函數,併爲其獲得一個文件描述符。文件描述符返回給了調用者。 如果出現錯誤,返回值將爲負。
清單 3. 使用 inotify_init
- /* Create an inotify instance and open a file descriptor
- to access it */
- int open_inotify_fd ()
- {
- int fd;
- watched_items = 0;
- fd = inotify_init ();
- if (fd < 0)
- {
- perror ("inotify_init () = ");
- }
- return fd;
- }
利用 inotify_add_watch 來增加監控
有了用於 inotify 實例的文件描述符之後,就需要增加一個或多個監控。 可以使用掩碼來設置想要監控的事件。在本例當中,採用掩碼 IN_ALL_EVENTS,來監控全部的有效事件。
清單 4. 使用 inotify_add_watch
- int watch_dir (int fd, const char *dirname, unsigned long mask)
- {
- int wd;
- wd = inotify_add_watch (fd, dirname, mask);
- if (wd < 0)
- {
- printf ("Cannot add watch for \"%s\" with event mask %lX", dirname,
- mask);
- fflush (stdout);
- perror (" ");
- }
- else
- {
- watched_items++;
- printf ("Watching %s WD=%d\n", dirname, wd);
- printf ("Watching = %d items\n", watched_items);
- }
- return wd;
- }
事件處理循環
現在我們已經設置了一些監控,接下來就要等待事件。如果還存在監控,並且 keep_running 標誌沒有被信號處理程序重置,則循環會一直進行。循環進程等待事件的發生,對有效事件進行排隊,並在返回等待狀態之前並處理隊列。 在真實應用程序當中,可能會採用一個線程將事件放入隊列,而採用另一個線程處理它們,清單 5 展示了該循環。
清單 5. 事件處理循環
- int process_inotify_events (queue_t q, int fd)
- {
- while (keep_running && (watched_items > 0))
- {
- if (event_check (fd) > 0)
- {
- int r;
- r = read_events (q, fd);
- if (r < 0)
- {
- break;
- }
- else
- {
- handle_events (q);
- }
- }
- }
- return 0;
- }
等待事件
在本程序中,循環會不停地進行下去,直至發生被監控事件或者收到了中斷信號。清單 6 展示了相關代碼。
清單 6. 等待事件或中斷
- int event_check (int fd)
- {
- fd_set rfds;
- FD_ZERO (&rfds);
- FD_SET (fd, &rfds);
- /* Wait until an event happens or we get interrupted
- by a signal that we catch */
- return select (FD_SETSIZE, &rfds, NULL, NULL, NULL);
- }
讀取事件
當事件發生時,程序會依照緩存區的大小來讀取儘量多的事件,然後把這些事件放入隊列等待事件處理程序來處理。 樣例代碼對於事件量大於 16.384-byte 之類的問題不作處理。 想處理這類問題,需要在緩存末端處理局部事件。當前對名字長度所做的限制沒有問題,但是優秀的防禦式編程會檢查名字,來確保不會出現緩存區溢出。
清單 7. 讀取事件並排隊
- int read_events (queue_t q, int fd)
- {
- char buffer[16384];
- size_t buffer_i;
- struct inotify_event *pevent;
- queue_entry_t event;
- ssize_t r;
- size_t event_size, q_event_size;-
- int count = 0;
- r = read (fd, buffer, 16384);
- if (r <= 0)
- return r;
- buffer_i = 0;
- while (buffer_i < r)
- {
- /* Parse events and queue them. */
- pevent = (struct inotify_event *) &buffer[buffer_i];
- event_size = offsetof (struct inotify_event, name) + pevent-> len;
- q_event_size = offsetof (struct queue_entry, inot_ev.name) +
- pevent->len;
- event = malloc (q_event_size);
- memmove (&(event->inot_ev), pevent, event_size);
- queue_enqueue (event, q);
- buffer_i += event_size;
- count++;
- }
- printf ("\n%d events queued\n", count);
- return count;
- }
處理事件
最終,需要對事件做處理。本例中的應用程序不處理事件,只報告發生了哪些事件。如果事件結構體中有一個名字出現, 程序將報告其是目錄還是文件。在發生移動操作時,還會報告與移動或重命名事件相關的 cookie 信息。 清單 8 展示了部分代碼,包括對一些事件的處理。參見 下載 部分可獲得全部代碼。
清單 8. 處理事件
- void handle_event (queue_entry_t event)
- {
- /* If the event was associated with a filename, we will store it here */
- char *cur_event_filename = NULL;
- char *cur_event_file_or_dir = NULL;
- /* This is the watch descriptor the event occurred on */
- int cur_event_wd = event->inot_ev.wd;
- int cur_event_cookie = event->inot_ev.cookie;
- unsigned long flags;
- if (event->inot_ev.len)
- {
- cur_event_filename = event->inot_ev.name;
- }
- if ( event->inot_ev.mask & IN_ISDIR )
- {
- cur_event_file_or_dir = "Dir";
- }
- else
- {
- cur_event_file_or_dir = "File";
- }
- flags = event->inot_ev.mask &
- ~(IN_ALL_EVENTS | IN_UNMOUNT | IN_Q_OVERFLOW | IN_IGNORED );
- /* Perform event dependent handler routines */
- /* The mask is the magic that tells us what file operation occurred */
- switch (event->inot_ev.mask &
- (IN_ALL_EVENTS | IN_UNMOUNT | IN_Q_OVERFLOW | IN_IGNORED))
- {
- /* File was accessed */
- case IN_ACCESS:
- printf ("ACCESS: %s \"%s\" on WD #%i\n",
- cur_event_file_or_dir, cur_event_filename, cur_event_wd);
- break;
- /* File was modified */
- case IN_MODIFY:
- printf ("MODIFY: %s \"%s\" on WD #%i\n",
- cur_event_file_or_dir, cur_event_filename, cur_event_wd);
- break;
- /* File changed attributes */
- case IN_ATTRIB:
- printf ("ATTRIB: %s \"%s\" on WD #%i\n",
- cur_event_file_or_dir, cur_event_filename, cur_event_wd);
- break;
- /* File open for writing was closed */
- case IN_CLOSE_WRITE:
- printf ("CLOSE_WRITE: %s \"%s\" on WD #%i\n",
- cur_event_file_or_dir, cur_event_filename, cur_event_wd);
- break;
- /* File open read-only was closed */
- case IN_CLOSE_NOWRITE:
- printf ("CLOSE_NOWRITE: %s \"%s\" on WD #%i\n",
- cur_event_file_or_dir, cur_event_filename, cur_event_wd);
- break;
- /* File was opened */
- case IN_OPEN:
- printf ("OPEN: %s \"%s\" on WD #%i\n",
- cur_event_file_or_dir, cur_event_filename, cur_event_wd);
- break;
- /* File was moved from X */
- case IN_MOVED_FROM:
- printf ("MOVED_FROM: %s \"%s\" on WD #%i. Cookie=%d\n",
- cur_event_file_or_dir, cur_event_filename, cur_event_wd,
- cur_event_cookie);
- break;
- .
- . (other cases)
- .
- /* Watch was removed explicitly by inotify_rm_watch or automatically
- because file was deleted, or file system was unmounted. */
- case IN_IGNORED:
- watched_items--;
- printf ("IGNORED: WD #%d\n", cur_event_wd);
- printf("Watching = %d items\n",watched_items);
- break;
- /* Some unknown message received */
- default:
- printf ("UNKNOWN EVENT \"%X\" OCCURRED for file \"%s\" on WD #%i\n",
- event->inot_ev.mask, cur_event_filename, cur_event_wd);
- break;
- }
- /* If any flags were set other than IN_ISDIR, report the flags */
- if (flags & (~IN_ISDIR))
- {
- flags = event->inot_ev.mask;
- printf ("Flags=%lX\n", flags);
- }
- }
該例子用來舉例說明 inotify 如何工作以及能夠監控哪些事件。 您的實際需求將決定對哪些事件進行監控以及如何處理這些事件。
用法舉例
在這部分當中,我們創建一個簡單的兩級目錄結構,目錄中有一個文件, 然後運行簡單程序來舉例說明 inotify 所能監控的一些事件。 我們將在一個終端會話中啓動 inotify 樣例程序, 但是因爲他是在後臺運行的(利用 &)因此程序的輸出與我們輸入的命令會交替出現。 應該在一個終端窗口運行該程序,而在其他窗口輸入命令。清單 9 展示了簡單文件結構和空文件的創建,以及最初啓動該簡單程序時的輸出。
清單 9. 創建樣例環境
- ian@attic4:~/inotify-sample$ mkdir -p dir1/dir2
- ian@attic4:~/inotify-sample$ touch dir1/dir2/file1
- ian@attic4:~/inotify-sample$ ./inotify_test dir1/ dir1/dir2/ dir1/dir2/file1&
- [2] 8733
- ian@attic4:~/inotify-sample$
- Watching dir1/ WD=1
- Watching = 1 items
- Watching dir1/dir2/ WD=2
- Watching = 2 items
- Watching dir1/dir2/file1 WD=3
- Watching = 3 items
- ian@attic4:~/inotify-sample$
在清單 10 當中,展示了列舉 dir2 內容時的輸出。 第一個事件報告與 dir1 有關,顯示出有些東西,名字叫做 dir2 ,在與監控描述符 1 相關的被監控目錄當中被打開了。 第二個條目與監控描述符 2 有關,顯示出被監控項目(在本例中爲 dir2 )被打開了。如果正在監控目錄樹中的多個項目, 可能會經常遇到這種雙重輸出。
清單 10. 列出 dir2 的內容
- ian@attic4:~/inotify-sample$ ls dir1/dir2
- file1
- 4 events queued
- OPEN: Dir "dir2" on WD #1
- OPEN: Dir "(null)" on WD #2
- CLOSE_NOWRITE: Dir "dir2" on WD #1
- CLOSE_NOWRITE: Dir "(null)" on WD #2
在清單 11 當中,在 file1 中加入一些文字。需要再次強調對於文件以及該文件所在目錄的雙重打開,關閉,和修改事件。還要注意不是全部事件都會被立刻讀取。排隊例程被調用了3次,每次有兩個事件。如果再次運行該程序,並且每次操作相同,您未必會再次遇到這一特別情況。
清單 11. 在 file1 中加入一些文字
- ian@attic4:~/inotify-sample$ echo "Some text" >> dir1/dir2/file1
- 2 events queued
- OPEN: File "file1" on WD #2
- OPEN: File "(null)" on WD #3
- 2 events queued
- MODIFY: File "file1" on WD #2
- MODIFY: File "(null)" on WD #3
- 2 events queued
- CLOSE_WRITE: File "file1" on WD #2
- CLOSE_WRITE: File "(null)" on WD #3
在清單 12 當中,改變 file1 的屬性。我們再次得到有關被監控項目以及其所在目錄的雙重輸出。
清單 12. 改變文件屬性
- ian@attic4:~/inotify-sample$ chmod a+w dir1/dir2/file1
- 2 events queued
- ATTRIB: File "file1" on WD #2
- ATTRIB: File "(null)" on WD #3
現在將文件 file1 移動到上一級目錄 dir1 當中。在清單 13 中顯示了輸出結果。 這次沒有雙重條目。我們實際上得到了 3 個條目,每個目錄一個,文件本身一個。 注意 cookie (569) 允許將 MOVED-FROM 事件與 MOVED_TO 事件關聯起來。
清單 13. 將文件 file1 移入 dir1
- ian@attic4:~/inotify-sample$ mv dir1/dir2/file1 dir1
- 3 events queued
- MOVED_FROM: File "file1" on WD #2. Cookie=569
- MOVED_TO: File "file1" on WD #1. Cookie=569
- MOVE_SELF: File "(null)" on WD #3
現在創建一個 file1 到 file2 的硬鏈接。由於到 inode 的鏈接數量變了,我們得到針對 file1 的 ATTRIB 事件,還得到一個針對 file2 的 CREATE 事件。
清單 14. 創建硬鏈接
- ian@attic4:~/inotify-sample$ ln dir1/file1 dir1/file2
- 2 events queued
- ATTRIB: File "(null)" on WD #3
- CREATE: File "file2" on WD #1
現在將文件 file1 移入當前目錄,將其重命名爲 file3 。當前目錄沒有被監控,因此不存在與 MOVED_FROM 事件相關聯的 MOVED_TO 事件。
清單 15. 將 file1 移入不受監控的目錄當中
- ian@attic4:~/inotify-sample$ mv dir1/file1 ./file3
- 2 events queued
- MOVED_FROM: File "file1" on WD #1. Cookie=572
- MOVE_SELF: File "(null)" on WD #3
此時,dir2 是空的,因此可以移動它。注意我們得到一個關於監控描述符 2 的 IGNORED 事件,可見我們只在監控兩個項目。
清單 16. 移動 dir2
- ian@attic4:~/inotify-sample$ rmdir dir1/dir2
- 3 events queued
- DELETE: Dir "dir2" on WD #1
- DELETE_SELF: File "(null)" on WD #2
- IGNORED: WD #2
- Watching = 2 items
移動文件 file3。注意這次我們沒有得到 IGNORED 事件。爲什麼呢?爲什麼得到了關於 file 3 的 ATTRIB 事件(就是原來的 dir1/dir2/file1)?
清單 17. 刪除 file3
- ian@attic4:~/inotify-sample$ rm file3
- 1 events queued
- ATTRIB: File "(null)" on WD #3
記住我們創建了 file1 到 file2 的硬鏈接。清單 17 顯示我們還在通過監控描述符 3 來監控 file2,儘管最開始不存在文件 2!
清單 18. 仍對 file2 進行監控!
- ian@attic4:~/inotify-sample$ touch dir1/file2
- 6 events queued
- OPEN: File "file2" on WD #1
- OPEN: File "(null)" on WD #3
- ATTRIB: File "file2" on WD #1
- ATTRIB: File "(null)" on WD #3
- CLOSE_WRITE: File "file2" on WD #1
- CLOSE_WRITE: File "(null)" on WD #3
現在刪除 dir1 來監控事件級聯,因爲程序它不監控任何事,它結束了自己。
清單 19. 刪除 dir1
- ian@attic4:~/inotify-sample$ rm -rf dir1
- 8 events queued
- OPEN: Dir "(null)" on WD #1
- ATTRIB: File "(null)" on WD #3
- DELETE_SELF: File "(null)" on WD #3
- IGNORED: WD #3
- Watching = 1 items
- DELETE: File "file2" on WD #1
- CLOSE_NOWRITE: Dir "(null)" on WD #1
- DELETE_SELF: File "(null)" on WD #1
- IGNORED: WD #1
- Watching = 0 items
- Terminating
inotify 的使用情況
可將 inotify 用於多種目標。下面列舉一些可能的情況:
性能監控
您可能想確定應用程序打開最頻繁的文件是哪個。如果發現一個小文件被頻繁打開與關閉, 您可能會考慮採用內存版,或者改變應用程序來採取其他方式共享該數據。
元信息
您可能想記錄文件的附加信息,例如起始創建時間,或者最後改變該文件的用戶 id 。
安全
您可能會因爲安全原因,需要對特定文件或目錄的所有訪問進行監控。
我們的樣例代碼監控所有事件並進行報告。實際上,您可能想依據您的需要,來查看這些事件的特定子集。您可能想監控不同被監控項目的不同事件。例如,您可能想監控文件的打開與關閉事件,但對於目錄只想監控創建與刪除事件。在任何可能的時候,您可以監控您所感興趣的最小事件集。
結束語
在應用到性能監控,程序調試,以及自動化等領域時,inotify 是功能強大,高級粒度機制的 Linux 文件系統監控工具。利用本文提供的樣例代碼,您可以開始編寫用來實時記錄文件系統事件並最小化性能開銷的應用程序。