Linux下的epoll和inotify

本文最后更新于2017年8月12日,已超过 1 年没有更新,如果文章内容失效,还请反馈给我,谢谢!

=Start=

缘由:

学习、提高需要

正文:

参考解答:
#include <sys/inotify.h>
#include <sys/epoll.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <string.h>
#define MONITOR_FLAGS  IN_MOVED_FROM|IN_MOVED_TO|IN_CREATE|IN_MODIFY|IN_ATTRIB|IN_DELETE|IN_DELETE_SELF
// #define MONITOR_FLAGS  IN_ALL_EVENTS
struct inotify_data_type{
    int fd;
    char self_type[16];
};
#ifndef PATH_MAX
#define PATH_MAX 128
#endif
typedef struct {
    int fd;
    char pathname[PATH_MAX];
} inotify_fd_path;
int main(int argc, char* argv[]){
    if(argc < 2) {
        return 1;
    }
    int inotify_fd = inotify_init();
    if(inotify_fd < 0){
        printf("inotify_init() error, create inotify descriptor failed.");
        return 1;
    }
    inotify_fd_path *wd_arr = malloc(sizeof(inotify_fd_path)*(argc-1));
    int i;
    for(i = 1; i < argc; i++){
        wd_arr[i-1].fd = inotify_add_watch(inotify_fd, argv[i], MONITOR_FLAGS);
        strncpy(wd_arr[i-1].pathname, argv[i], PATH_MAX-1);
        if(wd_arr[i-1].fd < 0){
            printf("inotify_add_watch() error, could not watch dirctory : %s");
            return 1;
        }
    }
    int nb = 1;
    ioctl(inotify_fd, FIONBIO, &nb);    // 作用是?
    int epoll_fd = epoll_create(1024);
    if(epoll_fd < 0){
        printf("epoll_create() error, create epoll descriptor failed");
        return 1;
    }
    struct inotify_data_type inotify_data;
    inotify_data.fd = inotify_fd;
    strcpy(inotify_data.self_type, "inotify");
    struct epoll_event inotify_event;
    int option = EPOLL_CTL_ADD;
    inotify_event.events = EPOLLIN|EPOLLET;
    inotify_event.data.ptr = &inotify_data;
    int result = epoll_ctl(epoll_fd, option, inotify_fd, &inotify_event);
    if(result < 0){
        printf("epoll_ctl() error, could not add Inotify event in EPOLL");
        return 1;
    }
    int running = 1;
    struct epoll_event event_list[10];
    while(running){
        int events_num = epoll_wait(epoll_fd, event_list, 100);
        if(events_num < 0){
            printf("epoll_wait() failed");
            return 1;
        }
        if(events_num > 0){
            // int i = 0;
            for(i = 0; i < events_num; i++){
                struct inotify_data_type *inotify_data_backup = event_list[i].data.ptr;
                if(strcmp(inotify_data_backup->self_type, "inotify") == 0){
                    int revents = event_list[i].events;
                    if(revents & (EPOLLERR|EPOLLHUP)){
                        continue;
                    }
                    if(revents & EPOLLIN){
                        char inotify_event_buf[1024];
                        bzero(inotify_event_buf, 1024);
                        int length = read(inotify_data_backup->fd, inotify_event_buf, 1024);
                        // 理论上,下面的代码不需要使用循环
                        char *tmp;
                        int tmp_len;
                        for(tmp = inotify_event_buf, tmp_len = 0; (tmp-inotify_event_buf) < length; tmp += tmp_len){
                            struct inotify_event *iev = (struct inotify_event*)tmp;
                            int j = 0;
                            for(j = 0; j < argc-1; j++){
                                if(wd_arr[j].fd == iev->wd){
                                    // 这里的 iev->name 只有文件名,不是全文件名
                                    if(iev->mask & IN_ACCESS){
                                        printf("[IN_ACCESS]The inotify event fd(%d) referred to File=%s, whose pathname=%s\n", wd_arr[j].fd, iev->name, wd_arr[j].pathname);
                                    }
                                    if(iev->mask & IN_ATTRIB){
                                        printf("[IN_ATTRIB]The inotify event fd(%d) referred to File=%s, whose pathname=%s\n", wd_arr[j].fd, iev->name, wd_arr[j].pathname);
                                    }
                                    if(iev->mask & IN_CLOSE_WRITE){
                                        printf("[IN_CLOSE_WRITE]The inotify event fd(%d) referred to File=%s, whose pathname=%s\n", wd_arr[j].fd, iev->name, wd_arr[j].pathname);
                                    }
                                    if(iev->mask & IN_CREATE){
                                        printf("[IN_CREATE]The inotify event fd(%d) referred to File=%s, whose pathname=%s\n", wd_arr[j].fd, iev->name, wd_arr[j].pathname);
                                    }
                                    if(iev->mask & IN_MODIFY){
                                        printf("[IN_MODIFY]The inotify event fd(%d) referred to File=%s, whose pathname=%s\n", wd_arr[j].fd, iev->name, wd_arr[j].pathname);
                                    }
                                    if(iev->mask & IN_DELETE){
                                        printf("[IN_DELETE]The inotify event fd(%d) referred to File=%s, whose pathname=%s\n", wd_arr[j].fd, iev->name, wd_arr[j].pathname);
                                    }
                                }
                            }
                            tmp_len = sizeof(struct inotify_event)+iev->len;
                        }
                    }
                }
            }
        }
    }
    close(epoll_fd);
    return 0;
}
参考链接:

Difference between inotify and epoll
https://stackoverflow.com/questions/17207809/difference-between-inotify-and-epoll

epoll模型添加inotify事件的代码实现
http://blog.csdn.net/zhoushuaiyin/article/details/42639053

使用epoll + inotify监控文件
http://xinmingyao.iteye.com/blog/705984

Like tail -F but with more epoll and inotify
https://github.com/Roguelazer/einotail

=END=

声明: 除非注明,ixyzero.com文章均为原创,转载请以链接形式标明本文地址,谢谢!
https://ixyzero.com/blog/archives/3511.html

《Linux下的epoll和inotify》上有3条评论

  1. fanotify 监控文件系统(inotify 的替代)
    https://www.ibm.com/developerworks/cn/linux/l-cn-fanotify/index.html
    http://man7.org/linux/man-pages/man7/fanotify.7.html
    http://manpages.ubuntu.com/manpages/zesty/man7/fanotify.7.html

    How do I program for Linux’s new fanotify file system monitoring feature?
    https://stackoverflow.com/questions/1835947/how-do-i-program-for-linuxs-new-fanotify-file-system-monitoring-feature

    How to tell which path a fanotify event refers to
    https://stackoverflow.com/questions/13379632/how-to-tell-which-path-a-fanotify-event-refers-to

    fanotify: the fscking all notification system
    https://lwn.net/Articles/339253/

    用Golang写的跨平台文件系统监控机制(Cross-platform file system notifications for Go.)
    https://github.com/fsnotify/fsnotify

    Sophos Anti-Virus for Linux: Fanotify Overview
    https://community.sophos.com/kb/en-us/118216

    A simple fanotify example for watching events on a filesystem.
    https://github.com/NegativeMjark/fanotify

    Is fanotify supported in Red Hat Enterprise Linux?
    https://access.redhat.com/solutions/458193

发表评论

电子邮件地址不会被公开。 必填项已用*标注