亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 1490 | 回復: 0
打印 上一主題 下一主題

使用 inotify 監(jiān)控 Linux 文件系統(tǒng)事件 [復制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2009-08-25 16:35 |只看該作者 |倒序瀏覽
Inotify 是文件系統(tǒng)事件監(jiān)控機制,計劃包含在即將發(fā)布的 Linux 內(nèi)核中作為dnotify 的有效替代。dnotify 是較早內(nèi)核支持的文件監(jiān)控機制。Inotify一種強大的、細粒度的、異步的機制,它滿足各種各樣的文件監(jiān)控需要,不僅限于安全和性能。下面讓我們一起學習如何安裝 inotify 和如何構(gòu)建一個示例用戶空間應用程序來響應文件系統(tǒng)事件。
文件系統(tǒng)事件監(jiān)控對于從文件管理器到安全工具的各種程序都是必要的,但是 dnotify(早期內(nèi)核中的標準)存在一些局限性,這使我們期待出現(xiàn)一種更加完善的機制。抱著這種期待,我們發(fā)現(xiàn)了 inotify,一種更加現(xiàn)代化的文件系統(tǒng)事件監(jiān)控替代品。

為什么使用 inotify?
使用 inotify 取代 dnotify 的原因有很多。第一個原因是,dnotify 需要您為每個打算監(jiān)控是否發(fā)生改變的目錄打開一個文件描述符。當同時監(jiān)控多個目錄時,這會消耗大量的資源,因為有可能達到每個進程的文件描述符限制。
除此之外,文件描述符會鎖定目錄,不允許卸載(unmount)支持的設備,這在存在可移動介質(zhì)的環(huán)境中會引發(fā)問題。在使用 inotify 時,如果正在監(jiān)控被卸載的文件系統(tǒng)上的文件,那么監(jiān)控會被自動移除并且您會接收到一個卸載事件。
dnotify 不如 inotify 的第二個原因是 dnotify 有點復雜。注意,使用 dnotify 基礎(chǔ)設施的簡單文件系統(tǒng)監(jiān)控粒度只停留于目錄級別。為了使用 dnotify 進行更細粒度的監(jiān)控,應用程序編程人員必須為每個受監(jiān)控的目錄保留一個 stat 結(jié)構(gòu)的緩存。該用戶空間的 stat 結(jié)構(gòu)緩存需要用來明確確定當接收到通知信號時目錄發(fā)生了什么變化。當獲得通知信號時,生成 stat 結(jié)構(gòu)列表并與最新的狀態(tài)相比較。顯而易見,這種技術(shù)是不理想的。
inotify 的另一個優(yōu)點是它使用文件描述符作為基本接口,使應用程序開發(fā)者使用 select 和 poll 來監(jiān)控設備。這允許有效的多路 I/O 和與 Glib 的 mainloop 的集成。相反,dnotify 所使用的信號常常使程序員頭疼并且感覺不太優(yōu)雅。
inotify 通過提供一個更優(yōu)雅的 API 解決了這些問題,該 API 使用最少的文件描述符,并確保更細粒度的監(jiān)控。與 inotify 的通信是通過設備節(jié)點提供的。基于以上原因,對于監(jiān)控 Linux 2.6 平臺上的文件,inotify 是您最明智的選擇。

安裝 inotify
安裝 inotify 的第一步是確定您使用的 Linux 內(nèi)核是否支持它。檢查發(fā)行版的最簡單方法是,尋找是否存在 /dev/inotify 設備。如果存在該設備,您可以跳到
在簡單應用程序中使用 inotify
一節(jié)。
在撰寫本文時,inotify 包含在 Andrew Morton 的 Linux 2.6-mm 目錄樹中,而且一些 Linux 發(fā)行版正在提供支持 inotify 的內(nèi)核(包括 Gentoo 和 Ubuntu)或者具有提供支持的補充內(nèi)核包(例如 Fedora 和 SuSE)。因為 Andrew 可能會根據(jù)需要從目錄樹刪除對 inotify 的支持,并且 inotify 版本還處于頻繁的開發(fā)階段,所以強烈建議您從頭開始打補丁。
如果缺少該設備,您可能需要對內(nèi)核打補丁并創(chuàng)建該設備。

為 inotify 對內(nèi)核打補丁
可以從 Linux Kernel Archives 獲得 inotify 補丁(請參閱
參考資料
一節(jié)的鏈接)。
您應該為特定的內(nèi)核應用最高版本編號的補丁。每個發(fā)行版處理內(nèi)核的安裝都有所不同,但以下介紹的是一個通用指導。注意:從 Linux Kernel Archives 獲取發(fā)行版 2.6 Linux 內(nèi)核源文件,如果合適,請獲取最新的穩(wěn)定版本。
從進入內(nèi)核源文件目錄開始:
bash:~$ cd /usr/src
因為您早先安裝了內(nèi)核源文件,現(xiàn)在需要將它解壓縮:
bash:~$ sudo tar jxvf linux-source-2.6.8.1.tar.bz2
現(xiàn)在,使您的 symlink 指向新的源文件目錄樹:
bash:~$ sudo ln -sf linux-source-2.6.8.1 linux
改變當前目錄到剛才創(chuàng)建的內(nèi)核源文件目錄:
bash:~$ cd linux
拷貝 inotify 補。
bash:~$ sudo cp ~/inotify* /usr/src
將內(nèi)核打補丁:
bash:~$ sudo patch -p1
構(gòu)建內(nèi)核:
bash:~$ sudo make menuconfig
像平時一樣配置您的內(nèi)核,確保 inotify 工作正常。如果必要,請將新內(nèi)核添加到引導加載程序中,但是一定要記住維護舊內(nèi)核的映像和引導加載程序選項。這一步對于不同引導加載程序有所不同(請參閱
參考資料
了解關(guān)于特定引導加載程序的更多信息)。重新引導計算機并選擇啟用 inotify 的新內(nèi)核。在繼續(xù)往下操作前,測試您的新內(nèi)核以確保它工作正常。

創(chuàng)建 inotify 設備
接下來,您需要確保創(chuàng)建 /dev/inotify 設備。以下步驟帶領(lǐng)您完成這個過程。重要注意:次設備編號可能會發(fā)生改變,所以您需要多加注意以確保它隨時更新!如果 Linux 安裝支持 udev 功能,它將會自動保持更新。
在重新引導到新內(nèi)核后,您必須獲取次設備編號:
bash:~$ dmesg | grep ^inotify
返回結(jié)果示例如下:
inotify device minor=63
因為 inotify 是 misc 設備,所以主設備編號是 10。要創(chuàng)建設備節(jié)點作為根用戶,請執(zhí)行以下命令:
bash:~$ mknod /dev/inotify c 10 63
注意:如有必要,請使用合適的次設備編號替換“63”。
您可以隨意設置您想要的權(quán)限。一個示例權(quán)限設置如下所示:
bash:~$ chown root:root /dev/inotify
bash:~$ chmod 666 /dev/inotify
現(xiàn)在準備使用 inotify 設備進行文件系統(tǒng)監(jiān)控。

在簡單應用程序中使用 inotify
為演示 inotify 的使用,我將展示如何為文件系統(tǒng)事件構(gòu)造一個監(jiān)控任意目錄(或單個文件)的示例程序。我將站在一個較高的層次上來展示 inotify 使文件系統(tǒng)監(jiān)控變得多么容易。

Main 方法
這個簡單的示例向我們展示 inotify 在任意目錄上設置監(jiān)控是多么容易。稍后我們將看到主要的幫助器例程。您可以在本文的
下載
一節(jié)獲取這些例子中使用的示例代碼。
清單 1. 在目錄上設置監(jiān)控
/* This program will take as argument a directory name and monitor it,
   printing event notifications to the console.
*/
int main (int argc, char **argv)
{
   /* This is the file descriptor for the inotify device */
   int inotify_fd;
   /* First we open the inotify dev entry */
   inotify_fd = open_inotify_dev();
   if (inotify_fd
   {
      return 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.
   */
   queue_t q;
   q = queue_create (128);
   /* Watch the directory passed in as argument
      Read on for why you might want to alter this for
      more efficient inotify use in your app.
   */
   watch_dir (inotify_fd, argv[1], ALL_MASK);
   process_inotify_events (q, inotify_fd);
   /* Finish up by destroying the queue, closing the fd,
      and returning a proper code
   */
   queue_destroy (q);
   close_inotify_dev (inotify_fd);
   return 0;
}

重要的幫助器方法
以下是每個基于 inotify 的應用程序共同的最重要的幫助器例程:
Ø         為讀取而打開 inotify 設備。
Ø         對從該設備讀取的事件進行排隊。
Ø         允許應用程序?qū)κ录ㄖM行有用處理的實際的每事件處理器。
我不會深入鉆研事件排隊的細節(jié),因為我們能夠使用一些策略來避免排隊。提供的代碼中就展示了一個這樣的方法;更先進的多線程方法可以并且已經(jīng)在其他地方實現(xiàn)。在那些實現(xiàn)中,讀者線程簡單地在 inotify 設備上執(zhí)行 select(),然后將事件拷貝到一些線程共享的存儲空間(或者一些像 Glib 的異步消息隊列的東西),以后處理器線程會處理這里的事件。
清單 2. 打開 inotify 設備
/* This simply opens the inotify node in dev (read only) */
int open_inotify_dev ()
{
   int fd;
   fd = open("/dev/inotify", O_RDONLY);
   if (fd
   {
      perror ("open(\"/dev/inotify\", O_RDONLY) = ");
   }
   return fd;
}
這對任何一個在 Linux 系統(tǒng)上進行過文件編程的人來說都應該是熟悉的。
清單 3. 實際的事件處理例程
/* This method does the dirty work of determining what happened,
   then allows us to act appropriately
*/
void handle_event (struct inotify_event *event)
{
   /* If the event was associated with a filename, we will store it here */
   char * cur_event_filename = NULL;
   /* This is the watch descriptor the event occurred on */
   int cur_event_wd = event->wd;
   if (event->len)
   {
      cur_event_filename = event->filename;
   }
   printf("FILENAME=%s\n", cur_event_filename);
        printf("\n");
   /* Perform event dependent handler routines */
   /* The mask is the magic that tells us what file operation occurred */
   switch (event->mask)
   {
      /* File was accessed */
      case IN_ACCESS:
         printf("ACCESS EVENT OCCURRED: File \"%s\" on WD #%i\n",
                 cur_event_filename, cur_event_wd);
      break;
      /* File was modified */
      case IN_MODIFY:
         printf("MODIFY EVENT OCCURRED: File \"%s\" on WD #%i\n",
                 cur_event_filename, cur_event_wd);
      break;
      /* File changed attributes */
      case IN_ATTRIB:
         printf("ATTRIB EVENT OCCURRED: File \"%s\" on WD #%i\n",
                 cur_event_filename, cur_event_wd);
      break;
      /* File was closed */
      case IN_CLOSE:
         printf("CLOSE EVENT OCCURRED: File \"%s\" on WD #%i\n",
                 cur_event_filename, cur_event_wd);
      break;
      /* File was opened */
      case IN_OPEN:
         printf("OPEN EVENT OCCURRED: File \"%s\" on WD #%i\n",
                 cur_event_filename, cur_event_wd);
      break;
      /* File was moved from X */
      case IN_MOVED_FROM:
         printf("MOVE_FROM EVENT OCCURRED: File \"%s\" on WD #%i\n",
                 cur_event_filename, cur_event_wd);
      break;
      /* File was moved to X */
      case IN_MOVED_TO:
         printf("MOVE_TO EVENT OCCURRED: File \"%s\" on WD #%i\n",
                 cur_event_filename, cur_event_wd);
      break;
      /* Subdir was deleted */
      case IN_DELETE_SUBDIR:
         printf("DELETE_SUBDIR EVENT OCCURRED: File \"%s\" on WD #%i\n",
                 cur_event_filename, cur_event_wd);
      break;
      /* File was deleted */
      case IN_DELETE_FILE:
         printf("DELETE_FILE EVENT OCCURRED: File \"%s\" on WD #%i\n",
                 cur_event_filename, cur_event_wd);
      break;
      /* Subdir was created */
      case IN_CREATE_SUBDIR:
         printf("CREATE_SUBDIR EVENT OCCURRED: File \"%s\" on WD #%i\n",
                 cur_event_filename, cur_event_wd);
      break;
      /* File was created */
      case IN_CREATE_FILE:
         printf("CREATE_FILE EVENT OCCURRED: File \"%s\" on WD #%i\n",
                 cur_event_filename, cur_event_wd);
      break;
      /* Watched entry was deleted */
      case IN_DELETE_SELF:
         printf("DELETE_SELF EVENT OCCURRED: File \"%s\" on WD #%i\n",
                 cur_event_filename, cur_event_wd);
      break;
      /* Backing FS was unmounted */
      case IN_UNMOUNT:
         printf("UNMOUNT EVENT OCCURRED: File \"%s\" on WD #%i\n",
                 cur_event_filename, cur_event_wd);
      break;
      /* Too many FS events were received without reading them
         some event notifications were potentially lost.  */
      case IN_Q_OVERFLOW:
         printf("Warning: AN OVERFLOW EVENT OCCURRED: \n");
      break;
      case IN_IGNORED:
         printf("IGNORED EVENT OCCURRED: \n");
      break;
      /* Some unknown message received */
      default:
         printf ("UNKNOWN EVENT OCCURRED for file \"%s\" on WD #%i\n",
              cur_event_filename, cur_event_wd);
      break;
   }
}
在每一條 case 語句中,您可以隨意執(zhí)行任意已實現(xiàn)并且滿足需要的方法。
至于性能監(jiān)控,您可以確定哪些文件是最經(jīng)常被讀取的和它們打開的持續(xù)時間。這種監(jiān)控非常方便,因為在某些情況下,如果文件在短時間內(nèi)被應用程序重復地讀取,它會將文件緩存在內(nèi)存中而不用返回磁盤去讀取,從而提高性能。
很容易舉出一些執(zhí)行有趣操作的特定于事件的處理器的例子。比如,如果您是在為底層文件系統(tǒng)實現(xiàn)一個元數(shù)據(jù)存儲索引,您可能會尋找文件創(chuàng)建事件,不久還會在該文件上觸發(fā)一個元數(shù)據(jù)挖掘操作。在安全環(huán)境中,如果文件被寫入一個無人可以寫入的目錄,您會觸發(fā)某些形式的系統(tǒng)警報。
請注意,inotify 支持許多非常細粒度的事件 —— 例如 CLOSE 與 CLOSE_WRITE。
本文中的代碼所列舉的許多事件,可能您并不希望在每次代碼運行時都看到。實際上,只要可能,您可以并且應該只請求對您的應用程序有用的事件子集。出于測試目的,本文章提供的代碼通過嚴格使用完整掩碼(如可下載的示例代碼[請參閱
參考資料
] 中 main 方法的第 51 行附近或者上面的
清單 1
中的第 29 行所執(zhí)行的)展示了許多事件。應用程序員通常想要有更多選擇,而您則需要更特定的掩碼來滿足您的需要。這使您可以從上述的 handle_event() 方法中的 catch 語句刪除不感興趣的條目。

結(jié)束語
當應用于性能監(jiān)控、調(diào)試和自動化領(lǐng)域時,inotify 是一種用于監(jiān)控 Linux 文件系統(tǒng)的、強大且細粒度的機制。使用本文提供的代碼,您就可以編寫能夠以最低的性能開銷響應或記錄文件系統(tǒng)事件的應用程序。

下載
描述
名字
大小
下載方法
Sample code used in this article
inotify-sample.tar
30 KB
HTTP

參考資料
獲取 Robert Love 提供的最新
Inotify 補丁


Linux Kernel Archives
獲取當前 Linux 內(nèi)核源文件目錄樹。這里是獲取 Linux 內(nèi)核源代碼的正規(guī)地點。

Event Management Best Practices
(IBM 紅皮書,2004 年 6 月)聚焦于最佳實踐,深入廣泛地理解了事件管理,并考查了事件過濾、復制檢測、相關(guān)性、通知、逐步升級、同步、故障單整合、維護模式和自動化。

Use autonomic computing for problem determination
”(developerWorks,2004 年 6 月),描述如何在 IT 系統(tǒng)中使用自治系統(tǒng)來監(jiān)控事件和診斷錯誤條件,并提供校正操作。

商業(yè)服務網(wǎng)格,第 3 部分: 設置規(guī)則
”(developerWorks,2003 年 4 月),展示了如何為服務級別定義、服務選擇、安全、錯誤恢復、
事件監(jiān)控
和服務映射配置網(wǎng)格系統(tǒng)的策略文件。

developerWorks Linux 專區(qū)
可以找到更多為 Linux 開發(fā)者準備的參考資料。
通過參與
developerWorks blogs
加入 developerWorks 社區(qū)。
在 Developer Bookstore 的 Linux 區(qū)購買
打折出售的 Linux 書籍
。
訂購免費 SEK for Linux
,這套 DVD(兩張),包含了來自 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 的用于 Linux 的最新 IBM 試用軟件。
使用
IBM 試用軟件
改革您的下一個 Linux 開發(fā)項目,可直接從 developerWorks 下載。

本文來自ChinaUnix博客,如果查看原文請點:http://blog.chinaunix.net/u2/66039/showart_2036772.html
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP