成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

inotify監(jiān)控Linux文件系統(tǒng)的必備利器

運維 系統(tǒng)運維
文件系統(tǒng)事件監(jiān)控對于從文件管理器到安全工具等多種程序來說都是必要的。對于如何整理和控制Linux文件系統(tǒng)中的事件在實際的使用中有很多方式,inotify是比較常用的一種方法。在本文中你會學習到如何使用inotify以及他的一些相關知識。

本文主要向大家介紹了如何使用inotify控制Linux文件系統(tǒng)中的事件。在具體的學習之前我們先來看看什么是inotify以及他的歷史簡介。我們還會向大家介紹inotify的具體應用情況以及使中遇到問題的解決方案。

inotify 介紹

文件系統(tǒng)事件監(jiān)控對于從文件管理器到安全工具等多種程序來說都是必要的。自 2.6.13 版本內核開始,Linux 就提供 inotify 功能,這允許監(jiān)控程序打開一個獨立文件描述符,并針對一系列特定的事件來監(jiān)控一個或多個文件或者目錄,例如打開、關閉、移動/重命名、 刪除、創(chuàng)建或者改變屬性。在以后的版本中還提供更多增強功能,因此在依賴這些特性之前請先檢查系統(tǒng)的內核版本。

在本文中,您將學會如何在簡單的監(jiān)控程序當中使用 inotify 函數。下載樣例代碼 并在系統(tǒng)當中進行編譯,來為后面的研究做準備。

歷史簡介

在 inotify 之前有 dnotify 。不幸的是,dnotify 有局限性,無法滿足用戶的需求, inotify 的優(yōu)勢如下:

Inotify 采用簡單的文件描述符,而 dnotify 需要為每個受監(jiān)控的目錄打開一個文件描述符。 這使得同時監(jiān)控多個目錄成本很高,而且還會遇到每進程文件描述符限制問題。

inotify 所采用的文件描述符通過系統(tǒng)調用獲得,并且沒有相關的設備或文件。對于 dnotify ,文件描述符與目錄關系固定,避免了相關設備未被加載的問題,這是可移動媒體的典型問題。對于 inotify ,如果受監(jiān)控文件或目錄所在的文件系統(tǒng)未被加載, 則會產生一個事件,然后該監(jiān)控會被自動移除。

Inotify 能夠監(jiān)控文件或目錄。Dnotify 監(jiān)控目錄, 因此程序員必須保持 stat 結構或者等效的數據結構,來反映目錄當中被監(jiān)控的文件, 然后在一個事件發(fā)生時,將其與當前狀態(tài)進行對比,來知曉目錄當中的條目發(fā)生了什么情況。

如前面所述,inotify 采用文件描述符,允許程序員采用標準 select 或者 poll 函數來對事件進行監(jiān)控。 這允許高效的多重 I/O 或者與 Glib 的 mainloop 集成。相比之下,dnotify 采用信號, 這使得程序員感到難度更大或者不夠流暢。 在 2.6.25 版本內核中,inotify 也增加了 Signal-drive I.O 通告功能。

用于 inotify 的 API

Inotify 提供簡單的 API ,采用最小的文件描述符并允許細粒度監(jiān)控。與 inotify 的通信通過系統(tǒng)調用實現。

inotify_init

是用于創(chuàng)建 inotify 實例的系統(tǒng)調用,并返回一個指向該實例的文件描述符。

inotify_init1

與 inotify_init 相似,并帶有附加標志。如果這些標志沒有指定,將采用與 inotify_init 相同的值。

inotify_add_watch

增加對文件或目錄的監(jiān)控并指定需要監(jiān)控哪些事件。 標志用于控制是否將事件加入到已有的監(jiān)控當中,是否只有路徑代表一個目錄才進行監(jiān)控, 是否需要追蹤符號鏈接,是否進行一次性監(jiān)控,當首次出現事件后就停止監(jiān)控。

inotify_rm_watch

從監(jiān)控列表中移除監(jiān)控項目。

read

讀取包含一個或多個事件信息的緩存。

close

關閉文件描述符,并移除所有在該描述符上的監(jiān)控。 當關于某一實例的文件描述符都關閉以后, 資源和下層的對象都將釋放,來供內核再次使用。

因此,典型的監(jiān)控程序要進行如下操作:

