在Linux相關(guān)項目中,遇到過這樣子的需求较幌,要監(jiān)控某個目錄下文件的改動,比如新建白翻,刪除等乍炉,這時候inotify就派上用場了。
相應(yīng)頭文件是:#include <sys/inotify.h>
inotify相關(guān)API
-
int inotify_init(void)
初始化一個inotify實例滤馍,返回值是一個文件描述符岛琼,在inotify_add_watch函數(shù)中將會用到。 -
int inotify_add_watch(int fd,const char *pathname,uint32_t mask)
由名字可知巢株,增加一個監(jiān)聽槐瑞,將要監(jiān)聽的文件或者目錄添加到inotify中,其中fd是inotify初始化時候返回的文件描述符阁苞,pathname是要監(jiān)聽的文件的路徑困檩,mask是要監(jiān)聽的事件(事件有多種,比如創(chuàng)建那槽,刪除等),其返回值是一個inotify標識悼沿,用于判斷返回的事件是屬于哪一個被監(jiān)聽的文件的,還有移除監(jiān)聽文件的時候通過這個標識指定骚灸。 -
int inotify_rm_watch(int fd,uint32_t wd)
從監(jiān)聽列表中刪除一個監(jiān)聽文件/目錄显沈,fd是初始化時候返回的文件描述符,wd是監(jiān)聽的文件的標識逢唤,由inotify_add_watch函數(shù)返回拉讯。 -
int inotify_rm_watch(int fd, int wd)
移除一個文件/目錄監(jiān)控
讀取事件
讀取事件是調(diào)用系統(tǒng)read()函數(shù),其中參數(shù)為inotify初始化返回的文件描述符鳖藕,而讀取事件會返回一個inotify_event結(jié)構(gòu)體魔慷,如下:
struct inotify_event
{
int wd; /* Watch descriptor. */
unit32_t mask; /* Watch mask */
unit32_t cookie; /* Cookie to synchronize two events. */
unit32_t len; /* Length (including NULLs) of name. */
char name[]; /* Name. */
};
wd:inotify標識符(就是inotify_add_watch的返回值)
mask:事件的掩碼
cookie:文件被修改時才用到
name:就是發(fā)生改變的文件/目錄的名字
len:就是name的長度
關(guān)閉inotify監(jiān)聽
如同文件操作一樣,inotify在最后也要調(diào)用close()函數(shù)關(guān)閉監(jiān)聽著恩,參數(shù)為初始化時候返回的文件描述符院尔。
事件類型
- IN_ACCESS:文件被訪問
- IN_ATTRIB:文件屬性改變
- IN_CLOSE_WRITE:關(guān)閉打開寫的文件
- IN_CLOSE_NOWRITE:關(guān)閉不是打開寫的文件
- IN_CREATE:用于目錄,監(jiān)控的目錄中創(chuàng)建目錄或者文件時會發(fā)生
- IN_DELETE:用于目錄喉誊,監(jiān)控的目錄中刪除目錄或者文件時會發(fā)生
- IN_DELETE_SELF:監(jiān)控的目錄或文件自身被刪除
- IN_MODIFY:文件被修改邀摆,會用到上述結(jié)構(gòu)體中的cookie
- IN_MOVE_SELF:監(jiān)控的文件或目錄自身被移動
- IN_MOVED_FROM:從監(jiān)控的目錄中移出文件
- IN_MOVED_TO:往監(jiān)控的目錄中移入文件
- IN_OPEN:文件/目錄被打開
- IN_ALL_EVENTS: 包含上述所有事件,在inotify_add_watch函數(shù)中調(diào)用
Sample
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define EVENT_BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
int main(void)
{
int length, i = 0;
int fd;
int wd;
char buffer[EVENT_BUF_LEN];
//inotify初始化
fd = inotify_init();
if (fd < 0)
{
perror("inotify_init");
return -1;
}
//監(jiān)聽/mnt和/home目錄
wd = inotify_add_watch(fd, "/mnt", IN_CREATE | IN_DELETE);
printf("1.wd = %d\n",wd);
wd = inotify_add_watch(fd, "/home", IN_CREATE | IN_DELETE);
printf("2.wd = %d\n",wd);
while(1)
{
i = 0;
length = read(fd, buffer, EVENT_BUF_LEN);
if (length < 0)
{
perror("read");
continue;
}
while (i < length)
{
struct inotify_event *event = (struct inotify_event *) &buffer[i];
if (event->len)
{
if (event->mask & IN_CREATE)
{
if (event->mask & IN_ISDIR)
{
printf("New directory wd = %d .\n", event->wd);
printf("New directory %s created.\n", event->name);
}
else
{
printf("New file wd = %d .\n", event->wd);
printf("New file %s created.\n", event->name);
}
}
else if (event->mask & IN_DELETE)
{
if (event->mask & IN_ISDIR)
{
printf("Directory wd = %d deleted.\n", event->wd);
printf("Directory %s deleted.\n", event->name);
}
else
{
printf("File wd = %d deleted.\n", event->wd);
printf("File %s deleted.\n", event->name);
}
}
}
i += EVENT_SIZE + event->len;
}
}
inotify_rm_watch(fd, wd);
close(fd);
return 0;
}
注意在事件發(fā)生時候伍茄,inotify.event.name的問題栋盹,可以參考這篇博文:
https://ixyzero.com/blog/archives/3513.html