Linux inotify 接口使用

概述

 inotify系列接口是为了实现监听文件系统的变化而开发的。inotify功能可以监听文件夹或者文件,如果被监听的对象是文件夹,那么除了可以监听文件夹本身的事件外(例如IN_DELETE_SELF),也会监听位于其内部的文件事件(例如IN_CREATE)。

基本概念

 对于大脑来说还是具象化的东西容易理解容易和记忆。但是生活中为了更加高效的传递信息就必须去冗余也就是抽象化,因为越抽象其所能表示的信息则越广泛。

  • watch
     一个监听对象,例如一个文件夹或者一个文件。成功调用inotify_add_watch接口后就会生成一个watch的文件句柄,并会将其加入inotify instant中去。
  • inotify instant
     是所有watch的入口点,所有watch的事件都通过read该instant获取。在成功调用inotify_init接口后被创建。
  • inotify_event
     用于记录文件系统中的事件变化。其定义如下
struct inotify_event {
  int      wd;       /* Watch descriptor */
  uint32_t mask;     /* Mask describing event */
  uint32_t cookie;   /* Unique cookie associating related
                        events (for rename(2)) */
  uint32_t len;      /* Size of name field */
  char     name[];   /* Optional null-terminated name */
};

API

 inotify提供的api则是非常的简洁。

  • inotify_init()
     初始化一个inotify instant并且返回一个已分配好inotify事件队列的inotify文件句柄,后面所有挂载其下的watch都通过read接口去读取改文件句柄获取事件。
  • inotify_add_watch()
     用于添加一个watch到已经初始化的inotify instant中去。成功调用后则会返回一个非零的该watch文件句柄。
  • inotify_rm_watch
     从一个inotify instant中删除一个watch。

应用例子

  • inotifyTest.c
/**
 * 
 * usage:
 *   ./argv[1] <watch1> 
*/
#include <stdio.h>
#include <sys/inotify.h>
#include <unistd.h>
#include <string.h>

#define PATH_INDEX      1


struct consoleCmd{
    int argc;
    char** argv;
};

struct watchInfo{
    int fd;
    char* path;
};

#define EVT_BUF_MAX     200
struct inotifyEvtBuf{

    char buf[EVT_BUF_MAX];
    ssize_t size;
};

struct inotifyInfo{

    int inotifyFd;
    struct watchInfo wif;
    struct inotifyEvtBuf iEvtBuf;
    struct consoleCmd* ccmd;
};

void initCosoleCmd(struct inotifyInfo* ii , int argc, char** argv)
{
    struct consoleCmd* ccmd = ii->ccmd;
    if(ccmd == NULL){
        perror("The ccmd is NULL\n");
        return;
    }

    ccmd->argc = argc;
    ccmd->argv = argv;
}

uint32_t getFileMask()
{

    return (uint32_t)(IN_CREATE|IN_DELETE);
}

/**
 * Used to get watch infomation from console.
*/
void parseWatch(struct inotifyInfo* ii)
{

    ii->wif.path = ii->ccmd->argv[PATH_INDEX];
}

void initWatchFileInfo(struct inotifyInfo*ii, uint32_t watchMask)
{
    struct consoleCmd* ccmd = ii->ccmd;
    struct watchInfo* wif  = &ii->wif;

    parseWatch(ii);
    //Getting inotify instant.
    ii->inotifyFd = inotify_init();
    if(ii->inotifyFd < 0){
        perror("Getting inotify instant is fail\n");
        return;
    }
    wif->fd = inotify_add_watch(ii->inotifyFd, 
                    wif->path,  watchMask);
    if(wif->fd< 0){
        perror("Adding watch is fail.\n");
        return;
    }
}

void clearEvtBuf(struct inotifyInfo* ii)
{

    struct inotifyEvtBuf* iEvtBuf = &ii->iEvtBuf;

    memset(iEvtBuf->buf, 0, EVT_BUF_MAX);
    iEvtBuf->size = 0;
}

ssize_t monitorWatch(struct inotifyInfo* ii)
{

    clearEvtBuf(ii);
    return read(ii->inotifyFd, ii->iEvtBuf.buf, EVT_BUF_MAX);
}

void inotifyLooper(struct inotifyInfo* ii)
{
    while(monitorWatch(ii)){

            struct inotify_event* evt = (struct inotify_event*)ii->iEvtBuf.buf;

            if(evt->wd == ii->wif.fd){
                if(evt->mask&IN_CREATE){
                    printf("%s is created.\n", evt->name);
                }else if(evt->mask&IN_DELETE){
                    printf("%s is deleted\n", evt->name);
                }else{
                    printf("This operaation can't be recognizeed for %s\n", evt->name);
                }
            }
    }
}
int main(int argc, char** argv)
{   
    struct consoleCmd ccmd;
    struct inotifyInfo mInotifyInfo;
    mInotifyInfo.ccmd = &ccmd;

    initCosoleCmd(&mInotifyInfo, argc, argv);
    
    initWatchFileInfo(&mInotifyInfo, getFileMask());
    
    inotifyLooper(&mInotifyInfo);
    
    inotify_rm_watch(mInotifyInfo.inotifyFd, mInotifyInfo.wif.fd);
    return 0;
}
  • Makefile
OBJ:=inotifyTest
EXT:=c
SRC:=$(OBJ).$(EXT)
GCC=gcc

$(OBJ):$(SRC)
	$(GCC) -o $@ $^

clean:
	rm -f $(OBJ)
  • 测试
$make
$mkdir watch1
$./inotifyTest watch1/&
$touch watch1/subDir
subDir is created.
$rm -rf watch1/subDir
subDir is deleted

 可以看到在被监听的目录下已经可以跟踪文件内部的文件变化了。

gitee仓库源码

https://gitee.com/solo-king/AllTestingFromLinux/blob/master/c/examples/inotify/inotifyTest.c
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值