利用 inotify_init 打開文件描述符;

增加一個或多個監(jiān)控;

等待事件;

處理事件,然后返回并等待更多事件;

當沒有活躍的監(jiān)控時或者基于某些信號的指示,關閉文件描述符,清空,然后退出。

在下一部分中,您將看到可以監(jiān)控的事件,以及它們如何在簡單程序當中運行。最后您將看到如何進行事件監(jiān)控。

通告

當應用程序讀取一個通告時,事件的順序也被讀取到緩存中。事件在一個變長結構體中被返回,見清單 1 。如果數據占滿了緩存,可能需要對最后一個條目進行局部事件信息或者局部名處理。

清單 1. 用于 inotify 的事件結構體

  1. struct inotify_event  
  2. {  
  3. int wd; /* Watch descriptor. */  
  4. uint32_t mask; /* Watch mask. */  
  5. uint32_t cookie; /* Cookie to synchronize two events. */  
  6. uint32_t len; /* Length (including NULs) of name. */  
  7. char name __flexarr; /* Name. */  
  8. }; 

注意,只有當監(jiān)控對象是一個目錄并且事件與目錄內部相關項目有關,而與目錄本身無關時,才提供 name 字段。 如果 IN_MOVED_FROM 事件與相應的 IN_MOVED_TO 事件都與被監(jiān)控的項目有關,cookie 就可用于將兩者關聯起來。 事件類型在掩碼字段中返回,并伴隨著能夠被內核設置的標志。 例如,如果事件與目錄有關,則標志 IN_ISDIR 將由內核設置。

能夠監(jiān)控的事件

有幾種事件能夠被監(jiān)控。有一些,比如 IN_DELETE_SELF 只應用到正在被監(jiān)控的項目,然而另一些比如 IN_ATTRIB 或者 IN_OPEN 可以應用到監(jiān)控過的項目, 或者如果該項目是目錄,則可以應用到其所包含的目錄或文件。

IN_ACCESS

被監(jiān)控項目或者被監(jiān)控目錄當中的條目被訪問過。例如,一個打開的文件被讀取。

IN_MODIFY

被監(jiān)控項目或者被監(jiān)控目錄當中的條目被修改過。例如,一個打開的文件被修改。

IN_ATTRIB

被監(jiān)控項目或者被監(jiān)控目錄當中條目的元數據被修改過。例如,時間戳或者許可被修改。

IN_CLOSE_WRITE

一個打開的,等待寫入的文件或目錄被關閉。

IN_CLOSE_NOWRITE

一個以只讀方式打開的文件或目錄被關閉。

IN_CLOSE

是可以很便捷地對前面提到的兩個關閉事件(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)進行邏輯或操作的掩碼。

IN_OPEN

文件或目錄被打開。

IN_MOVED_FROM

被監(jiān)控項目或者被監(jiān)控目錄當中的條目被移出監(jiān)控區(qū)域。該事件還包含一個 cookie 來實現 IN_MOVED_FROM 與 IN_MOVED_TO 的關聯。

IN_MOVED_TO

文件或目錄被移入監(jiān)控區(qū)域。該事件包含一個針對 IN_MOVED_FROM 的 cookie 。如果文件或目錄只是被重命名,將能看到這兩個事件,如果它只是被移入或移出非監(jiān)控區(qū)域,將只能看到一個事件。 如果移動或重命名一個被監(jiān)控項目,監(jiān)控將繼續(xù)進行。參見下面的 IN_MOVE-SELF 。

IN_MOVE

是可以很便捷地對前面提到的兩個移動事件(IN_MOVED_FROM | IN_MOVED_TO)進行邏輯或操作的掩碼。

IN_CREATE

在被監(jiān)控目錄當中創(chuàng)建了子目錄或文件。

IN_DELETE

被監(jiān)控目錄當中有子目錄或文件被刪除。

IN_DELETE_SELF

被監(jiān)控項目本身被刪除。監(jiān)控被終止并收到一個 IN_IGNORED 事件。

IN_MOVE_SELF

監(jiān)控項目本身被移動。

除了事件標志以外,還可以在 inotify 頭文件(/usr/include/sys/inotify.h)中找到其他幾個標志。 例如,如果只想監(jiān)控第一個事件,可以在增加監(jiān)控時設置 IN_ONESHOT 標志。#p#

