Inotify机制的简单应用
编程之路刚刚开始,错误难免,希望大家能够指出。
一、Inotify机制
1.简单介绍inotify:Inotify可用于检测单个文件,也可以检测整个目录。当检测的对象是一个目录的时候,目录本身和目录里的内容都会成为检测的对象。
此种机制的出现的目的是当内核空间发生某种事件之后,可以立即通知到用户空间。方便用户做出具体的操作。
2.inotify的三个API:
inotify_init(void)
用于创建一个inotify的实例,然后返回inotify事件队列的文件描述符。
inotify_add_watch(int fd, const char* pathname, uint32_t mask)
该函数用于添加“watch list”,也就是检测列表。 可以是一个新的watch,也可以是一个已经存在的watch。其中fd就是inotify_init的返回值,pathname是要检测目录或者文件的路径,mask就是要检测的事件类型。该函数成功返回的是一个unique的watch描述符。
inotify_rm_watch(int fd, int wd)
用于从watch list种移除检测的对象。
3.读取事件:
使用read系统调用可以获取至少一个(必定为整数个,当剩余空间不足容纳下一个结构体时,该结构体只能下次read获取)的inotify_event结构体。
struct inotify_event {
int wd; /*watch描述符 */
uint32_t mask; /* 事件掩码 */
uint32_t cookie;
uint32_t len; /* name的长度 */
char name[]; /* 文件或目录名 */
};
切记如果read()的读取缓冲区如果小于一个inotify_event的长度,read会返回错误,所以建议缓冲区为每个inotify_event的长度假定为“sizeof(struct inotify_event) + NAME_MAX +1”,“NAME_MAX”是系统文件名最大长度的宏定义。
二、sigaction 函数
1.int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) 这个系统调用的作用是改变进程接收到的指定信号的行动。
signum : 说明具体信号,它可以是除了SIGKILL和SIGSTOP之外的任何有效信号值。
act : 将要安装的signum定义信号的新行动。
oldact: 用来保存signum定义信号的过去的行动。
2.目前个人所了解的sigaction和signal的区别:
1.signal只能对信号进行一次自定义处理,之后恢复默认操作,sigaction可以进行反复调用;
2.signal处理过程中无法阻塞某些信号,而sigaction可以阻塞它自身和其他信号;
3.sigaction 结构体定义如下:
struct sigaction { void (*sa_handler)(int); 设置为SIG_DFL表示默认行动,设置为SIG_IGN表示忽略这个信号,或者设置为处理函数的指针。 void (*sa_sigaction)(int, siginfo_t* , vid*); sigset_t sa_mask; 这个参数指明了在信号处理函数执行过程中应该被阻止的信号的mask值(包括它自己)。 int sa_flags; 改变信号的行为; void (*sa_restorer)(void); };
简单说明一下思路:
1.将argv[1]指定的目录及其子目录都设置为受监控目录;
2.不断去read事件,并将事件指定记录在某个文件内,并存有时间发生的大概时间;
3.进程需要通过发送“SIGINT”信号来进行停止。
#define _XOPEN_SOURCE 500 #include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <limits.h>
#include <fcntl.h>
#include <ftw.h>
#include <time.h> #define BUF_SIZE (10 *(sizeof(struct inotify_event) + NAME_MAX +1))
#define INOTIFT_EVENT (IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY | IN_MOVED_FROM | IN_MOVED_TO) struct pathInfo
{
int wd;
char czPath[];
struct pathInfo *pNext;
}; struct eventInfo
{
int event;
char explain[];
}; static struct eventInfo g_stEventInfo[] =
{
{IN_CREATE,"create file"},
{IN_DELETE,"delete file"},
{IN_DELETE_SELF,"delete file"},
{IN_MODIFY,"alter file"},
{IN_MOVED_FROM,"lose file"},
{IN_MOVED_TO,"append file"},
}; int g_inotifyFd;
FILE *g_fp;
struct pathInfo *g_list; /*
IN_CREATE 在受监控目录下创建了文件或目录
IN_DELETE 在受监控目录内删除了文件或目录
IN_DELETE_SELF 删除了受监控目录/文件本身
IN_MODIFY 文件被修改
IN_MOVED_FROM 文件移除受监控目录
IN_MOVED_TO 将文件移到受监控目录
*/ int myNfwt(const char *fpath,const struct stat *sb,int flag,struct FTW *ftwbuf)
{
if(flag != FTW_DP)
{
return ;
}
int wd = inotify_add_watch(g_inotifyFd,fpath,INOTIFT_EVENT);
if(wd == -)
{
perror("inotify_add_watch");
return -;
} struct pathInfo *pTemp = (struct pathInfo *)malloc(sizeof(struct pathInfo));
memset(pTemp->czPath,,sizeof(pTemp->czPath));
pTemp->wd = wd;
pTemp->pNext = NULL;
if(strcpy(pTemp->czPath,fpath) == NULL)
{
perror("strcpy");
return -;
} if(g_list == NULL)
{
g_list = pTemp;
return ;
}
else
{
if(g_list->pNext == NULL)
{
g_list->pNext = pTemp;
return ;
}
struct pathInfo *p = g_list->pNext;
while()
{
if(p->pNext == NULL)
{
p->pNext = pTemp;
return ;
}
p = p->pNext;
}
}
} int watch_object(char *fileName)
{
int flags = FTW_PHYS | FTW_DEPTH;
int ret = nftw(fileName,myNfwt,,flags);
if(ret == -)
{
perror("nftw");
return -;
} return ;
} char *GetPath(int wd)
{
if(g_list == NULL)
{
return NULL;
}
if(g_list->wd == wd)
{
return g_list->czPath;
}
struct pathInfo *pTemp = g_list->pNext; while()
{
if(pTemp == NULL)
{
break;
}
if(pTemp->wd == wd)
{
return pTemp->czPath;
}
pTemp = pTemp->pNext;
}
return NULL;
} int recordEvent()
{
int iReadNum;
char czBuf[BUF_SIZE+] = {};
struct inotify_event *pEvent;
time_t now;
struct tm*tm_now; iReadNum = read(g_inotifyFd,czBuf,BUF_SIZE);
if(iReadNum == -)
{
printf("read failed\n");
return -;
}
else if(iReadNum == )
{
return ;
}
time(&now);
tm_now = localtime(&now);
char *p = czBuf;
while()
{
if(p >= czBuf+iReadNum)
{
break;
}
pEvent = (struct inotify_event *)p;
char *pPath = GetPath(pEvent->wd);
if(pPath == NULL)
{
return -;
}
for(int index = ;index < sizeof(g_stEventInfo)/sizeof(struct eventInfo);index++)
{
if(pEvent->mask & (g_stEventInfo[index].event))
{
fprintf(g_fp,"path : %-30s\t event : %-30s\t file name : %-30s\t time : %s",pPath,g_stEventInfo[index].explain,pEvent->name,asctime(tm_now));
break;
}
}
fflush(g_fp);
p += (sizeof(struct inotify_event) + pEvent->len);
} return ;
} int GetFileLine()
{
char *p;
char czBuf[] = {};
int line = ;
while()
{
p = fgets(czBuf,,g_fp);
if(p == NULL)
{
return line;
}
line++;
}
return -;
} int freeSpace(struct pathInfo **pInfo)
{
if(*pInfo == NULL)
{
return ;
}
else
{
if((*pInfo)->pNext == NULL)
{
if(inotify_rm_watch(g_inotifyFd,(*pInfo)->wd) == -)
{
printf("notify_rm_watch error\n");
}
free((*pInfo));
*pInfo = NULL;
return ;
}
else
{
freeSpace(&((*pInfo)->pNext));
if(inotify_rm_watch(g_inotifyFd,(*pInfo)->wd) == -)
{
printf("notify_rm_watch error\n");
}
free(*pInfo);
*pInfo = NULL;
return ;
}
}
return -;
} void catch_signal(int sig)
{
if(sig == SIGINT)
{
int ret = freeSpace(&g_list);
if(ret < )
{
printf("free space failed\n");
}
close(g_inotifyFd);
fclose(g_fp);
}
} int main(int argc,char *argv[])
{
if(argc < )
{
printf("please input file/dir name:./a.ot File.txt\n");
return -;
} g_inotifyFd = inotify_init();
if(g_inotifyFd == -)
{
perror("inotify_init");
return -;
}
int ret = watch_object(argv[]);
if(ret != )
{
return -;
} g_fp = fopen("/home/gc/Record_Jyb","a+");
if(g_fp == NULL)
{
perror("fopen");
return -;
} struct sigaction stSign;
stSign.sa_handler = catch_signal;
sigemptyset(&stSign.sa_mask);
stSign.sa_flags = SA_RESETHAND;
sigaction(SIGINT,&stSign,); while()
{
if(GetFileLine() >= )
{
fclose(g_fp);
g_fp = fopen("/home/gc/Record_Jyb","w");
if(g_fp == NULL)
{
perror("fopen");
return -;
}
fclose(g_fp);
g_fp = fopen("/home/gc/Record_Jyb","a+");
if(g_fp == NULL)
{
perror("fopen");
return -;
}
}
ret = recordEvent();
if(ret < )
{
return -;
}
sleep();
}
}
总的来说,虽然这只是一个很简单的功能,但还是为自己的一小步提升而高兴,在此分享给各位一起进步。
单单代码逻辑可修改的地方就有很多,还望大家见谅。
Inotify机制的简单应用的更多相关文章
- (转)java反射机制及简单工厂模式
第一步,定义一个接口类 package factory.face; /** * 接口,为了保证返回的对象可以统一用 Product接受 * @author Administrator */ publi ...
- springMVC源码分析--异常处理机制HandlerExceptionResolver简单示例(一)
springMVC对Controller执行过程中出现的异常提供了统一的处理机制,其实这种处理机制也简单,只要抛出的异常在DispatcherServlet中都会进行捕获,这样就可以统一的对异常进行处 ...
- Linux内核Inotify机制学习笔记
一.Inotify简介: Inotify是一种文件变化通知机制,Linux内核从2.6.13开始引入.它是一个内核用于通知用户空间程序文件系统变化的机制.开源社区提出用户态需要内核提供一些机制,以便用 ...
- Android的Message机制(简单小结)
对于Android的Message机制主要涉及到三个主要的类,分别是Handler.Message.Looper:首先对每个类做一个简单介绍:然后再介绍所谓的Android的Message机制是如何实 ...
- 利用JDK动态代理机制实现简单拦截器
利用JDK动态代理机制实现简单的多层拦截器 首先JDK动态代理是基于接口实现的,所以我们先定义一个接口 public interface Executer { public Object execut ...
- java——关于异常处理机制的简单原理和应用
异常处理机制的简单原理和应用 一.Execption可以分为java标准定义的异常和程序员自定义异常2种 (1)一种是当程序违反了java语规则的时候,JAVA虚拟机就会将发生的错误表示为一个异常.这 ...
- java反射机制的简单介绍
参考博客: https://blog.csdn.net/mlc1218559742/article/details/52754310 先给出反射机制中常用的几个方法: Class.forName (& ...
- 180609-Spring之事件驱动机制的简单使用
文章链接:https://liuyueyi.github.io/hexblog/hexblog/2018/06/09/180609-Spring之事件驱动机制的简单使用/ Spring之事件驱动机制的 ...
- Linux内核中的信号机制--一个简单的例子【转】
本文转载自:http://blog.csdn.net/ce123_zhouwei/article/details/8562958 Linux内核中的信号机制--一个简单的例子 Author:ce123 ...
随机推荐
- Spring boot+mybatis+thymeleaf 实现登录注册,增删改查
本文重在实现理解,过滤器,业务,逻辑需求,样式请无视.. 项目结构如下 1.idea新建Spring boot项目,在pom中加上thymeleaf和mybatis支持.pom.xml代码如下 < ...
- MapReduce 踩坑 :Aggregation is not enabled. Try the nodemanager at IP:HOST
原因:yarn-site.xml 中,有关mapreduce日志查看的aggregation未配置启用 解决:在yarn-site.xml 中加入以下配置 <property> <n ...
- gym 101081 E. Polish Fortress 几何
E. Polish Fortress time limit per test 2.0 s memory limit per test 256 MB input standard input outpu ...
- webpack点滴
一个比较完整的webpack的配置,自己配置不断更新. const path = require('path') const configs = require('./configs/') const ...
- guxh的python笔记七:抽象基类
1,鸭子类型和白鹅类型 1.1,白鹅类型 白鹅类型对接口有明确定义,比如不可变序列(Sequence),需要实现__contains__,__iter__,__len__,__getitem__,__ ...
- 『流畅的Python』第15章:上下文管理器和else块
- [spring源码] 小白级别的源码解析ioc(二)
之前一篇,整体描述了一下 Spring的整体概况和 jar包的介绍. 现在开始进入具体的源码解析,从本篇开始,先介绍spring的ioc容器.之前也看过一些介绍spring源码的, 有的是只讲整体的接 ...
- springcloud-Ribbon-负载均衡组件
Ribbon负载均衡 1.Ribbon简介 ribbin是Netflix发布的负载均衡器,有助于控制http和tcp客户端的行为,为ribbon配置服务提供者列表后,ribbon就可以基于某种负载均衡 ...
- springcloud-Eureka-服务注册与发现核心组件
Eureka组件 Eureka是Netfilx开源的服务发现组件,本身是一个基于rest的服务,它包含client和server两部分. Spirng Cloud将它集成在子项目Spirng Clou ...
- [hdu P3085] Nightmare Ⅱ
[hdu P3085] Nightmare Ⅱ Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...