Android系统--输入系统(二)必备Linux知识_实现inotify_epoll.c
Android系统--输入系统(二)必备Linux知识_实现inotify_epoll.c
课后作业
1. 编写 inotify_epoll.c, 用它来监测tmp/目录: 有文件被创建/删除, 有文件可读出数据
a. 当在tmp/下创建文件时, 会立刻监测到,并且使用epoll监测该文件
b. 当文件有数据时,读出数据
c. 当tmp/下文件被删除时,会立刻监测到,并且把它从epoll中移除不再监测
2. 程序基本框架
(1)初始化--初始化epoll和inotify,获取其fd
(2)添加事件
对文件夹中文件的创建和删除进行检测--inotify_add_watch(mINotifyFd, dir, IN_DELETE | IN_CREATE);
将监听事件加入epoll池中,监听事件行为--add_to_epoll(mINotifyFd, mEpollFd);
(3)等待事件发生
添加、删除文件事件--read_process_inotify_fd(int mINotifyFd, int mEpollFd)
往文件写入数据--read(mPendingEventItems[i].data.fd, buf, DATA_MAX_LEN);
实现代码:
#include <sys/epoll.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/inotify.h>
#include <stdlib.h>
#include <errno.h>
#define DATA_MAX_LEN 512
#define MAX_FILES 1024
static char *base_dir;
static char *epoll_files[MAX_FILES];
#if 0
typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
#endif
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);
}
/*函数说明:传入文件名,根据epoll_file数组指针,判断每一项指向的是否有内容,如有则比较文件名是否相同*/
int get_epoll_fd_for_name(char *name)
{
int i;
char name_to_find[512];
sprintf(name_to_find, "%s/%s", base_dir, name);
for (i = 0; i < MAX_FILES; i++)
{
if (!epoll_files[i])
continue;
if (!strcmp(epoll_files[i], name_to_find))
return i;
}
return -1;
}
int read_process_inotify_fd(int mINotifyFd, int mEpollFd)
{
int res;
char event_buf[512];
int event_size;
int event_pos = 0;
struct inotify_event *event;
/* read */
res = read(mINotifyFd, event_buf, sizeof(event_buf));
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
* 它们的长度不一样
* 逐个处理
*/
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);
char *name = malloc(512);
sprintf(name, "%s/%s", base_dir, event->name);
int tmpFd = open(name, O_RDWR); //如有创建文件,则打开
printf("add to epoll: %s\n", name);
add_to_epoll(tmpFd, mEpollFd); //将读取写入文件的事件加入epoll中
epoll_files[tmpFd] = name; //暂时保存文件名称,用于后面释放epoll中的该事件
} else {
printf("delete file: %s\n", event->name);
int tmpFd = get_epoll_fd_for_name(event->name); //利用文件名查找对应的事件fd
if (tmpFd >= 0)
{
printf("remove from epoll: %s/%s\n", base_dir, event->name);
rm_from_epoll(tmpFd, mEpollFd);
free(epoll_files[tmpFd]);
}
}
}
event_size = sizeof(*event) + event->len;
res -= event_size;
event_pos += event_size;
}
return 0;
}
int main(int argc,char **argv)
{
int mEpollFd;
int i;
char buf[DATA_MAX_LEN];
int mINotifyFd;
int result;
// 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 <tmp>\n",argv[0]);
return -1;
}
base_dir = argv[1];
//1. init
/* 1.1 epoll_create */
mEpollFd = epoll_create(8);
/* 1.2 inotify_init */
mINotifyFd = inotify_init();
//2. add
/* 2.1 add watch */
result = inotify_add_watch(mINotifyFd, base_dir, IN_DELETE | IN_CREATE);
/* 2.2 addto epoll*/
add_to_epoll(mINotifyFd, mEpollFd);
/* 3. epoll_wait */
while (1)
{
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, -1);
for (i = 0; i < pollResult; i++)
{
if (mPendingEventItems[i].data.fd == mINotifyFd) //事件fd为文件添加和删除,则跳转到inotify处理函数
{
read_process_inotify_fd(mINotifyFd, mEpollFd);
}
else
{
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);
}
}
}
return 0;
}
具体操作:
gcc -o inotify_epoll inotify_epoll.c
mkdir tmp
./inotify_epoll tmp/ &
mkfifo tmp/1 tmp/2 tmp/3
echo aaa > tmp/1
echo bbb > tmp/2
echo ccc > tmp/3rm tmp/3
Android系统--输入系统(二)必备Linux知识_实现inotify_epoll.c的更多相关文章
- Android系统--输入系统(三)必备Linux知识_双向通信(scoketpair)
Android系统--输入系统(三)必备Linux知识_双向通信(scoketpair) 引入 1. 进程和APP通信 创建进程 读取.分发 - 进程发送输入事件给APP 进程读取APP回应的事件 输 ...
- Android系统--输入系统(一)必备的Linux知识_inotify和epoll
Android系统--输入系统(一)必备的Linux知识_inotify和epoll 引入 1. 笔记本电脑插入外接键盘,两个键盘都可以使用 a. 键盘即插即用--如何检测键盘的接入和拔出 hotpl ...
- Android系统--输入系统(十二)Dispatch线程_总体框架
Android系统--输入系统(十二)Dispatch线程_总体框架 1. Dispatch线程框架 我们知道Dispatch线程是分发之意,那么便可以引入两个问题:1. 发什么;2. 发给谁.这两个 ...
- 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 ...
随机推荐
- WinRAR 5.01 正式版 (简体中文)附注册机及注册码
软件分类:数据压缩软件大小:1.91 MB 软件类别:国外软件 软件授权:注册版软件语言:简体中文点击进入:官方主页 应用平台:Win 8.Win 7.Win 2008 R2.Win 2008.Wi ...
- day13迭代器与生成器
三个作业: # 1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码 login_dic = {'alex':False} def ...
- Docker学习(2Docker基本命令 )
1.首先我们需要明确在docker中需要了解的一些基础知识 Docker虚拟化有三个概念需要理解,分别镜像.容器.仓库. 1) 镜像:docker的镜像其实就是模板,跟我们常见的ISO镜像类似,是一个 ...
- [Docker]学习笔记--搭建gitlab
Gitlab 是一个用于仓库管理系统的开源项目.使用Git作为代码管理工具,并在此基础上搭建起来的web服务. 详细介绍可以参照官网,https://about.gitlab.com/ 今天主要是通过 ...
- [CTSC1999][网络流24题] 星际转移
36. [CTSC1999][网络流24题] 星际转移 ★★★☆ 输入文件:home.in 输出文件:home.out 简单对比时间限制:1 s 内存限制:128 MB «问题描述: ...
- 【BZOJ1930】[Shoi2003]pacman 吃豆豆 最大费用最大流
[BZOJ1930][Shoi2003]pacman 吃豆豆 Description 两个PACMAN吃豆豆.一开始的时候,PACMAN都在坐标原点的左下方,豆豆都在右上方.PACMAN走到豆豆处就会 ...
- 【BZOJ1190】[HNOI2007]梦幻岛宝珠 分层背包DP
[BZOJ1190][HNOI2007]梦幻岛宝珠 Description 给你N颗宝石,每颗宝石都有重量和价值.要你从这些宝石中选取一些宝石,保证总重量不超过W,且总价值最大为,并输出最大的总价值. ...
- Linux安装mysql8.*
分别在Linux和windows上安装mysql8.* 环境 CentOS7 安装mysql8 步骤: window下的Navicat 连接MySql8: 第一部分 CentOS7安装mysql8 1 ...
- Java工程师面试题整理[社招篇]
http://blog.csdn.net/jackfrued/article/details/44921941 1.面向对象的特征有哪些方面?2.访问修饰符public,private,protect ...
- VS中没有为此解决方案配置选中要生成的项目
菜单->生成->配置管理器->给要生成的项目打钩