• 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, 它并不会立刻返回, 而是继续等待有数据

  • 相关阅读:
    IDEA(jetbrain通用)优雅级使用教程(转)
    intellij idea 修改背景保护色&&修改字体&&快捷键大全(转)
    淘宝可伸缩高性能互联网架构HSF(转)
    spring利用注解@Value获取properties属性为null
    String.valueOf()方法注意
    Spring任务调度器之Task的使用(转)
    Mybatis集成(转)
    深入理解mybatis原理, Mybatis初始化SqlSessionFactory机制详解(转)
    Spring+Mybatis+SpringMVC+Maven+MySql搭建实例(转)
    Spring4.2+SpringMVC+Mybatis3.4的集成(转-)
  • 原文地址:https://www.cnblogs.com/lkq1220/p/6434184.html
Copyright © 2020-2023  润新知