libevent+inotify实现配置文件实时读取

8 篇文章 0 订阅

有些配置文件需要被频繁使用,但是又需要支持根据“场景”进行模式切换。如果每次都重新读取势必影响服务响应效率,折衷的方式是定时重新读取,比如5分钟。但最好的方式是在真正需要的时候在重新读取,即,文件修改之后。

那么如何得知所关注的文件已经被修改?

Inotify 是一个 Linux特性,它监控文件系统操作,比如读取、写入和创建。Inotify 反应灵敏,用法非常简单,并且比 cron 任务的繁忙轮询高效得多。可以监控一个目录或指定的文件。

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)

注:上述事件,目录和文件同样适用。

 

下面使用libevent+inotify来实现文件修改通知。为了定时输出监控文件的内容,我增加了一个定时事件,在定时回调中输出目标文件的内容。 

主要测试代码:

static void show_file()
{
//*
// 受监控的文件
    const char* file_path = "./settings/other/checkModify.txt";
    ifstream ifs;
    ifs.open(file_path, ios::binary);
    if (!ifs.is_open()) {
        cout<<"file open failed!!!"<<endl;
        return;
    }
    
    // 定位到流末尾以获得长度;
    ifs.seekg(0, ifs.end);
    int length = ifs.tellg();
    // 再定位到开始处进行读取;
    ifs.seekg(0, ifs.beg);
 
    // 定义一个buffer;
    char *buffer = new char[length];
    // 将数据读入buffer;
    ifs.read(buffer, length);

    cout<<buffer<<endl;

    delete[] buffer;
    ifs.close();
    //*/
}
// timer callback  定时展示文件内容
void on_timer(int sock, short event, void *arg)
{
    cout << "---In timer callback---" << endl;
    show_file();
    struct timeval tv;
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    // 重新添加定时事件(定时事件触发后默认自动删除)
    event_add((struct event*)arg, &tv);
    cout << "---Timer callback end---" << endl;
}

 

// 捕获到文件状态改变时的回调
void watch_notify_events(int fd, short events, void *arg)
{
    cout<<"---In watch_notify_events---"<<endl;
    char buf[512];
    int rc;
    struct inotify_event *inotify_ev = NULL;
  
    rc = read(fd, buf, sizeof(buf));
  
    inotify_ev = (struct inotify_event *)buf;
    if (inotify_ev == NULL)
        return;
  
    if(inotify_ev->mask & IN_MODIFY)
    {
        cout<<"file modifiy"<<endl;
        show_file();
    }
}

 

// 主函数
int main()
{
    /// inotify
    int inotify_fd;
    inotify_fd = inotify_init();
    if (inotify_fd < 0) {
        cout<<"init inotify error"<<endl;
        return -1;
    }

    int wd;
    const char* notify_path = "./settings/other";
    wd = inotify_add_watch(inotify_fd, notify_path, IN_MODIFY);

    // 初始化
    event_init();

    struct event evTimer;
    // 设置定时事件
    evtimer_set(&evTimer, on_timer, &evTimer);

    struct timeval tv;
    tv.tv_sec = 5;
    tv.tv_usec = 0;
    // 添加定时事件
    event_add(&evTimer, &tv);

    // add inotify event
    struct event evNotify;
    event_set(&evNotify, inotify_fd, EV_READ | EV_PERSIST, watch_notify_events, NULL);

    event_add(&evNotify, NULL);


    // 事件循环
    event_dispatch();

    int rc;
    rc = inotify_rm_watch(inotify_fd, wd);
    if (rc < 0) {
        cout<<"remove file error"<<endl;
        return -2;
    }
    close(inotify_fd);

    return 0;
}

 执行情况如下:

 代码正常运行需要libevent库的支持,需先完成安装,编译时增加 -levent参数。目标文件初始化内容为“Not Modifyed!!!”,修改后内容为“Now it’s Modifyed!!!”,修改过程中IN_MODIFY文件状态所产生的信号事件通过Inotify机制捕捉到后,经过libevent事件分发到对应的回调函数进行处理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值