Linux下inotify机制简介
http://blog.csdn.net/tommy_wxie/article/details/45149921
1.inotify機制簡介:
inotify是Linux內核提供的一個文件系統變化通知機制,從2.6.13版本的內核開始提供,比如你在創建一個文件時它可以通知你哪個文件被創建了,刪除文件時通知你哪個文件被刪除了,修改文件時通知你哪個文件被修改了,關閉文件時哪個文件被關閉了,是可寫關閉還是不可寫關閉等等。這個機制在某些特定用途下是很必要的,比如桌面搜索引擎,一般當我們不記得某一文件放在哪個地方時,我們可以直接通過這個桌面搜索引擎來搜索該文件以得到其位置,在Linux下的beagle搜索引擎就是用inotify實現的;還有就是用在文件同步方面和文件的增量備份方面,當本地的文件被修改保存后可以即時的將該文件同步到遠程服務器上去。
在2.6.13版本的內核之前文件系統變化通知機制用的是dnotify,當然為了兼容以前的版本,現在的內核也還提供dnotify,inotify與dnotify相比具有很多優勢,比如inotify資源占用少,特別是表現在文件描述符這塊,inotify通過系統調用實現,而dnotify通過信號等等,具體優勢感興趣的可以自己去查查資料;在2.6.36內核版本后又提供了另一個文件系統變化通知機制fanotify用以替代inotify,fanotify機制相對于inotify又有其自己的優勢,比如通過適當設置fanotify可以阻斷你對文件進行的操作,而inotify只通知不阻斷,fanotify可以對指定目錄下的所有文件的某些變化進行通知,而inotify只能對指定目錄下的兩級目錄內的文件系統變化進行通知,即只能對指定目錄下的文件或者子目錄的變化進行通知,而對子目錄下的文件和目錄的變化探測不到,但當前fanotify能進行通知的事件較少,感覺還不完善,有興趣的可以自己去查查相關資料。
2.inotify機制能通知的事件:
以下代碼摘自include/linux/inotify.h
/* the following are legal, implemented events that user-space can watch for */
#define IN_ACCESS 0x00000001 /* File was accessed */
#define IN_MODIFY 0x00000002 /* File was modified */
#define IN_ATTRIB 0x00000004 /* Metadata changed */
#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed */
#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */
#define IN_OPEN 0x00000020 /* File was opened */
#define IN_MOVED_FROM 0x00000040 /* File was moved from X */
#define IN_MOVED_TO 0x00000080 /* File was moved to Y */
#define IN_CREATE 0x00000100 /* Subfile was created */
#define IN_DELETE 0x00000200 /* Subfile was deleted */
#define IN_DELETE_SELF 0x00000400 /* Self was deleted */
#define IN_MOVE_SELF 0x00000800 /* Self was moved */
/* the following are legal events. they are sent as needed to any watch */
#define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted */
#define IN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */
#define IN_IGNORED 0x00008000 /* File was ignored */
/* helper events */
#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* close */
#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* moves */
/* special flags */
#define IN_ONLYDIR 0x01000000 /* only watch the path if it is a directory */
#define IN_DONT_FOLLOW 0x02000000 /* don't follow a sym link */
#define IN_MASK_ADD 0x20000000 /* add to the mask of an already existing watch */
#define IN_ISDIR 0x40000000 /* event occurred against dir */
#define IN_ONESHOT 0x80000000 /* only send event once */
/*
* All of the events - we build the list by hand so that we can add flags in
* the future and not break backward compatibility. Apps will get only the
* events that they originally wanted. Be sure to add new events here!
*/
#define IN_ALL_EVENTS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE |
IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM |
IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF |
IN_MOVE_SELF)
以上所定義的常量在下面用于下面介紹的mask設置或mask值判斷
3.inotify機制用戶態接口函數:
3.1:inotify_init():創建一個inotify實例,返回值為一個文件描述符,具體可查看man手冊。
3.2:inotify_init1(...):在2.6.27版本中出現,功能更細致,用于替代inotify_init(),具體可查看man手冊。
3.3:inotify_add_watch(...):用于在inotify_init...返回的文件描述符上添加一個監控實例,具體可查看man手冊。
3.4:inotufy_rm_watch(...):用于移除指定的監控實例,具體可查看man手冊。
3.5:read(...):用于讀取發生的事件,具體可參看man手冊。
4.inotify機制事件數據結構解析:
通過read讀取到的每一個事件,其結構體定義如下:
struct inotify_event { __s32 wd; /* watch descriptor */ __u32 mask; /* watch mask */ __u32 cookie; /* cookie to synchronize two events */ __u32 len; /* length (including nulls) of name */ char name[0]; /* stub for possible name */};
此處說明一下字段len和name[0],當我們在一個監控目錄下新建一個文件file1時,會得到len=6(5+1,5代表file1長度,1代表字符串結束字符null),name指針中指向的就是file1這個字符串,該字符串緊接在讀取到的event事件后,并且以null結尾。
5.一下是我寫的一個使用inotify機制的簡短程序:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/inotify.h>
struct wd_path
{
int wd;
char *path;
};
char * event_array[] = {
"File was accessed",
"File was modified",
"File attributes were changed",
"writtable file closed",
"Unwrittable file closed",
"File was opened",
"File was moved from X",
"File was moved to Y",
"Subfile was created",
"Subfile was deleted",
"Self was deleted",
"Self was moved",
"",
"Backing fs was unmounted",
"Event queued overflowed",
"File was ignored"
};
#define EVENT_NUM 16
int main(int argc,char *argv[])
{
int fd,wd,len,tmp_len,i;
char buffer[1024],*offset,target[1024];
struct wd_path *wd_array;
struct inotify_event *event;
wd_array=(struct wd_path*)malloc((argc-1)*sizeof(struct wd_path));
fd=inotify_init();
if(-1==fd)
{
printf("failed to init inotifyn");
return 0;
}
for(i=0;i<argc-1;i++)
{
wd_array[i].path=argv[i+1];
wd=inotify_add_watch(fd,wd_array[i].path,IN_ALL_EVENTS);
wd_array[i].wd=wd;
}
memset(buffer,0,1024);
while(len=read(fd,buffer,1024))
{
offset=buffer;
event=(struct inotify_event*)buffer;
while(((char *)event-buffer)<len)
{
for(i=0;i<argc-1;i++)
{
if(event->wd==wd_array[i].wd)
{
memset(target,0,1024);
strcpy(target,wd_array[i].path);
strcat(target,"/");
strcat(target,event->name);
printf("nnntarget:%s:n",target);
}
}
for(i=0;i<EVENT_NUM;i++)
{
if(event->mask&(1<<i))
printf(" event:%sn",event_array[i]);
}
tmp_len=sizeof(struct inotify_event)+event->len;
event=(struct inotify_event*)(offset+tmp_len);
offset+=tmp_len;
}
}
return 1;
}
總結
以上是生活随笔為你收集整理的Linux下inotify机制简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 12款途观牌照灯泡是多长?
- 下一篇: 伊力特酒(伊力特酒的前世今生)