inotify 簡單應用

這里的簡單應用遵循以上的通用邏輯。 我們使用一個信號處理程序來監(jiān)控 ctrl-c(SIGINT)并且 重置一個標志(keep_running)使應用了解終止操作。 真實的 inotify 調用在 utility 例程當中完成。注意, 我們還創(chuàng)建了一個隊列,這樣能夠將事件從 inotify 底層對象中清除,留著稍后處理。在真實的應用當中,您可能希望用其他(具有更高優(yōu)先級)的線程來完成這一操作。 這里的列舉的應用程序,只是為了對一般原理進行舉例說明。我們采用了一個簡單的事件鏈表, 隊列中的每一條目都包含原始事件加上用于存儲指向隊列中下一事件指針的空間。

主程序

清單 2 中展示了信號處理程序和主程序。在本例當中,對所有在命令行中出現過的文件或目錄進行監(jiān)控, 并利用事件掩碼 IN_ALL_EVENTS 來監(jiān)控每一對象的所有事件。 在真實的應用程序中,您可能只希望追蹤文件與目錄的創(chuàng)建或刪除事件,因此您可以掩去打開、關閉以及屬性改變事件。 如果您對文件或目錄的重命名和移動不感興趣,您也可以掩去各種移動事件。關于更多細節(jié),參見 inotify 幫助信息。

