如何在 rename() 過後持續使用 inotify 來監控文件?

由於工作上遇到此問題,請教了咕狗大神半天也找不太到合適的答案,只好自己研究了。

平常使用 inotify() 可以拿來監控文件的變更,最常見的就是透過 IN_CLOSE_WRITE 這個 mask 來監視,範例如下:




Net->network_ity5.ity_fd = inotify_init();

Net->network_ity5.wd = inotify_add_watch( Net->network_ity5.ity_fd, "/sysconf/conf.network", IN_CLOSE_WRITE );

Net->network_ity5.length = read( Net->network_ity5.ity_fd,  Net->network_ity5.ity_buffer, ITY_BUF_LEN );

while ( Net->network_ity5.ity_i < Net->network_ity5.length )
{
    if (event->mask & IN_CLOSE_WRITE)
    {
        ....
    }
}


某天發現,某一支程式內會針對範例的 "/sysconf/conf.network" 做 rename() 的動作,這將導致 inotify 誤認為檔案已刪除,而發出一個 mask 訊號 IN_IGNORED,告訴 inotify 不再監控,進而失去對此文件的掌控。

要避免此方法其實很簡單(當初找了老半天),只要在偵測到此訊號時,重新透過 inotify_add_watch() 來建立新的 inotify 即可。底下的範例會先將舊有的 inotify 透過 inotify_rm_watch() 移除掉,並 close(fd),然後再重新 inotify_init()、inotify_add_watch() 與 read():


while ( Net->network_ity5.ity_i < Net->network_ity5.length )
{
 struct inotify_event *event = ( struct inotify_event *) &Net->network_ity5.ity_buffer[ Net->network_ity5.ity_i ];

 /* 
  * If the file was renamed, we must close the old inotify and re-crate the inotify again. */
 if (event->mask & IN_IGNORED)
 {
  DBGPRINT(RT_DEBUG_INFO, ("inotify The file conf.network_ity5 was IN_IGNORED\n"));

  /* Remove inotify and close fd. */
  inotify_rm_watch( Net->network_ity5.ity_fd, Net->network_ity5.wd );
  close( Net->network_ity5.ity_fd );

  /* Re-init the inotify. */
  Net->network_ity5.ity_fd = inotify_init();
  if (Net->network_ity5.ity_fd < 0)
  {
   DBGPRINT(RT_DEBUG_BOSS, ("creat network_ity5 fail .. \n"));
   return -1;
  }
  /* Recreate inotify watch */
  Net->network_ity5.wd = inotify_add_watch( Net->network_ity5.ity_fd, "/sysconf/conf.network", IN_CLOSE_WRITE );

  Net->network_ity5.length = read( Net->network_ity5.ity_fd,  Net->network_ity5.ity_buffer, ITY_BUF_LEN );
  if ( Net->network_ity5.length < 0 )
  {
   perror( "network_ity5 read length < 0" );
  }

  /* Continue the while loop to re-detect the inotify. */
  continue;
 }
}



參考資料:
1. inotify介绍
2. inotify failed when /etc/hosts file change
3. Linux下使用inotify监控文件动作


PS. Blog 版面好像太小了,貼上這種大程式碼,閱讀起來有點慘不忍睹阿...


留言

這個網誌中的熱門文章

How to use ebtables: ebtable 的小筆記

解決 VirtualBox 無法開啟 NS_ERROR_FAILURE (0x80004005)