zoukankan      html  css  js  c++  java
  • Android系统--输入系统(二)必备Linux知识_实现inotify_epoll.c

    Android系统--输入系统(二)必备Linux知识_实现inotify_epoll.c

    课后作业

    1. 编写 inotify_epoll.c, 用它来监测tmp/目录: 有文件被创建/删除, 有文件可读出数据

    • a. 当在tmp/下创建文件时, 会立刻监测到,并且使用epoll监测该文件

    • b. 当文件有数据时,读出数据

    • c. 当tmp/下文件被删除时,会立刻监测到,并且把它从epoll中移除不再监测

    2. 程序基本框架

    (1)初始化--初始化epoll和inotify,获取其fd

    (2)添加事件

    • 对文件夹中文件的创建和删除进行检测--inotify_add_watch(mINotifyFd, dir, IN_DELETE | IN_CREATE);

    • 将监听事件加入epoll池中,监听事件行为--add_to_epoll(mINotifyFd, mEpollFd);

    (3)等待事件发生

    • 添加、删除文件事件--read_process_inotify_fd(int mINotifyFd, int mEpollFd)

    • 往文件写入数据--read(mPendingEventItems[i].data.fd, buf, DATA_MAX_LEN);

    实现代码:
    
    #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 512
    
    #define MAX_FILES    1024
    
    
    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
    
    
    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);
    
    }
    
    
    /*函数说明:传入文件名,根据epoll_file数组指针,判断每一项指向的是否有内容,如有则比较文件名是否相同*/
    int get_epoll_fd_for_name(char *name)
    
    {
    
    	int i;
    
    	char name_to_find[512];
    
    	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;
    
    }
    
    
    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));
    
        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中
    
    				epoll_files[tmpFd] = name;       //暂时保存文件名称,用于后面释放epoll中的该事件
    
    					
    
                } else {
    
                    printf("delete file: %s
    ", event->name);  
    
    				int tmpFd = get_epoll_fd_for_name(event->name);  //利用文件名查找对应的事件fd
    
    				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;
    
            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];
    
    	//1. init
    
    	
    
    	/* 1.1  epoll_create */
    
        mEpollFd = epoll_create(8);
    
    	/* 1.2 inotify_init */
    
        mINotifyFd = inotify_init();
    
    	//2. add
    
    	/* 2.1 add watch */
    
        result = inotify_add_watch(mINotifyFd, base_dir, IN_DELETE | IN_CREATE);
    
    	/* 2.2 addto epoll*/
    
    	add_to_epoll(mINotifyFd, mEpollFd);
    
    	/* 3. 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)  //事件fd为文件添加和删除,则跳转到inotify处理函数
    
    			{
    
    				read_process_inotify_fd(mINotifyFd, mEpollFd);
    
    			}
    
    			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);
    
    			}
    
    		}
    
    		
    
    	}
    
    
    	return 0;
    }
    
    
    具体操作:
    • gcc -o inotify_epoll inotify_epoll.c

    • mkdir tmp

    • ./inotify_epoll tmp/ &

    • mkfifo tmp/1 tmp/2 tmp/3

    • echo aaa > tmp/1
      echo bbb > tmp/2
      echo ccc > tmp/3

    • rm tmp/3

  • 相关阅读:
    几个论坛上看到的2015小米笔试题
    Line(扩展欧几里得)
    MapReduce编程之倒排索引
    annotation(@Retention@Target)详解
    【JEECG技术文档】JEECG平台对外接口JWT应用文档V3.7.2
    jeecg 模糊查询
    jeecg下实现自动默认模糊查询
    The packaging for this project did not assign a file to the build artifact
    Maven添加本地Jar包
    maven 如何引入本地jar包
  • 原文地址:https://www.cnblogs.com/lkq1220/p/6435129.html
Copyright © 2011-2022 走看看