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\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的更多相关文章
- Android系统--输入系统(三)必备Linux知识_双向通信(scoketpair)
Android系统--输入系统(三)必备Linux知识_双向通信(scoketpair) 引入 1. 进程和APP通信 创建进程 读取.分发 - 进程发送输入事件给APP 进程读取APP回应的事件 输 ...
- Android系统--输入系统(二)必备Linux知识_实现inotify_epoll.c
Android系统--输入系统(二)必备Linux知识_实现inotify_epoll.c 课后作业 1. 编写 inotify_epoll.c, 用它来监测tmp/目录: 有文件被创建/删除, 有文 ...
- Android系统--输入系统(五)输入系统框架
Android系统--输入系统(五)输入系统框架 1. Android设备使用场景: 假设一个Android平板,APP功能.系统功能(开机关机.调节音量).外接设备功能(键盘.触摸屏.USB外接键盘 ...
- Android系统--输入系统(六)模拟输入驱动程序
Android系统--输入系统(六)模拟输入驱动程序 1. 回顾输入子系统 简单字符设备驱动:应用程序通过调用驱动所实现的函数使能硬件. 输入子系统:由于有多个应用程序使用输入子系统,故肯定使用的是早 ...
- Android系统--输入系统(九)Reader线程_核心类及配置文件
Android系统--输入系统(九)Reader线程_核心类及配置文件 1. Reader线程核心类--EventHub 1.1 Reader线程核心结构体 实例化对象:mEventHub--表示多个 ...
- Android系统--输入系统(十)Reader线程_核心类及配置文件深入分析
Android系统--输入系统(十)Reader线程_核心类及配置文件深入分析 0. 前言 个人认为该知识点阅读Android源代码会不仅容易走进死胡同,并且效果并不好,前脚看完后脚忘记,故进行总结, ...
- Android系统--输入系统(七)Reader_Dispatcher线程启动分析
Android系统--输入系统(七)Reader_Dispatcher线程启动分析 1. Reader/Dispatcher的引入 对于输入系统来说,将会创建两个线程: Reader线程(读取事件) ...
- Android系统--输入系统(八)Reader线程_使用EventHub读取事件
Android系统--输入系统(八)Reader线程_使用EventHub读取事件 1. Reader线程工作流程 获得事件 size_t count = mEventHub->getEvent ...
- Android系统--输入系统(十一)Reader线程_简单处理
Android系统--输入系统(十一)Reader线程_简单处理 1. 引入 Reader线程主要负责三件事情 获得输入事件 简单处理 上传给Dispatch线程 InputReader.cpp vo ...
随机推荐
- git commit --amend用法
提交信息很长时间内会一直保留在你的代码库(code base)中,所以你肯定希望通过这个信息正确地了解代码修改情况. 下面这个命令可以让你编辑最近一次的提交信息,但是你必须确保没有对当前的代码库(wo ...
- day1笔记 初识python,paython基础
一.计算机,操作系统 软件发送指令给操作系统,操作系统再把指令发送给 内存,cpu,硬盘等 二.Python的历史. Python2: 1.臃肿,源码的重复量很多.2.语法不清晰,掺杂着c,++,P ...
- python学习【第十篇】单例设计模式
单例设计模式 目的:让类创建对象,在系统中只有唯一的实例,让每一次创建的对象返回的内存地址都是相同的. __new__方法 使用类名创建对象时,python解释器首先会调用__new__方法为对象分配 ...
- 2318: Spoj4060 game with probability Problem
2318: Spoj4060 game with probability Problem Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 356 Sol ...
- 1677 treecnt(贡献)
1677 treecnt 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 给定一棵n个节点的树,从1到n标号.选择k个点,你需要选择一些边使得这k个点通过选择的边联 ...
- Storm 集群安装
http://archive.apache.org/dist/storm/ 版本都在这 本人安装的是 其他版本的自行安装吧,估计都差不多 sudo mkdir /export/serverssudo ...
- 使用 mock 测试
参考文章:https://semaphoreci.com/community/tutorials/getting-started-with-mocking-in-python What are the ...
- HTTP 状态码简介(对照)
HTTP状态码 当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求.当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应 ...
- opencv3计算机视觉+Python(四)
使用分水岭和GrabCut算法进行物体分割 用GrabCut算法进行图像分割 在OpenCV中,实现了grabcut分割算法,该算法可以方便的分割出前景图像,操作简单,而且分割的效果很好.算法的原理参 ...
- End to End 端到端
在DeepLearning的文章中有看到end2end一次,作者们似乎都比较喜欢这个end2end learning的方式.那么到底啥是end2end? 找了一下相关论文,没找到专门讲这个概念的,看来 ...