inotify和epoll机制
来源:互联网 发布:java 集合不加泛型 编辑:程序博客网 时间:2024/06/06 09:40
假设你买了一台笔记本,但是你嫌它自带的键盘不好用,于是你买了个键盘,这样你可以两个键盘同时使用,这里面涉及了什么呢?
- 键盘即插即用
a) 那么怎么检测键盘的接入和拔出,两种机制- Hotplug机制:内核发现键盘接入/拔出->启动hotplug进程->消息传入输入系统,这种机制非常复杂,Android并不使用这种机制
- Inotift:输入系统使用inotify检测一个目录“/dev/input”
- 可使用多键盘同时使用
a) 怎么知道哪个键盘被按下:使用epoll,只要一有数据这个epoll就能读取到
Inotify的使用
功能:检测目录/文件的变化
- fd = inotify_init()
- inotify_add_watch(目录/文件,创建/删除)
- read(fd ) 无文件发生变化则休眠,有文件发生变化则返回,返回一个或多个结构体,结构体内容如下:
struct inotify_event { __s32 wd; /* watch descriptor */ __u32 mask; /* watch mask */ __u32 cookie; /* cookie to synchronize two events */ __u32 len; /* length (including nulls) of name */ char name[0]; /* stub for possible name */};
inotify代码:
/* * 参考: frameworks\native\services\inputflinger\EventHub.cpp */#include <unistd.h>#include <stdio.h>#include <sys/inotify.h>#include <string.h>#include <errno.h> /* Usage: inotify <dir> */ 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));//读到的数据放入event_buf /* 如果一个event都没有的话返回错误 */ if(res < (int)sizeof(*event)) { if(errno == EINTR) return 0; printf("could not get event, %s\n", strerror(errno)); return -1; } /* process * 读到的数据是1个或多个inotify_event * 它们的长度不一样 * 逐个处理 */ /* 逐个取出event_buf里面的inotify_event */ 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[0]); return -1; } /* inotify_init */ mINotifyFd = inotify_init(); /* add watch */ /* 检测哪个目录, 检测它是否有删除文件(IN_DELETE)或创建文件(IN_CREATE) */ result = inotify_add_watch(mINotifyFd, argv[1], IN_DELETE | IN_CREATE); /* read */ while (1) { /* 读数据 */ read_process_inotify_fd(mINotifyFd); } return 0; }
测试:
gcc -o inotify inotify.c /* 编译 */
mkdir tmp /* 创建tmp这个目录 */
./inotify tmp & /* 检测tmp这个目录 */
echo > tmp/1 /* 在tmp目录下创建文件1 */
echo > tmp/2 /* 在tmp目录下创建文件2 */
rm tmp/1 tmp/2 /* 删除这两个文件 */
效果:
epoll的使用
功能:用来监测多个文件(有无数据供读出、有无空间供写入)
- epoll_create(创建fd)
- 对每个文件,执行epoll_ctl(…, epoll_ctl_add, …),表示要检测它
- 执行epoll_wait(等待某个文件可用)
- 不再想检测某个文件:epoll_ctl(…, epoll_ctl_del, …)
epoll代码:
#include <sys/epoll.h>#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <string.h>#define DATA_MAX_LEN 500/* usage: epoll <file1> [file2] [file3] ... */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;/* 监测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. /* 每次调用epoll_wait最多可以得到16个事件,可以再次调用,可以监测多个文件 */ 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; } /* epoll_create */ mEpollFd = epoll_create(8); /* 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); } /* epoll_wait */ while (1) { //-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);//从 mPendingEventItems[i].data.fd 读到的数据放到 buf 里面 buf[len] = '\0'; printf("get data: %s\n", buf); //sleep(3); } } 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
效果:
总结:
android使用inotify来检测驱动目录,从而知道某个键盘被插入拔出,使用epoll来检测目录下的文件,从而知道某个键盘是否有数据
阅读全文
0 0
- inotify和epoll机制
- inotify和epoll结合使用的小例子
- inotify机制
- Inotify机制
- linux 系统调用 inotify & epoll
- inotify + epoll实现热插拔检测
- Linux文件系统Inotify机制
- [文件系统]Inotify机制介绍
- Linux文件系统Inotify机制
- linux inotify通知机制
- inotify通知机制
- dnotify机制与inotify机制
- epoll机制和libevent库学习
- epoll机制
- epoll机制
- epoll机制
- epoll机制
- epoll机制
- 优化知识,利用ViewStub类来延迟加载视图 延迟加载和避免重复渲染视图
- Activity生命周期
- HDMI中SCL和SDA两个引脚的作用
- python快速入门
- Ubuntu 16.04安装Mysql5.7修改root密码
- inotify和epoll机制
- 经验积累-内存泄漏
- 剑指offer-重建二叉树(java版)
- jquery 一个form的数据传给另一个form
- 1003 Hangover
- jar包内容修改并重新打包方法
- C++中拷贝构造函数与拷贝赋值操作符
- UVA 10976 数论 枚举
- RuntimeError: Working outside of application context.