Linux-c inotify監(jiān)控目錄和文件使用


在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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市敷矫,隨后出現(xiàn)的幾起案子例获,更是在濱河造成了極大的恐慌汉额,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件榨汤,死亡現(xiàn)場離奇詭異蠕搜,居然都是意外死亡,警方通過查閱死者的電腦和手機收壕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門妓灌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蜜宪,你說我怎么就攤上這事旬渠。” “怎么了端壳?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長枪蘑。 經(jīng)常有香客問我损谦,道長,這世上最難降的妖魔是什么岳颇? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任照捡,我火速辦了婚禮,結(jié)果婚禮上话侧,老公的妹妹穿的比我還像新娘栗精。我一直安慰自己,他們只是感情好瞻鹏,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布悲立。 她就那樣靜靜地躺著,像睡著了一般新博。 火紅的嫁衣襯著肌膚如雪薪夕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天赫悄,我揣著相機與錄音原献,去河邊找鬼。 笑死埂淮,一個胖子當著我的面吹牛姑隅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播倔撞,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼讲仰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了痪蝇?” 一聲冷哼從身側(cè)響起叮盘,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤秩贰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后柔吼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體毒费,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年愈魏,在試婚紗的時候發(fā)現(xiàn)自己被綠了觅玻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡培漏,死狀恐怖溪厘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情牌柄,我是刑警寧澤畸悬,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站珊佣,受9級特大地震影響蹋宦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜咒锻,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一冷冗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惑艇,春花似錦蒿辙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至恭取,卻和暖如春习瑰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背秽荤。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工甜奄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人窃款。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓课兄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親晨继。 傳聞我的和親對象是個殘疾皇子烟阐,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容