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\native\services\inputflinger\EventHub.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\n", 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\"\n", event->wd, event->mask, event->len ? event->name : ""); if(event->len) { if(event->mask & IN_CREATE) { printf("create file: %s\n", event->name); } else { printf("delete file: %s\n", 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> \n",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\native\services\inputflinger\EventHub.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] ...\n", 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\n", mPendingEventItems[i].events); int len = read(mPendingEventItems[i].data.fd, buf, DATA_MAX_LEN); buf[len] = '\0'; printf("get data: %s\n", 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, 它并不会立刻返回, 而是继续等待有数据

Android系统--输入系统(一)必备的Linux知识_inotify和epoll的更多相关文章

  1. Android系统--输入系统(三)必备Linux知识_双向通信(scoketpair)

    Android系统--输入系统(三)必备Linux知识_双向通信(scoketpair) 引入 1. 进程和APP通信 创建进程 读取.分发 - 进程发送输入事件给APP 进程读取APP回应的事件 输 ...

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

    Android系统--输入系统(二)必备Linux知识_实现inotify_epoll.c 课后作业 1. 编写 inotify_epoll.c, 用它来监测tmp/目录: 有文件被创建/删除, 有文 ...

  3. Android系统--输入系统(五)输入系统框架

    Android系统--输入系统(五)输入系统框架 1. Android设备使用场景: 假设一个Android平板,APP功能.系统功能(开机关机.调节音量).外接设备功能(键盘.触摸屏.USB外接键盘 ...

  4. Android系统--输入系统(六)模拟输入驱动程序

    Android系统--输入系统(六)模拟输入驱动程序 1. 回顾输入子系统 简单字符设备驱动:应用程序通过调用驱动所实现的函数使能硬件. 输入子系统:由于有多个应用程序使用输入子系统,故肯定使用的是早 ...

  5. Android系统--输入系统(九)Reader线程_核心类及配置文件

    Android系统--输入系统(九)Reader线程_核心类及配置文件 1. Reader线程核心类--EventHub 1.1 Reader线程核心结构体 实例化对象:mEventHub--表示多个 ...

  6. Android系统--输入系统(十)Reader线程_核心类及配置文件深入分析

    Android系统--输入系统(十)Reader线程_核心类及配置文件深入分析 0. 前言 个人认为该知识点阅读Android源代码会不仅容易走进死胡同,并且效果并不好,前脚看完后脚忘记,故进行总结, ...

  7. Android系统--输入系统(七)Reader_Dispatcher线程启动分析

    Android系统--输入系统(七)Reader_Dispatcher线程启动分析 1. Reader/Dispatcher的引入 对于输入系统来说,将会创建两个线程: Reader线程(读取事件) ...

  8. Android系统--输入系统(八)Reader线程_使用EventHub读取事件

    Android系统--输入系统(八)Reader线程_使用EventHub读取事件 1. Reader线程工作流程 获得事件 size_t count = mEventHub->getEvent ...

  9. Android系统--输入系统(十一)Reader线程_简单处理

    Android系统--输入系统(十一)Reader线程_简单处理 1. 引入 Reader线程主要负责三件事情 获得输入事件 简单处理 上传给Dispatch线程 InputReader.cpp vo ...

随机推荐

  1. LINQ 标准查询操作符

    本文介绍了LINQ标准查询操作符.没有这些操作符,LINQ就不会存在.本文为理解这些操作符的功能提供了很好的基础.了解它们将会很有帮助,因为LINQ的各种Provider都是基于这些操作符来完成各自丰 ...

  2. poj 2125(最小割)

    题目链接:http://poj.org/problem?id=2125 思路:将最小点权覆盖转化为最小割模型,于是拆点建图,将点i拆成i,i+n,其中vs与i相连,边容量为w[i]-,i+n与vt相连 ...

  3. js事件绑定的方法

    废话不多少,直接上代码 第一种 <body> <div style="width:400px;height:400px;background:blueviolet" ...

  4. jprofiler_监控远程linux服务器的JVM进程(转 非常棒)

    几天前写了一篇文章,jprofiler_监控远程linux服务器的tomcat进程(实践),介绍了使用jprofiler怎样监控远程linux的tomcat进程,这两天想了想,除了可以监控tomcat ...

  5. 【BZOJ3083/3306】遥远的国度/树 树链剖分+线段树

    [BZOJ3083]遥远的国度 Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了 ...

  6. Salty Fish(区间和)

    Problem 2253 Salty Fish Accept: 35    Submit: 121Time Limit: 1000 mSec    Memory Limit : 32768 KB Pr ...

  7. 在前端眼中pc端和移动的开发区别

    按照昨天所说,本包子今天将总结在前端开发中,pc端和移动端的区别,整理完这些区别,本包子将开始整理pc端的布局,会写实际的代码了,还是那句话,希望文章中有什么不足的地方,大家能多多指正,大家一起进步, ...

  8. 不恰当使用线程池处理 MQ 消息引起的故障

    现状 业务部门反应网站访问特别慢,负责运维监控的同事说MQ消息队列积压了,中间件的说应用服务器内存占用很高,GC 一直回收不了内存,GC 线程占了近 100% 的 CPU,其他的基本上都在等待,数据库 ...

  9. Introduction to Mathematical Thinking - Week 3

    there exists and all there exists 证明根号2是无理数 all 习题 3. Which of the following formal propositions say ...

  10. TreeMap详细介绍(源码解析)和使用示例

    本文转自 http://www.cnblogs.com/skywang12345/p/3310928.html 概要 这一章,我们对TreeMap进行学习.我们先对TreeMap有个整体认识,然后再学 ...