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

一、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();
}
}

总的来说,虽然这只是一个很简单的功能,但还是为自己的一小步提升而高兴,在此分享给各位一起进步。

单单代码逻辑可修改的地方就有很多,还望大家见谅。

05-11 15:19