编程之路刚刚开始,错误难免,希望大家能够指出。

一、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机制的简单应用的更多相关文章

  1. (转)java反射机制及简单工厂模式

    第一步,定义一个接口类 package factory.face; /** * 接口,为了保证返回的对象可以统一用 Product接受 * @author Administrator */ publi ...

  2. springMVC源码分析--异常处理机制HandlerExceptionResolver简单示例(一)

    springMVC对Controller执行过程中出现的异常提供了统一的处理机制,其实这种处理机制也简单,只要抛出的异常在DispatcherServlet中都会进行捕获,这样就可以统一的对异常进行处 ...

  3. Linux内核Inotify机制学习笔记

    一.Inotify简介: Inotify是一种文件变化通知机制,Linux内核从2.6.13开始引入.它是一个内核用于通知用户空间程序文件系统变化的机制.开源社区提出用户态需要内核提供一些机制,以便用 ...

  4. Android的Message机制(简单小结)

    对于Android的Message机制主要涉及到三个主要的类,分别是Handler.Message.Looper:首先对每个类做一个简单介绍:然后再介绍所谓的Android的Message机制是如何实 ...

  5. 利用JDK动态代理机制实现简单拦截器

    利用JDK动态代理机制实现简单的多层拦截器 首先JDK动态代理是基于接口实现的,所以我们先定义一个接口 public interface Executer { public Object execut ...

  6. java——关于异常处理机制的简单原理和应用

    异常处理机制的简单原理和应用 一.Execption可以分为java标准定义的异常和程序员自定义异常2种 (1)一种是当程序违反了java语规则的时候,JAVA虚拟机就会将发生的错误表示为一个异常.这 ...

  7. java反射机制的简单介绍

    参考博客: https://blog.csdn.net/mlc1218559742/article/details/52754310 先给出反射机制中常用的几个方法: Class.forName (& ...

  8. 180609-Spring之事件驱动机制的简单使用

    文章链接:https://liuyueyi.github.io/hexblog/hexblog/2018/06/09/180609-Spring之事件驱动机制的简单使用/ Spring之事件驱动机制的 ...

  9. Linux内核中的信号机制--一个简单的例子【转】

    本文转载自:http://blog.csdn.net/ce123_zhouwei/article/details/8562958 Linux内核中的信号机制--一个简单的例子 Author:ce123 ...

随机推荐

  1. innoDB锁小结

    innodb的锁分两类:lock和latch. 其中latch主要是保证并发线程操作临界资源的正确性,要求时间非常短,所以没有死锁检测机制.latch包括mutex(互斥量)和rwlock(读写锁). ...

  2. vue分页控件

    下载:https://pan.baidu.com/s/1c125Vgc 一个简单的分页控件: 自动加载模式: 手动加载模式: loading图标使用了iconfont: 主要方法: beginRefr ...

  3. 【微信小程序开发】使用button标签的open-type="getUserInfo"引导用户去授权

    一. 前言 小程序官方文档,上面说明 > wx.getUserInfo(OBJECT) 注意:此接口有调整,使用该接口将不再出现授权弹窗,请使用 <button open-type=&qu ...

  4. Matlab:导数边界值的有限元(Ritz)法

    tic; % this method is transform from Ritz method %is used for solving two point BVP %this code was w ...

  5. easyui 如何为标签动态追加属性实现渲染效果

    简述一下在项目遇到的问题,这边有一个需求,选择不同类型,加载不同的div标签(其中属性是否必填是区分类型的关键) html界面是这样的 <div class="grid_1 lbl&q ...

  6. vue和react全面对比(详解)

    vue和react对比(详解) 放两张图镇压小妖怪 本文先讲共同之处, 再分析区别 大纲在此: 共同点: a.都使用虚拟dom b.提供了响应式和组件化的视图组件 c.注意力集中保持在核心库,而将其他 ...

  7. shell读取mysql数据库

    select_sql="select value from glpi_configs where name='version' " db_data=`mysql -h $host ...

  8. mysql-8.0.12-winx64 解压版安装(转)

    1.官网下载 https://dev.mysql.com/downloads/mysql/ 2.解压到一个合适的目录 3.配置环境变量 path : bin的目录(必须配置) MYSQL_HOME:m ...

  9. css图形——椭圆

    在css中,我们也使用border-radius属性来实现椭圆 语法 border-radius:x/y; 说明: x表示圆角的水平半径,y表示圆角的垂直半径. 例如:border-radius:30 ...

  10. 唤醒实验(java

    package sy;import java.util.Random; public class random { public static void main(String[] args) { / ...