zoukankan      html  css  js  c++  java
  • 输入系统:epoll & inotify

    一、epoll

    作用:检测一个或多个文件的可读、可写等属性变化:

    代码示例:

    #include <sys/epoll.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <string.h>
    
    
    #if 0
    typedef union epoll_data {
       void        *ptr;
       int          fd;
       uint32_t     u32;
       uint64_t     u64;
    } epoll_data_t;
    
    #endif
    
    
    #define DATA_MAX_LEN 500
    
    /* usage: epoll <file1> [file2] [file3] ... */
    
    int add_to_epoll(int fd, int epollFd)
    {
        int result;
        struct epoll_event eventItem;
        memset(&eventItem, 0, sizeof(eventItem));
        eventItem.events = EPOLLIN;
        eventItem.data.fd = fd;
        result = epoll_ctl(epollFd, EPOLL_CTL_ADD, fd, &eventItem);
        return result;
    }
    
    void rm_from_epoll(int fd, int epollFd)
    {
        epoll_ctl(epollFd, EPOLL_CTL_DEL, fd, NULL);
    }
    
    
    int main(int argc, char **argv)
    {
        int mEpollFd;
        int i;
        char buf[DATA_MAX_LEN];
    
        // Maximum number of signalled FDs to handle at a time.
        static const int EPOLL_MAX_EVENTS = 16;
    
        // The array of pending epoll events and the index of the next event to be handled.
        struct epoll_event mPendingEventItems[EPOLL_MAX_EVENTS];
    
        
        if (argc < 2)
        {
            printf("Usage: %s <file1> [file2] [file3] ...
    ", argv[0]);
            return -1;
        }
    
        /* epoll_create */
        mEpollFd = epoll_create(8);
    
        /* for each file:
         * open it
         * add it to epoll: epoll_ctl(...EPOLL_CTL_ADD...)
         */
        for (i = 1; i < argc; i++)     
        {
            //int tmpFd = open(argv[i], O_RDONLY|O_NONBLOCK);
            int tmpFd = open(argv[i], O_RDWR);
            add_to_epoll(tmpFd, mEpollFd);
        }
    
        /* epoll_wait */
        while (1)
        {
            
            int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, -1);
            for (i = 0; i < pollResult; i++)
            {
                printf("Reason: 0x%x
    ", mPendingEventItems[i].events);
                int len = read(mPendingEventItems[i].data.fd, buf, DATA_MAX_LEN);
                buf[len] = '';
                printf("get data: %s
    ", buf);
                //sleep(3);
            }
            
        }
        
        return 0;
    }

    二、inotify

    作用: 监控一个目录下文件的增加、删除事件:

    代码示例:

    #include <unistd.h>
    #include <stdio.h>
    #include <sys/inotify.h>
    #include <string.h>
    #include <errno.h>
    
    
    /*
     *参考: frameworks
    ativeservicesinputflingerEventHub.cpp
     */
    
    /*Usage: inotify <dir> */
    
    int read_process_inotify_fd(int fd)
    {
        int res;
        char event_buf[512];
        int event_size;
        int event_pos = 0;
        struct inotify_event *event;
        
        /* read */    
        res = read(fd, event_buf, sizeof(event_buf));
    
        if(res < (int)sizeof(*event)) {
            if(errno == EINTR)
                return 0;
            printf("could not get event, %s
    ", strerror(errno));
            return -1;
        }
    
        /* process
         * 读到的数据是1个或多个inotify_event
         * 它们的长度不一样
         * 逐个处理
         */
    
        while(res >= (int)sizeof(*event)) {
            event = (struct inotify_event *)(event_buf + event_pos);
            //printf("%d: %08x "%s"
    ", event->wd, event->mask, event->len ? event->name : "");
            if(event->len) {
                if(event->mask & IN_CREATE) {
                    printf("create file: %s
    ", event->name);
                } else {
                    printf("delete file: %s
    ", event->name);
                }
            }
            event_size = sizeof(*event) + event->len;
            res -= event_size;
            event_pos += event_size;
        }
        return 0;
    }
    
    int main(int argc, char **argv)
    {
        int mINotifyFd;
        int result;
    
        if (argc != 2)
        {
            printf("Usage: %s <dir>
    ", argv[0]);
            return -1;
        }
    
        /* inotify_init */
    
        mINotifyFd = inotify_init();
    
        /* add watch */
        result = inotify_add_watch(mINotifyFd, argv[1], IN_DELETE | IN_CREATE);
    
        /* read */
        while (1)
        {
            read_process_inotify_fd(mINotifyFd);
        }
    
        return 0;
    }

    三、inotify和epoll的综合应用:

    代码示例:

    #include <sys/epoll.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <string.h>
    #include <sys/inotify.h>
    #include <stdlib.h>
    #include <errno.h>
    
    
    #define DATA_MAX_LEN 500
    #define MAX_FILES 1000
    
    static char *base_dir;
    static char *epoll_files[MAX_FILES];
    
    #if 0
    typedef union epoll_data {
       void        *ptr;
       int          fd;
       uint32_t     u32;
       uint64_t     u64;
    } epoll_data_t;
    
    #endif
    
    
    
    /* usage: epoll <file1> [file2] [file3] ... */
    
    int add_to_epoll(int fd, int epollFd)
    {
        int result;
        struct epoll_event eventItem;
        memset(&eventItem, 0, sizeof(eventItem));
        eventItem.events = EPOLLIN;
        eventItem.data.fd = fd;
        result = epoll_ctl(epollFd, EPOLL_CTL_ADD, fd, &eventItem);  //添加一个文件句柄到epoll监测列表
        return result;
    }
    
    void rm_from_epoll(int fd, int epollFd)
    {
        epoll_ctl(epollFd, EPOLL_CTL_DEL, fd, NULL);
    }
    
    //通过文件名找到epoll监测列表中对应该文件的下标
    int get_epoll_fd_for_name(char *name) { int i; char name_to_find[500]; sprintf(name_to_find, "%s/%s", base_dir, name); for (i = 0; i < MAX_FILES; i++) { if (!epoll_files[i]) continue; if (!strcmp(epoll_files[i], name_to_find)) return i; } return -1; } /* *参考: frameworks ativeservicesinputflingerEventHub.cpp */ /*Usage: inotify <dir> */ int read_process_inotify_fd(int mINotifyFd, int mEpollFd) { int res; char event_buf[512]; int event_size; int event_pos = 0; struct inotify_event *event; /* read */ res = read(mINotifyFd, event_buf, sizeof(event_buf)); //返回值是一个或多个inotify_event总和大小 if(res < (int)sizeof(*event)) { if(errno == EINTR) return 0; printf("could not get event, %s ", strerror(errno)); return -1; } /* process * 读到的数据是1个或多个inotify_event * 它们的长度不一样 * 逐个处理 */ while(res >= (int)sizeof(*event)) { event = (struct inotify_event *)(event_buf + event_pos); //printf("%d: %08x "%s" ", event->wd, event->mask, event->len ? event->name : ""); if(event->len) { if(event->mask & IN_CREATE) { printf("create file: %s ", event->name); char *name = malloc(512); sprintf(name, "%s/%s", base_dir, event->name); int tmpFd = open(name, O_RDWR); printf("add to epoll: %s ", name); add_to_epoll(tmpFd, mEpollFd); epoll_files[tmpFd] = name; } else { printf("delete file: %s ", event->name); int tmpFd = get_epoll_fd_for_name(event->name); if (tmpFd >= 0) { printf("remove from epoll: %s/%s ", base_dir, event->name); rm_from_epoll(tmpFd, mEpollFd); free(epoll_files[tmpFd]); } } } event_size = sizeof(*event) + event->len; //一个event大小=结构体大小+所含数据长度 res -= event_size; event_pos += event_size; } return 0; } int main(int argc, char **argv) { int mEpollFd; int i; char buf[DATA_MAX_LEN]; int mINotifyFd; int result; // Maximum number of signalled FDs to handle at a time. static const int EPOLL_MAX_EVENTS = 16; // The array of pending epoll events and the index of the next event to be handled. struct epoll_event mPendingEventItems[EPOLL_MAX_EVENTS]; if (argc != 2) { printf("Usage: %s <tmp> ", argv[0]); return -1; } base_dir = argv[1]; /* epoll_create */ mEpollFd = epoll_create(8); //创建epoll文件句柄 /* inotify_init */ mINotifyFd = inotify_init(); //创建inotify文件句柄,可用epoll监测 /* add watch */ result = inotify_add_watch(mINotifyFd, base_dir, IN_DELETE | IN_CREATE); //设置监测inotify文件句柄 add_to_epoll(mINotifyFd, mEpollFd); //使用epoll监测inotify文件句柄 /* epoll_wait */ while (1) { int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, -1); //当文件有数据可读时返回 for (i = 0; i < pollResult; i++) { if (mPendingEventItems[i].data.fd == mINotifyFd) //当监测到的文件句柄为mINodifyFd(目录)时说明有文件创建/删除 { read_process_inotify_fd(mINotifyFd, mEpollFd); //根据event->name 添加/移除 对该文件的监测 } else { printf("Reason: 0x%x ", mPendingEventItems[i].events); int len = read(mPendingEventItems[i].data.fd, buf, DATA_MAX_LEN); buf[len] = ''; printf("get data: %s ", buf); //sleep(3); } } } return 0; }
  • 相关阅读:
    PHP常用字符串函数
    PHP 中解析 url 并得到 url 参数
    PHP中的10个实用函数
    虚拟主机知识全解
    php三种常用的加密解密算法
    Javascript中的位运算符和技巧
    ECMAScript 5中新增的数组方法
    捕捉小括号获取的内容保存在RegExp的$1 $2..属性中
    js获取浏览器窗口的大小
    关于switch的思考和总结
  • 原文地址:https://www.cnblogs.com/blogs-of-lxl/p/6416851.html
Copyright © 2011-2022 走看看