清單 2. inotify-test.c 的簡單主程序

  1. /* Signal handler that simply resets a flag to cause termination */  
  2. void signal_handler (int signum)  
  3. {  
  4. keep_running = 0;  
  5. }  
  6. int main (int argc, char **argv)  
  7. {  
  8. /* This is the file descriptor for the inotify watch */  
  9. int inotify_fd;  
  10. keep_running = 1;  
  11. /* Set a ctrl-c signal handler */  
  12. if (signal (SIGINT, signal_handler) == SIG_IGN)  
  13. {  
  14. /* Reset to SIG_IGN (ignore) if that was the prior state */  
  15. signal (SIGINT, SIG_IGN);  
  16. }  
  17. /* First we open the inotify dev entry */  
  18. inotify_fd = open_inotify_fd ();  
  19. if (inotify_fd > 0)  
  20. {  
  21. /* We will need a place to enqueue inotify events,  
  22. this is needed because if you do not read events  
  23. fast enough, you will miss them. This queue is   
  24. probably too small if you are monitoring something  
  25. like a directory with a lot of files and the directory   
  26. is deleted.  
  27. */  
  28. queue_t q;  
  29. q = queue_create (128);  
  30. /* This is the watch descriptor returned for each item we are   
  31. watching. A real application might keep these for some use   
  32. in the application. This sample only makes sure that none of  
  33. the watch descriptors is less than 0.  
  34. */  
  35. int wd;  
  36. /* Watch all events (IN_ALL_EVENTS) for the directories and   
  37. files passed in as arguments.  
  38. Read the article for why you might want to alter this for   
  39. more efficient inotify use in your app.   
  40. */  
  41. int index;  
  42. wd = 0;  
  43. printf("\n");  
  44. for (index = 1; (index < argc) && (wd >= 0); index++)   
  45. {  
  46. wd = watch_dir (inotify_fd, argv[index], IN_ALL_EVENTS);  
  47. }  
  48. if (wd > 0)   
  49. {  
  50. /* Wait for events and process them until a   
  51. termination condition is detected  
  52. */  
  53. process_inotify_events (q, inotify_fd);  
  54. }  
  55. printf ("\nTerminating\n");  
  56. /* Finish up by closing the fd, destroying the queue,  
  57. and returning a proper code  
  58. */  
  59. close_inotify_fd (inotify_fd);  
  60. queue_destroy (q);  
  61. }  
  62. return 0;  

利用 inotify_init 打開文件描述符

清單 3 展示了用于創(chuàng)建 inotify 實例的簡單應用函數,并為其獲得一個文件描述符。文件描述符返回給了調用者。 如果出現錯誤,返回值將為負。

清單 3. 使用 inotify_init

  1. /* Create an inotify instance and open a file descriptor  
  2. to access it */  
  3. int open_inotify_fd ()  
  4. {  
  5. int fd;  
  6. watched_items = 0;  
  7. fd = inotify_init ();  
  8. if (fd < 0)  
  9. {  
  10. perror ("inotify_init () = ");  
  11. }  
  12. return fd;  

利用 inotify_add_watch 來增加監(jiān)控

有了用于 inotify 實例的文件描述符之后,就需要增加一個或多個監(jiān)控。 可以使用掩碼來設置想要監(jiān)控的事件。在本例當中,采用掩碼 IN_ALL_EVENTS,來監(jiān)控全部的有效事件。

清單 4. 使用 inotify_add_watch

  1. int watch_dir (int fd, const char *dirname, unsigned long mask)  
  2. {  
  3. int wd;  
  4. wd = inotify_add_watch (fd, dirname, mask);  
  5. if (wd < 0)  
  6. {  
  7. printf ("Cannot add watch for \"%s\" with event mask %lX", dirname,  
  8. mask);  
  9. fflush (stdout);  
  10. perror (" ");  
  11. }  
  12. else  
  13. {  
  14. watched_items++;  
  15. printf ("Watching %s WD=%d\n", dirname, wd);  
  16. printf ("Watching = %d items\n", watched_items);   
  17. }  
  18. return wd;  

#p#事件處理循環(huán)

現在我們已經設置了一些監(jiān)控,接下來就要等待事件。如果還存在監(jiān)控,并且 keep_running 標志沒有被信號處理程序重置,則循環(huán)會一直進行。循環(huán)進程等待事件的發(fā)生,對有效事件進行排隊,并在返回等待狀態(tài)之前并處理隊列。 在真實應用程序當中,可能會采用一個線程將事件放入隊列,而采用另一個線程處理它們,清單 5 展示了該循環(huán)。

清單 5. 事件處理循環(huán)

  1. int process_inotify_events (queue_t q, int fd)  
  2. {  
  3. while (keep_running && (watched_items > 0))  
  4. {  
  5. if (event_check (fd) > 0)  
  6. {  
  7. int r;  
  8. r = read_events (q, fd);  
  9. if (r < 0)  
  10. {  
  11. break;  
  12. }  
  13. else  
  14. {  
  15. handle_events (q);  
  16. }  
  17. }  
  18. }  
  19. return 0;  

等待事件

在本程序中,循環(huán)會不停地進行下去,直至發(fā)生被監(jiān)控事件或者收到了中斷信號。清單 6 展示了相關代碼。

清單 6. 等待事件或中斷

  1. int event_check (int fd)  
  2. {  
  3. fd_set rfds;  
  4. FD_ZERO (&rfds);  
  5. FD_SET (fd, &rfds);  
  6. /* Wait until an event happens or we get interrupted   
  7. by a signal that we catch */  
  8. return select (FD_SETSIZE, &rfds, NULL, NULL, NULL);  

讀取事件

當事件發(fā)生時,程序會依照緩存區(qū)的大小來讀取盡量多的事件,然后把這些事件放入隊列等待事件處理程序來處理。 樣例代碼對于事件量大于 16.384-byte 之類的問題不作處理。 想處理這類問題,需要在緩存末端處理局部事件。當前對名字長度所做的限制沒有問題,但是優(yōu)秀的防御式編程會檢查名字,來確保不會出現緩存區(qū)溢出。

清單 7. 讀取事件并排隊

  1. int read_events (queue_t q, int fd)  
  2. {  
  3. char buffer[16384];  
  4. size_t buffer_i;  
  5. struct inotify_event *pevent;  
  6. queue_entry_t event;  
  7. ssize_t r;  
  8. size_t event_size, q_event_size;-  
  9. int count = 0;  
  10. r = read (fd, buffer, 16384);  
  11. if (r <= 0)  
  12. return r;  
  13. buffer_i = 0;  
  14. while (buffer_i < r)  
  15. {  
  16. /* Parse events and queue them. */  
  17. pevent = (struct inotify_event *) &buffer[buffer_i];  
  18. event_size = offsetof (struct inotify_event, name) + pevent->
    len;  
  19. q_event_size = offsetof (struct queue_entry, inot_ev.name) +   
  20. pevent->len;  
  21. event = malloc (q_event_size);  
  22. memmove (&(event->inot_ev), pevent, event_size);  
  23. queue_enqueue (event, q);  
  24. buffer_i += event_size;  
  25. count++;  
  26. }  
  27. printf ("\n%d events queued\n", count);  
  28. return count;  

處理事件

最終,需要對事件做處理。本例中的應用程序不處理事件,只報告發(fā)生了哪些事件。如果事件結構體中有一個名字出現, 程序將報告其是目錄還是文件。在發(fā)生移動操作時,還會報告與移動或重命名事件相關的 cookie 信息。 清單 8 展示了部分代碼,包括對一些事件的處理。參見 下載 部分可獲得全部代碼。

清單 8. 處理事件

  1. void handle_event (queue_entry_t event)  
  2. {  
  3. /* If the event was associated with a filename, we will 
    store it here */  
  4. char *cur_event_filename = NULL;  
  5. char *cur_event_file_or_dir = NULL;  
  6. /* This is the watch descriptor the event occurred on */  
  7. int cur_event_wd = event->inot_ev.wd;  
  8. int cur_event_cookie = event->inot_ev.cookie;  
  9. unsigned long flags;  
  10. if (event->inot_ev.len)  
  11. {  
  12. cur_event_filename = event->inot_ev.name;  
  13. }  
  14. if ( event->inot_ev.mask & IN_ISDIR )  
  15. {  
  16. cur_event_file_or_dir = "Dir";  
  17. }  
  18. else   
  19. {  
  20. cur_event_file_or_dir = "File";  
  21. }  
  22. flags = event->inot_ev.mask &   
  23. ~(IN_ALL_EVENTS | IN_UNMOUNT | IN_Q_OVERFLOW | IN_IGNORED );  
  24. /* Perform event dependent handler routines */  
  25. /* The mask is the magic that tells us what file operation 
    occurred */  
  26. switch (event->inot_ev.mask &   
  27. (IN_ALL_EVENTS | IN_UNMOUNT | IN_Q_OVERFLOW | IN_IGNORED))  
  28. {  
  29. /* File was accessed */  
  30. case IN_ACCESS:  
  31. printf ("ACCESS: %s \"%s\" on WD #%i\n",  
  32. cur_event_file_or_dir, cur_event_filename, cur_event_wd);  
  33. break;  
  34. /* File was modified */  
  35. case IN_MODIFY:  
  36. printf ("MODIFY: %s \"%s\" on WD #%i\n",  
  37. cur_event_file_or_dir, cur_event_filename, cur_event_wd);  
  38. break;  
  39. /* File changed attributes */  
  40. case IN_ATTRIB:  
  41. printf ("ATTRIB: %s \"%s\" on WD #%i\n",  
  42. cur_event_file_or_dir, cur_event_filename, cur_event_wd);  
  43. break;  
  44. /* File open for writing was closed */  
  45. case IN_CLOSE_WRITE:  
  46. printf ("CLOSE_WRITE: %s \"%s\" on WD #%i\n",  
  47. cur_event_file_or_dir, cur_event_filename, cur_event_wd);  
  48. break;  
  49. /* File open read-only was closed */  
  50. case IN_CLOSE_NOWRITE:  
  51. printf ("CLOSE_NOWRITE: %s \"%s\" on WD #%i\n",  
  52. cur_event_file_or_dir, cur_event_filename, cur_event_wd);  
  53. break;  
  54. /* File was opened */  
  55. case IN_OPEN:  
  56. printf ("OPEN: %s \"%s\" on WD #%i\n",  
  57. cur_event_file_or_dir, cur_event_filename, cur_event_wd);  
  58. break;  
  59. /* File was moved from X */  
  60. case IN_MOVED_FROM:  
  61. printf ("MOVED_FROM: %s \"%s\" on WD #%i. Cookie=%d\n",  
  62. cur_event_file_or_dir, cur_event_filename, cur_event_wd,   
  63. cur_event_cookie);  
  64. break;  
  65. .  
  66. . (other cases)  
  67. .  
  68. /* Watch was removed explicitly by inotify_rm_watch or 
    automatically  
  69. because file was deleted, or file system was unmounted. */  
  70. case IN_IGNORED:  
  71. watched_items--;  
  72. printf ("IGNORED: WD #%d\n", cur_event_wd);  
  73. printf("Watching = %d items\n",watched_items);   
  74. break;  
  75. /* Some unknown message received */  
  76. default:  
  77. printf ("UNKNOWN EVENT \"%X\" OCCURRED for file \"%s\" on WD #%i\n",  
  78. event->inot_ev.mask, cur_event_filename, cur_event_wd);  
  79. break;  
  80. }  
  81. /* If any flags were set other than IN_ISDIR, report the flags */  
  82. if (flags & (~IN_ISDIR))  
  83. {  
  84. flags = event->inot_ev.mask;  
  85. printf ("Flags=%lX\n", flags);  
  86. }  

該例子用來舉例說明 inotify 如何工作以及能夠監(jiān)控哪些事件。 您的實際需求將決定對哪些事件進行監(jiān)控以及如何處理這些事件。#p#

用法舉例

在這部分當中,我們創(chuàng)建一個簡單的兩級目錄結構,目錄中有一個文件, 然后運行簡單程序來舉例說明 inotify 所能監(jiān)控的一些事件。 我們將在一個終端會話中啟動 inotify 樣例程序, 但是因為他是在后臺運行的(利用 &)因此程序的輸出與我們輸入的命令會交替出現。 應該在一個終端窗口運行該程序,而在其他窗口輸入命令。清單 9 展示了簡單文件結構和空文件的創(chuàng)建,以及最初啟動該簡單程序時的輸出。

清單 9. 創(chuàng)建樣例環(huán)境

  1. ian@attic4:~/inotify-sample$ mkdir -p dir1/dir2  
  2. ian@attic4:~/inotify-sample$ touch dir1/dir2/file1  
  3. ian@attic4:~/inotify-sample$ ./inotify_test dir1/ 
    dir1/dir2/ dir1/dir2/file1&  
  4. [2] 8733  
  5. ian@attic4:~/inotify-sample$   
  6. Watching dir1/ WD=1 
  7. Watching = 1 items  
  8. Watching dir1/dir2/ WD=2 
  9. Watching = 2 items  
  10. Watching dir1/dir2/file1 WD=3 
  11. Watching = 3 items  
  12. ian@attic4:~/inotify-sample$  

在清單 10 當中,展示了列舉 dir2 內容時的輸出。 第一個事件報告與 dir1 有關,顯示出有些東西,名字叫做 dir2 ,在與監(jiān)控描述符 1 相關的被監(jiān)控目錄當中被打開了。 第二個條目與監(jiān)控描述符 2 有關,顯示出被監(jiān)控項目(在本例中為 dir2 )被打開了。如果正在監(jiān)控目錄樹中的多個項目, 可能會經常遇到這種雙重輸出。

清單 10. 列出 dir2 的內容

  1. ian@attic4:~/inotify-sample$ ls dir1/dir2  
  2. file1  
  3. 4 events queued  
  4. OPEN: Dir "dir2" on WD #1  
  5. OPEN: Dir "(null)" on WD #2  
  6. CLOSE_NOWRITE: Dir "dir2" on WD #1  
  7. CLOSE_NOWRITE: Dir "(null)" on WD #2 

在清單 11 當中,在 file1 中加入一些文字。需要再次強調對于文件以及該文件所在目錄的雙重打開,關閉,和修改事件。還要注意不是全部事件都會被立刻讀取。排隊例程被調用了3次,每次有兩個事件。如果再次運行該程序,并且每次操作相同,您未必會再次遇到這一特別情況。

清單 11. 在 file1 中加入一些文字

  1. ian@attic4:~/inotify-sample$ echo "Some text" >> dir1/dir2/file1  
  2. 2 events queued  
  3. OPEN: File "file1" on WD #2  
  4. OPEN: File "(null)" on WD #3  
  5. 2 events queued  
  6. MODIFY: File "file1" on WD #2  
  7. MODIFY: File "(null)" on WD #3  
  8. 2 events queued  
  9. CLOSE_WRITE: File "file1" on WD #2  
  10. CLOSE_WRITE: File "(null)" on WD #3 

在清單 12 當中,改變 file1 的屬性。我們再次得到有關被監(jiān)控項目以及其所在目錄的雙重輸出。

清單 12. 改變文件屬性

  1. ian@attic4:~/inotify-sample$ chmod a+w dir1/dir2/file1  
  2. 2 events queued  
  3. ATTRIB: File "file1" on WD #2  
  4. ATTRIB: File "(null)" on WD #3 

現在將文件 file1 移動到上一級目錄 dir1 當中。在清單 13 中顯示了輸出結果。 這次沒有雙重條目。我們實際上得到了 3 個條目,每個目錄一個,文件本身一個。 注意 cookie (569) 允許將 MOVED-FROM 事件與 MOVED_TO 事件關聯起來。

清單 13. 將文件 file1 移入 dir1

  1. ian@attic4:~/inotify-sample$ mv dir1/dir2/file1 dir1  
  2. 3 events queued  
  3. MOVED_FROM: File "file1" on WD #2. Cookie=569 
  4. MOVED_TO: File "file1" on WD #1. Cookie=569 
  5. MOVE_SELF: File "(null)" on WD #3 

現在創(chuàng)建一個 file1 到 file2 的硬鏈接。由于到 inode 的鏈接數量變了,我們得到針對 file1 的 ATTRIB 事件,還得到一個針對 file2 的 CREATE 事件。

清單 14. 創(chuàng)建硬鏈接

  1. ian@attic4:~/inotify-sample$ ln dir1/file1 dir1/file2  
  2. 2 events queued  
  3. ATTRIB: File "(null)" on WD #3  
  4. CREATE: File "file2" on WD #1 

現在將文件 file1 移入當前目錄,將其重命名為 file3 。當前目錄沒有被監(jiān)控,因此不存在與 MOVED_FROM 事件相關聯的 MOVED_TO 事件。

清單 15. 將 file1 移入不受監(jiān)控的目錄當中

  1. ian@attic4:~/inotify-sample$ mv dir1/file1 ./file3  
  2. 2 events queued  
  3. MOVED_FROM: File "file1" on WD #1. Cookie=572 
  4. MOVE_SELF: File "(null)" on WD #3 

此時,dir2 是空的,因此可以移動它。注意我們得到一個關于監(jiān)控描述符 2 的 IGNORED 事件,可見我們只在監(jiān)控兩個項目。

清單 16. 移動 dir2

  1. ian@attic4:~/inotify-sample$ rmdir dir1/dir2  
  2. 3 events queued  
  3. DELETE: Dir "dir2" on WD #1  
  4. DELETE_SELF: File "(null)" on WD #2  
  5. IGNORED: WD #2  
  6. Watching = 2 items 

移動文件 file3。注意這次我們沒有得到 IGNORED 事件。為什么呢?為什么得到了關于 file 3 的 ATTRIB 事件(就是原來的 dir1/dir2/file1)?

清單 17. 刪除 file3

  1. ian@attic4:~/inotify-sample$ rm file3  
  2. 1 events queued  
  3. ATTRIB: File "(null)" on WD #3 

記住我們創(chuàng)建了 file1 到 file2 的硬鏈接。清單 17 顯示我們還在通過監(jiān)控描述符 3 來監(jiān)控 file2,盡管最開始不存在文件 2!

清單 18. 仍對 file2 進行監(jiān)控!

  1. ian@attic4:~/inotify-sample$ touch dir1/file2  
  2. 6 events queued  
  3. OPEN: File "file2" on WD #1  
  4. OPEN: File "(null)" on WD #3  
  5. ATTRIB: File "file2" on WD #1  
  6. ATTRIB: File "(null)" on WD #3  
  7. CLOSE_WRITE: File "file2" on WD #1  
  8. CLOSE_WRITE: File "(null)" on WD #3 

現在刪除 dir1 來監(jiān)控事件級聯,因為程序它不監(jiān)控任何事,它結束了自己。

清單 19. 刪除 dir1

  1. ian@attic4:~/inotify-sample$ rm -rf dir1  
  2. 8 events queued  
  3. OPEN: Dir "(null)" on WD #1  
  4. ATTRIB: File "(null)" on WD #3  
  5. DELETE_SELF: File "(null)" on WD #3  
  6. IGNORED: WD #3  
  7. Watching = 1 items  
  8. DELETE: File "file2" on WD #1  
  9. CLOSE_NOWRITE: Dir "(null)" on WD #1  
  10. DELETE_SELF: File "(null)" on WD #1  
  11. IGNORED: WD #1  
  12. Watching = 0 items  
  13. Terminating 

inotify 的使用情況

可將 inotify 用于多種目標。下面列舉一些可能的情況:

性能監(jiān)控

您可能想確定應用程序打開最頻繁的文件是哪個。如果發(fā)現一個小文件被頻繁打開與關閉, 您可能會考慮采用內存版,或者改變應用程序來采取其他方式共享該數據。

元信息

您可能想記錄文件的附加信息,例如起始創(chuàng)建時間,或者最后改變該文件的用戶 id 。

安全

您可能會因為安全原因,需要對特定文件或目錄的所有訪問進行監(jiān)控。

我們的樣例代碼監(jiān)控所有事件并進行報告。實際上,您可能想依據您的需要,來查看這些事件的特定子集。您可能想監(jiān)控不同被監(jiān)控項目的不同事件。例如,您可能想監(jiān)控文件的打開與關閉事件,但對于目錄只想監(jiān)控創(chuàng)建與刪除事件。在任何可能的時候,您可以監(jiān)控您所感興趣的最小事件集。

結束語

在應用到性能監(jiān)控,程序調試,以及自動化等領域時,inotify 是功能強大,高級粒度機制的 Linux 文件系統(tǒng)監(jiān)控工具。利用本文提供的樣例代碼,您可以開始編寫用來實時記錄文件系統(tǒng)事件并最小化性能開銷的應用程序。

【編輯推薦】

  1. Linux inotify使用安裝創(chuàng)建設備
  2. 四大Linux文件系統(tǒng)在2.6.34內核下的基準測試
  3. 下一代Linux文件系統(tǒng)將如何發(fā)展?
  4. Linux文件系統(tǒng)組織結構簡說分析結構
責任編輯:張浩 來源: IBMDW
相關推薦

2010-05-07 15:40:18

ibmdwLinux

2010-11-04 10:16:11

inotify監(jiān)控Linux文件系統(tǒng)

2009-10-28 12:05:32

linux監(jiān)控技術

2011-01-13 14:10:30

Linux文件系統(tǒng)

2020-07-22 14:53:06

Linux系統(tǒng)虛擬文件

2017-04-20 14:55:36

LinuxPyinotifyPython

2021-06-06 16:55:22

Linux文件系統(tǒng)

2021-04-12 05:44:44

Linux文件系統(tǒng)

2020-09-25 07:48:12

Linux系統(tǒng)文件

2011-01-11 10:29:35

Linux文件

2012-05-10 13:49:44

Linux文件系統(tǒng)

2009-12-22 15:12:33

Linux擴展文件系統(tǒng)

2009-12-25 09:58:46

linux劃分文件系統(tǒng)

2009-12-14 13:14:57

2021-11-01 13:38:55

Linux文件系統(tǒng)

2011-01-13 13:18:38

Linux網絡文件

2019-09-20 10:04:45

Linux系統(tǒng)虛擬文件

2018-08-24 10:10:25

Linux文件系統(tǒng)技術

2020-01-15 09:10:13

LinuxWindowsmacOS

2021-05-31 07:50:59

Linux文件系統(tǒng)
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 少妇无套高潮一二三区 | 日韩成人免费视频 | 九九热视频这里只有精品 | 久久久久久久久久爱 | 国产精品视频一区二区三区四区国 | 国产午夜av片 | 国产精品久久久久久久久动漫 | 久久中文网 | 99视频免费 | 99国内精品久久久久久久 | 久久99深爱久久99精品 | 成人免费视频一区 | 一区二区在线免费观看 | 国产免费色 | 天天干夜夜操 | 91久久精品国产91久久 | 亚洲国产成人av好男人在线观看 | 精品国产青草久久久久96 | 日本一区二区三区免费观看 | 日韩精品一区二区三区久久 | 综合久久综合久久 | 精品一区二区三区在线观看国产 | 91.xxx.高清在线 | 免费的av网站| 国产成人精品一区二区在线 | 国产色网站 | 亚洲视频手机在线 | 一级毛片免费完整视频 | 激情的网站 | 国产精品女人久久久 | 91精品国产欧美一区二区成人 | 成人一区二 | 色香婷婷 | 一区二区三区视频在线观看 | 成人在线免费视频 | 性福视频在线观看 | 亚洲不卡在线观看 | 国产一区二区在线视频 | 中文字幕成人免费视频 | 热久久久 | 日韩精品在线播放 |