Linux inotify特性以及遍历方式监控所有子目录

首先,转载一段关于inotify的介绍:

它是一个内核用于通知用户空间程序文件系统变化的机制。

众所周知,Linux 桌面系统与 MAC 或 Windows相比有许多不如人意的地方,为了改善这种状况,开源社区提出用户态需要内核提供一些机制,以便用户态能够及时地得知内核或底层硬件设备发生了什么,从而能够更好地管理设备,给用户提供更好的服务,如hotplug、udev 和 inotify 就是这种需求催生的。Hotplug是一种内核向用户态应用通报关于热插拔设备一些事件发生的机制,桌面系统能够利用它对设备进行有效的管理,udev 动态地维护 /dev下的设备文件,inotify 是一种文件系统的变化通知机制,如文件增加、删除等事件可以立刻让用户态得知,该机制是著名的桌面搜索引擎项目beagle 引入的,并在 Gamin 等项目中被应用。

按我的理解,inotify本身是linux内核向系统或用户提供的一个API,即发生文件变更请求时,除了处理这个任务本身,还向某个接口播报一个事件,如果我们设置了接收这个目录内的事件(inotify_add_watch (fd, path, mask)),就能够从相应的事件socket中取得相应信息。
inotify库中定义了这几个函数:

inotify_init ();
inotify_add_watch (fd, path, mask);
inotify_rm_watch (fd, wd);

其中,inotify_init ()用于初始化一个实例;
inotify_add_watch (fd, path, mask)将一个目录(path)加入监控,fd为初始化好的inotify实例,mask为监控的事件;
inotify_rm_watch (fd, wd)将一个监控的对象移出监控,wd为已添入监控的对象;

以下为根据inotify库开发的记录文件变更的小工具,它在inotify_add_watch添加单个目录的基础上,加入了递归遍历子文件夹,并将它们全部纳入监控,通过设置一个静态全局结构来对每个纳入监控的目录进行标记,从而能够识别到发生事件的位置并将其记录下来。另外,它还附带了更新机制,即当监控到文件创建事件时,会判断其是否为文件夹,若是的话会将其同样纳入监控。

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h> 
#include <dirent.h>
#include <malloc.h>
#define EVENT_NUM 12
#define IS_FILE 8
#define IS_DIR 4
#define DATA_W 200

static struct dir_path{
int id;
char **path;
}dir;

char *event_str[EVENT_NUM] =
{
	"IN_ACCESS",
	"IN_MODIFY",        //文件修改
	"IN_ATTRIB",
	"IN_CLOSE_WRITE",
	"IN_CLOSE_NOWRITE",
	"IN_OPEN",
	"IN_MOVED_FROM",    //文件移动from
	"IN_MOVED_TO",      //文件移动to
	"IN_CREATE",        //文件创建
	"IN_DELETE",        //文件删除
	"IN_DELETE_SELF",
	"IN_MOVE_SELF"
	};
//=======================================================================
int id_add(char *path_id){
		//free(dir.path[dir.id]);
		dir.path[dir.id]=(char *)malloc(DATA_W);
		strncpy(dir.path[dir.id],path_id,DATA_W);
		printf("%d:%s\n",dir.id,dir.path[dir.id]);
		dir.id=dir.id+1;
		return 0;
}
//=======================================================================
		char *gettime()
	{   
		static char timestr[40];
		time_t t;
		struct tm *nowtime;
		time(&t);
		nowtime = localtime(&t);
		strftime(timestr,sizeof(timestr),"%Y-%m-%d %H:%M:%S",nowtime);
		return timestr;
	}
//=======================================================================
		int inotify_watch_dir(char *dir_path,int fd)
	{
		int wd;
		int len;
		DIR *dp;
		char pdir_home[DATA_W];
		char pdir[DATA_W];
		strcpy(pdir_home,dir_path);
		struct dirent *dirp;
		struct inotify_event *event;
		if (fd < 0)
		{
			fprintf(stderr, "inotify_init failed\n");
			return -1;
		}
		wd = inotify_add_watch(fd, dir_path, IN_CREATE|IN_ATTRIB|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO);
		if ((dp = opendir(dir_path)) == NULL)
        {
            return -1;
        }
        while ((dirp = readdir(dp)) != NULL)
        {
             if(strcmp(dirp->d_name,".") == 0 || strcmp(dirp->d_name,"..") == 0)
             {
                 continue;
             }

             if (dirp->d_type == IS_FILE)
             {
                 continue;
             }
             if (dirp->d_type == IS_DIR)
             {
		strncpy(pdir,pdir_home,DATA_W);
		strncat(pdir,"/",1);
             	strncat(pdir,dirp->d_name,BUFSIZ);
		id_add(pdir);
                inotify_watch_dir(pdir, fd);
             }
         }
         closedir(dp);
	}
//====================================================================
		int main(int argc,char *argv[])
	{
		dir.id=1;
		dir.path=(char **)malloc(65534);
		if(argc < 2)
		{
			fprintf(stderr, "USISZ-TE Hao_zeng\nusage:%s [path]\n", argv[0]);
			return -1;
		}
		id_add(argv[1]);
		int fd=inotify_init();

		inotify_watch_dir(argv[1],fd);

		int i;
		int len;
		int nread;
		struct stat res;
		char path[BUFSIZ];
		char buf[BUFSIZ];
		struct inotify_event *event;
		char log_dir[DATA_W]={};
		getcwd(log_dir,DATA_W);
		strncat(log_dir,"/inotify.log",12);
		//printf("log path: %s\n",log_dir);
		buf[sizeof(buf) - 1] = 0;
		while( (len = read(fd, buf, sizeof(buf) - 1)) > 0 )
		{
			nread = 0;
			while(len> 0)
		{
			event = (struct inotify_event *)&buf[nread];
			for(i=0; i<EVENT_NUM; i++)
			{
			if((event->mask >> i) & 1)
			{
			if(event->len > 0)
			if(strncmp(event->name,".",1))
		{
			FILE *fp=NULL;
			fp=fopen(log_dir,"a");
			fprintf(fp,"%s: %s/%s --- %s\n",gettime(),dir.path[event->wd],event->name,event_str[i]);
			fprintf(stdout,"%s: %s/%s --- %s\n",gettime(),dir.path[event->wd],event->name,event_str[i]);
			if((!strcmp(event_str[i],"IN_CREATE"))|(!strcmp(event_str[i],"IN_MOVED_TO"))){
			memset(path,0,sizeof path);
			strncat(path,dir.path[event->wd],BUFSIZ);
			strncat(path,"/",1);
			strncat(path,event->name,BUFSIZ);
			stat(path ,&res);
			if (S_ISDIR(res.st_mode))
		        {
  		          inotify_add_watch(fd, path, IN_CREATE|IN_ATTRIB|IN_DELETE|IN_MOVED_FROM|IN_MOVED_TO);
				  id_add(path);
		        }
			}
				fclose(fp);
		}
	}
	}
		nread = nread + sizeof(struct inotify_event) + event->len;
		len = len - sizeof(struct inotify_event) - event->len;
	}
	}
		return 0;
	}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值