Linux inotify + Epoll实现机制
首先学习Inotify机制,就是Linux系统下对文件目录的监听,如果目录下有文件创建删除都可以被监听到,那这个有什么作用呢?
在Android Input系统中可以实现对设备热插拔的监听。我们先看一个简单的Demo
#include<stdio.h>
#include<assert.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<sys/inotify.h>
#include<limits.h>
#include<fcntl.h> #define BUF_LEN 1000 void displayEvent(struct inotify_event* tempEvent)
{printf("mask = %d\n",tempEvent->mask); //判断有哪些事件发生if(tempEvent->mask & IN_ACCESS) printf("IN_ACCESS\n"); if(tempEvent->mask & IN_DELETE_SELF) printf("IN_DELETE_SELF\n"); if(tempEvent->mask & IN_MODIFY) printf("IN_MODIFY\n"); if(tempEvent->mask & IN_OPEN) printf("IN_OPEN\n");}int main(int argc , char** argv)
{int mNotifyId , mWd;char mInfoBuf[BUF_LEN];ssize_t mNumRead;struct inotify_event * mTempEvent; char* p; if(argc < 2){printf("argv error\n");}//创建inotifymNotifyId = inotify_init();if(mNotifyId == -1){printf("notifyInit Failure\n");} //添加对文件的监听mWd = inotify_add_watch(mNotifyId,argv[1],IN_ALL_EVENTS);if(mWd == -1){printf("watch failure \n");}while(1){//监听的路径是否有文件创建删除等消息mNumRead = read(mNotifyId,mInfoBuf,BUF_LEN);if(mNumRead == -1){printf("read error\n");}for(p = mInfoBuf;p < mInfoBuf + mNumRead;){mTempEvent = (struct inotify_event *)p;displayEvent(mTempEvent);p += sizeof(struct inotify_event) + mTempEvent->len;}}return 0;}
Inotify可以监听到哪些事件呢
可以被监控的事件:有几种事件能够被监控。一些事件,比如 IN_DELETE_SELF 只适用于正在被监控的项目,而另一些,比如 IN_ATTRIB 或者 IN_OPEN 则只适用于监控过的项目,或者如果该项目是目录,则可以应用到其所包含的目录或文件。IN_ACCESS被监控项目或者被监控目录中的条目被访问过。例如,一个打开的文件被读取。IN_MODIFY被监控项目或者被监控目录中的条目被修改过。例如,一个打开的文件被修改。IN_ATTRIB被监控项目或者被监控目录中条目的元数据被修改过。例如,时间戳或者许可被修改。IN_CLOSE_WRITE一个打开的,等待写入的文件或目录被关闭。IN_CLOSE_NOWRITE一个以只读方式打开的文件或目录被关闭。IN_CLOSE一个掩码,可以很便捷地对前面提到的两个关闭事件(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)进行逻辑操作。IN_OPEN文件或目录被打开。IN_MOVED_FROM被监控项目或者被监控目录中的条目被移出监控区域。该事件还包含一个 cookie 来实现 IN_MOVED_FROM 与 IN_MOVED_TO 的关联。IN_MOVED_TO文件或目录被移入监控区域。该事件包含一个针对 IN_MOVED_FROM 的 cookie。如果文件或目录只是被重命名,将能看到这两个事件,如果它只是被移入或移出非监控区域,将只能看到一个事件。如果移动或重命名一个被监控项目,监控将继续进行。参见下面的 IN_MOVE-SELF。IN_MOVE可以很便捷地对前面提到的两个移动事件(IN_MOVED_FROM | IN_MOVED_TO)进行逻辑操作的掩码。IN_CREATE在被监控目录中创建了子目录或文件。IN_DELETE被监控目录中有子目录或文件被删除。IN_DELETE_SELF被监控项目本身被删除。监控终止,并且将收到一个 IN_IGNORED 事件。IN_MOVE_SELF监控项目本身被移动。除了事件标志以外,还可以在 inotify 头文件(/usr/include/sys/inotify.h)中找到其他几个标志。例如,如果只想监控第一个事件,可以在增加监控时设置 IN_ONESHOT 标志。
下面就是Epoll+Inotify的实现
#include <stdio.h>
#include <sys/epoll.h>
#include <sys/inotify.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>/* 定义epoll最大监听的文件数量 */
#define EPOLL_MAX_EVENTS 32#define BUFFER_SIZE 1024
#define ARRAY_LENGTH 128 // 定义数组的长度
#define NAME_LENGTH 128 // 定义文件名长度的限制 struct file_name_fd_desc { int fd; // 文件的描述符 char name[32]; // 文件名 char base_name[NAME_LENGTH]; // 带绝对路径的文件名
}; static struct epoll_event gEpollEventArray[EPOLL_MAX_EVENTS];/* 定义一个数组用来存放对应文件的文件描述符和文件名 */
static struct file_name_fd_desc gFileFdArray[ARRAY_LENGTH];static int array_index = 0;static char *base_dir; /*添加文件描述符到Epoll*/
static int add_to_epoll(int epoll_fd, int file_fd)
{int result;struct epoll_event eventItem;memset(&eventItem,0,sizeof(eventItem));eventItem.events=EPOLLIN;eventItem.data.fd = file_fd;result = epoll_ctl(epoll_fd,EPOLL_CTL_ADD,file_fd,&eventItem); return result;
}/*从Epoll删除文件描述符*/
static void remove_epoll(int epoll_fd,int file_fd)
{epoll_ctl(epoll_fd,EPOLL_CTL_DEL,file_fd,NULL);
}/*inotify监听到事件的处理逻辑,将新创建的文件添加到epoll,删除的文件从epoll删除*/
static int inotify_event_handler(int epoll_fd,int notify_fd)
{char InfoBuf[BUFFER_SIZE];struct inotify_event *event;char* p;int tmp_fd;int i;memset(InfoBuf,0,BUFFER_SIZE); int result = read(notify_fd,InfoBuf,BUFFER_SIZE);for(p = InfoBuf ; p < InfoBuf + result;){event = (struct inotify_event *)(p);if(event->mask & IN_CREATE){sprintf(gFileFdArray[array_index].name,"%s",event->name);sprintf(gFileFdArray[array_index].base_name,"%s%s",base_dir,event->name);tmp_fd = open(gFileFdArray[array_index].base_name, O_RDWR);if(tmp_fd == -1){printf("open file failure : %s\n",gFileFdArray[array_index].base_name);return -1;}gFileFdArray[array_index].fd = tmp_fd;add_to_epoll(epoll_fd,tmp_fd);array_index += 1;printf("add file to epoll %s\n",event->name);}else //delete file{for(i = 0 ; i < ARRAY_LENGTH ; i++){ if(!strcmp(gFileFdArray[i].name,event->name)){remove_epoll(epoll_fd,gFileFdArray[i].fd);gFileFdArray[i].fd = 0;memset(gFileFdArray[i].name, 0, sizeof(gFileFdArray[i].name)); memset(gFileFdArray[i].base_name, 0, sizeof(gFileFdArray[i].base_name));printf("delete file to epoll %s\n",event->name);break; }}}p += sizeof(struct inotify_event) + event->len; }}int main(int argc,char** argv)
{int mInotifyId;int mEpollId;char readbuf[1024]; int readlen;if(argc != 2){printf("Paramter Error\n");}base_dir = argv[1];//epoll创建mEpollId = epoll_create(1);if(mEpollId == -1){printf("Epoll Create Error\n");return -1;} mInotifyId = inotify_init();//Observe Directory FILE_CREATE & FILE_DELETE//inotify添加对文件的监听int result = inotify_add_watch(mInotifyId,argv[1],IN_DELETE | IN_CREATE);if(result == -1){printf("File Add Watch Failure\n");return -1;}add_to_epoll(mEpollId,mInotifyId);while(1){result = epoll_wait(mEpollId,gEpollEventArray,EPOLL_MAX_EVENTS,-1);if(result == -1){printf("epoll wait error\n");return -1;}else{ printf("file event happen\n");int i = 0; for(i = 0; i < result; i++){if(gEpollEventArray[i].data.fd == mInotifyId){//inotify event handlerif(-1 == inotify_event_handler(mEpollId,mInotifyId)) { printf("inotify handler error!\n"); return -1; } }else{printf("read data.....\n"); //read content of filereadlen = read(gEpollEventArray[i].data.fd, readbuf, 1024); readbuf[readlen] = '\0'; printf("read data %s\n",readbuf); }}}}}
Linux inotify + Epoll实现机制相关推荐
- Handler消息机制(一):Linux的epoll机制
在linux 没有实现epoll事件驱动机制之前,我们一般选择用select或者poll等IO多路复用的方法来实现并发服务程序.在linux新的内核中,有了一种替换它的机制,就是epoll. sele ...
- linux --- inotify 文件系统变化通知机制
Linux --- inotify 文件系统变化通知机制 在linux下开发过程中,用户态需要内核提供一些机制,以便用户态能够及时地得知内核或底层硬件设备发生了什么,从而能够更好地管理设备,给用户提供 ...
- Linux inotify功能及实现原理【转】
转自:http://blog.csdn.net/myarrow/article/details/7096460 1. inotify主要功能 它是一个内核用于通知用户空间程序文件系统变化的机制. 众所 ...
- linux内核设计与实现 epub_Epoll学习服务器的简单实现-Linux内核Epoll结构
1.Begins~ 有的人学习linux编程很久,只知道网络编程是socket,bind, listen...,然而这些都是网络通信软件最基本的接口.在某网络公司待了y,也了解到公司的基础就是网络转发 ...
- linux socket epoll
什么是epoll epoll是什么?按照man手册的说法:是为处理大批量句柄而作了改进的poll.当然,这不是2.6内核才有的,它是在2.5.44内核中被引进的(epoll(4) is a new A ...
- netty的epoll和linux的epoll是如何实现的
1.linux的epoll epoll 是Linux内核中的一种可扩展IO事件处理机制,最早在 Linux 2.5.44内核中引入,可被用于代替POSIX select 和 poll 系统调用,并且在 ...
- Linux inotify
简述 Linux inotify是一种监控文件系统中文件和目录变化的机制,能够实时地监视文件和目录的变化并通知相应的进程. 在Linux系统中,文件系统的访问和管理是通过系统调用进行的.inotify ...
- Windows 平台下面的IOCP技术 Linux下面Epoll 还有FreeBSD下面Kqueue的应用了。跨平台库行业里面最出名的莫过于ACE、ASIO(Boos公司)两大支持库支持IOCP
http://wenku.baidu.com/view/4117460502020740be1e9b3c.html 游戏服务器集群 自从2003年开发VOIP Radius Server以及修改Gnu ...
- Linux inotify功能及原理(inotify_init、inotify_add_watch、inotify_rm_watch、read)
1. inotify主要功能 它是一个内核用于通知用户空间程序文件系统变化的机制. 开源社区提出用户态需要内核提供一些机制,以便用户态能够及时地得知内核或底层硬件设备发生了什么,从而能够更好地管理设备 ...
最新文章
- Ubuntu通过路由器上网的配置
- 在c 语言中stdio,C语言中,什么时候用到stdio.h之外的解释文件
- mysql 开启守护进程_[求助]Linux上MySQL Server 5.6 安装后无法启动守护进程
- mysql int 11 java_mysql中int(11)列的大小(以字节为单位)是多少?
- Fullpage参数说明
- hdoj 1285 确定比赛名次 【拓扑排序】
- 计算机编程pdf百度云,计算机编程基础.pdf
- android怎么阿看手机是移动联通还是电信的网络,GSM是联通、移动还是电信的网络?...
- python爬取公众号,用最简单的方式爬虫
- 解决在IE下“JSON”未定义的有关问题
- 远程连接桌面报:这可能是由于credssp加密oracle修正
- 那些年-SAP固定资产导入AS91 OASV
- Matlab 2016 超详细安装教程
- html 卫星地图显示地名,卫星图看:河南10个名字非常好听的县(区),你认识几个?...
- HP惠普服务器做RAID
- java实现微信企业号API服务端调用封装
- qconshanghai2015
- 安徽师大附中%你赛day3T1 怜香惜玉 解题报告
- GO语言开发天天生鲜项目第三天 用户模块开发
- libevent库bufferevent事件实现socket通信