zoukankan      html  css  js  c++  java
  • Android系统--输入系统(一)必备的Linux知识_inotify和epoll

    Android系统--输入系统(一)必备的Linux知识_inotify和epoll

    引入

    1. 笔记本电脑插入外接键盘,两个键盘都可以使用

    a. 键盘即插即用--如何检测键盘的接入和拔出

    • hotplug机制:内核发现键盘接入或拨出之后启动hotplug进程,进程发出信号告诉输入系统,输入系统处理

    • inotify机制:输入系统使用inotify检测/dev/input的节点变化

    b. 可用使用多键盘--如何知道哪个键盘被按下

    • epoll机制:可以检测多个事件

    c. 如何使用inotify和epoll机制:

    (1) inotify使用(用于检测目录或者文件的变化)

    • 初始化得到文件句柄--fd=inotify_init();

    • 检测对象--inotify_add_watch(fd,目录/文件,创建/删除);

    • 对象变化--read();返回一个或者多个结构体:struct inotify_event

               struct inotify_event {
    
                   __s32 wd;
    
                   __u32 mask;    //发生的变化状态
    
                   __u32 cookie;
    
                   __u32 len;     //name的长度
    
                   char name[0];  //发生变化的文件
    
               }
    
    范例代码:

    inotify.c

    
     *Author  : LKQ
    
     *Date    : 2017-2-23
    
     *Desc    : use inotify watch dir change
    
     *参考: frameworks
    ativeservicesinputflingerEventHub.cpp
    
     */
    
     /*Usage: inotify <dir> */
    
     
    
    #include <unistd.h>
    
    #include <stdio.h>
    
    #include <sys/inotify.h>
    
    #include <string.h>
    
    #include <errno.h>
    
    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));  //return a struct 
    
    	
    
        if(res < (int)sizeof(*event)) {
    
            if(errno == EINTR)
    
                return 0;
    
            printf("could not get event, %s
    ", strerror(errno));
    
            return -1;
    
        }	
    
    	
    
    	//procee : read a and more inotify_event
    
    	//deal with each struct 
    
    	
    
        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[1]);
    
    	}
    
    	/*1. inotify init*/
    
        mINotifyFd = inotify_init();	
    
    	/*2. add watch*/
    
        result = inotify_add_watch(mINotifyFd, argv[1], IN_DELETE | IN_CREATE);	
    
    	/*3. read*/
    
    	while (1)
    
    	{
    
    		read_process_inotify_fd(mINotifyFd);
    
    	}
    
    	return 0;
    
    }
    
    
    使用过程:

    gcc -o inotify inotify.c

    mkdir tmp

    ./inotify tmp &

    echo > tmp/1

    echo > tmp/2

    rm tmp/1 tmp/2

    (2) epoll使用(用于检测多个文件:1. 有无数据可供读取;2. 有无空间写入)

    • 初始化得到文件句柄--fd=epoll_create();

    • 对于每一个文件执行epoll_ctl(fd,EPOLL_CRTL_ADD,...);表示监测该文件的行为

    • epoll_wait();等待某个文件可用epoll_ctl(fd,EPOLL_CRTL_DEL,...);

    范例代码:

    epoll.c

    
    /*
    
     *Author  : LKQ
    
     *Date    : 2017-2-23
    
     *Desc    :how to use epoll
    
     *参考: frameworks
    ativeservicesinputflingerEventHub.cpp
    
     */
    
    /* usage: epoll <file1> [file2] [file3] ... */
    
    #include <stdio.h>
    
    #include <sys/epoll.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 512
    
    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;
    
        }
    
    	/*1. epoll create*/
    
        mEpollFd = epoll_create(8);	
    
    	/*2.  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);
    
    	}
    
    	/*3.  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);
    
    		}
    
    	}
    
    	/*remove epoll*/
    
    	for(i=1;i<argc;i++){
    
    		rm_from_epoll(mPendingEventItems[i].data.fd,mEpollFd);
    
    	}
    
    	return 0;
    
    }
    
    
    操作方法:

    gcc -o epoll epoll.c

    mkdir tmp

    mkfifo tmp/1 tmp/2 tmp/3

    ./epoll tmp/1 tmp/2 tmp/3 &

    echo aaa > tmp/1

    echo bbb > tmp/2

    echo ccc > tmp/3

    补充:

    当fifo文件以 O_RDONLY|O_NONBLOCK 方式打开,会出现不断返回epoll_wait,导致崩溃。

    原因:使用fifo是, 我们的epoll程序是reader;echo aa > tmp/1 是writer

    a. 如果reader以 O_RDONLY|O_NONBLOCK打开FIFO文件,writer写入数据时, epoll_wait会立刻返回;
    当writer关闭FIFO之后, reader再次调用epoll_wait, 它也会立刻返回(原因是EPPLLHUP, 描述符被挂断)

    b. 如果reader以 O_RDWR打开FIFO文件当writer写入数据时, epoll_wait会立刻返回;
    当writer关闭FIFO之后, reader再次调用epoll_wait, 它并不会立刻返回, 而是继续等待有数据

  • 相关阅读:
    27. Remove Element
    26. Remove Duplicates from Sorted Array
    643. Maximum Average Subarray I
    674. Longest Continuous Increasing Subsequence
    1. Two Sum
    217. Contains Duplicate
    448. Find All Numbers Disappeared in an Array
    566. Reshape the Matrix
    628. Maximum Product of Three Numbers
    UVa 1349 Optimal Bus Route Design (最佳完美匹配)
  • 原文地址:https://www.cnblogs.com/lkq1220/p/6434184.html
Copyright © 2011-2022 走看看