Inotify 是一個 Linux 核心特性,它監控檔案系統,並且及時向專門的應用程式發出相關的事件警告,比如刪除、讀、寫和卸載操作等。您還可以跟蹤活動的源頭和目標等細節,尤其是設定檔,修改後可以實現自動重載配置資訊,而不必要重啟。
源碼:http://download.csdn.net/detail/liuhongxiangm/6722679
inotify 幾個函數
#include <sys/inotify.h>
1、int inotify_init(void)
核心中建立一個inotify執行個體,成功返回描述符,失敗返回-1,errno判斷失敗資訊
2、int inotify_add_watch(int fd, const char*pathname, uint32_t mask)
添加監視事件,參數是inotify描述符, 要監視路徑名, 相關事件
相關事件有:
Inotify 可以監視的檔案系統事件包括:
IN_ACCESS,即檔案被訪問
IN_MODIFY,檔案被 write
IN_ATTRIB,檔案屬性被修改,如 chmod、chown、touch 等
IN_CLOSE_WRITE,可寫檔案被 close
IN_CLOSE_NOWRITE,不可寫檔案被 close
IN_OPEN,檔案被 open
IN_MOVED_FROM,檔案被移走,如 mv
IN_MOVED_TO,檔案被移來,如 mv、cp
IN_CREATE,建立新檔案
IN_DELETE,檔案被刪除,如 rm
IN_DELETE_SELF,自刪除,即一個可執行檔在執行時刪除自己
IN_MOVE_SELF,自移動,即一個可執行檔在執行時移動自己
IN_UNMOUNT,宿主檔案系統被 umount
IN_CLOSE,檔案被關閉,等同於(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
IN_MOVE,檔案被移動,等同於(IN_MOVED_FROM | IN_MOVED_TO)
3、int inotify_rm_watch(int fd, int wd)
移一個監視器
4、還需要read()讀取事件,close()關閉inotify描述符
struct inotify_event
{
int wd; /* The watch descriptor */
uint32_t mask; /* Watch mask */
uint32_t cookie; /* A cookie to tie two events together */
uint32_t len; /* The length of the filename found in the name field */
char name __flexarr; /* The name of the file, padding to the end with NULs */
}
5、使用例子
CInotify類封裝
CInotify.h
#ifndef CINOTIFY_H#define CINOTIFY_H#include <stdlib.h>#include <stdio.h>#include <sys/inotify.h>#include <pthread.h>#include <unistd.h>#include <sys/select.h>typedef void (*fun_inotify)(inotify_event *event, void *puser);class CInotify{public: CInotify(); ~CInotify(); int Init(fun_inotify callback, void *puser); int AddWatch(const char*pathname, uint32_t mask); int RemoveWatch(int wd); int Close(); friend void* WatchThread(void*);private: int WatchLoop();private: int m_fdInotify; void *m_pUser; fun_inotify m_funInotify; pthread_t m_thWatch; char *m_bufEvent;};#endif // CINOTIFY_H
CInotify.cpp
#include "cinotify.h"#define EVENT_SIZE (sizeof(struct inotify_event))#define BUF_LEN (1024*(EVENT_SIZE+16))void* WatchThread(void* p);void* WatchThread(void* p){ CInotify *thiz = (CInotify*)p; thiz->WatchLoop(); return 0;}CInotify::CInotify(){ m_fdInotify = -1; m_pUser = NULL; m_funInotify = NULL; m_thWatch = -1; m_bufEvent = NULL;}CInotify::~CInotify(){ m_fdInotify = -1; m_pUser = NULL; m_funInotify = NULL; m_thWatch = -1; m_bufEvent = NULL;}int CInotify::Init(fun_inotify callback, void *puser){ m_bufEvent = new char[BUF_LEN]; m_funInotify = callback; m_pUser = puser; m_fdInotify = inotify_init(); if(m_fdInotify < 0) { return -1; } //create watch thread if( pthread_create(&m_thWatch, NULL,WatchThread, this) < 0) { close(m_fdInotify); return -1; } return m_fdInotify;}int CInotify::AddWatch(const char*pathname, uint32_t mask){ return inotify_add_watch(m_fdInotify, pathname, mask);}int CInotify::RemoveWatch(int wd){ return inotify_rm_watch(m_fdInotify, wd);}int CInotify::Close(){ if(m_fdInotify != -1) { close(m_fdInotify); m_fdInotify = -1; } if(m_thWatch != -1) { pthread_cancel(m_thWatch); pthread_join(m_thWatch, NULL); m_thWatch = -1; } return 0;}int CInotify::WatchLoop(){ fd_set rfd; struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; while(true) { int retval; FD_ZERO(&rfd); FD_SET(m_fdInotify,&rfd); retval = select(m_fdInotify+1, &rfd, NULL, NULL, &tv); if(retval == 0) { continue; } else if(retval == -1) { return -1; } int len = read(m_fdInotify,m_bufEvent, BUF_LEN); int index = 0; while(index < len) { inotify_event *event = (inotify_event*)&m_bufEvent[index]; { //call back if(m_funInotify != NULL) { m_funInotify(event,m_pUser); } index += EVENT_SIZE + event->len; } } } return 0;}
main.cpp
#include <iostream>#include <errno.h>#include <stdio.h>#include "cinotify.h"using namespace std;void inotify(inotify_event *event, void *puser){ if ( event->mask & IN_CREATE ) { if ( event->mask & IN_ISDIR ) { printf( "The directory %s was created.\n", event->name ); } else { printf( "The file %s was created.\n", event->name ); } } if ( event->mask & IN_DELETE ) { if ( event->mask & IN_ISDIR ) { printf( "The directory %s was deleted.\n", event->name ); } else { printf( "The file %s was deleted.\n", event->name ); } } if ( event->mask & IN_MODIFY ) { if ( event->mask & IN_ISDIR ) { printf( "The directory %s was modified.\n", event->name ); } else { printf( "The file %s was modified.\n", event->name ); } } if ( event->mask & IN_ACCESS ) { if ( event->mask & IN_ISDIR ) { printf( "The directory %s was access.\n", event->name ); } else { printf( "The file %s was access.\n", event->name ); } }}int main(){ int iret = 0; CInotify notify; iret = notify.Init(&inotify, NULL); iret = notify.AddWatch("log.txt", IN_MODIFY|IN_ACCESS); if(iret < 0) { perror("inotify error"); } getchar(); notify.Close(); return 0;}