Inotify機制的簡單應用

編程之路剛剛開始,錯誤不免,但願你們可以指出。編程

 

1、Inotify機制cookie

1.簡單介紹inotify:Inotify可用於檢測單個文件,也能夠檢測整個目錄。當檢測的對象是一個目錄的時候,目錄自己和目錄裏的內容都會成爲檢測的對象。app

此種機制的出現的目的是當內核空間發生某種事件以後,能夠當即通知到用戶空間。方便用戶作出具體的操做。函數

2.inotify的三個API:ui

  inotify_init(void)                        spa

  用於建立一個inotify的實例,而後返回inotify事件隊列的文件描述符。指針

  inotify_add_watch(int fd, const char* pathname, uint32_t  mask)  rest

  該函數用於添加「watch list」,也就是檢測列表。 能夠是一個新的watch,也能夠是一個已經存在的watch。其中fd就是inotify_init的返回值,pathname是要檢測目錄或者文件的路徑,mask就是要檢測的事件類型。該函數成功返回的是一個unique的watch描述符。code

  inotify_rm_watch(int fd, int wd)                    對象

  用於從watch list種移除檢測的對象。

3.讀取事件:

  使用read系統調用能夠獲取至少一個(一定爲整數個,當剩餘空間不足容納下一個結構體時,該結構體只能下次read獲取)的inotify_event結構體。

1 struct inotify_event {  
2     int      wd;           /*watch描述符 */  
3     uint32_t mask;     /*  事件掩碼 */  
4     uint32_t cookie;   
5     uint32_t len;      /* name的長度 */  
6     char     name[];   /* 文件或目錄名 */  
7 };  

  切記若是read()的讀取緩衝區若是小於一個inotify_event的長度,read會返回錯誤,因此建議緩衝區爲每一個inotify_event的長度假定爲「sizeof(struct inotify_event) + NAME_MAX +1」,「NAME_MAX」是系統文件名最大長度的宏定義。

 

2、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 結構體定義以下:

 1 struct sigaction {
 2 
 3     void (*sa_handler)(int);    設置爲SIG_DFL表示默認行動,設置爲SIG_IGN表示忽略這個信號,或者設置爲處理函數的指針。
 4 
 5     void (*sa_sigaction)(int,  siginfo_t* , vid*);
 6 
 7     sigset_t sa_mask;    這個參數指明瞭在信號處理函數執行過程當中應該被阻止的信號的mask值(包括它本身)。
 8 
 9     int sa_flags;   改變信號的行爲;
10 
11     void (*sa_restorer)(void);
12 
13 };

 

簡單說明一下思路:
  1.將argv[1]指定的目錄及其子目錄都設置爲受監控目錄;

  2.不斷去read事件,並將事件指定記錄在某個文件內,並存有時間發生的大概時間;

  3.進程須要經過發送「SIGINT」信號來進行中止。

  1 #define _XOPEN_SOURCE 500
  2 
  3 #include <stdio.h>
  4 #include <assert.h>
  5 #include <unistd.h>
  6 #include <stdlib.h>
  7 #include <signal.h>
  8 #include <errno.h>
  9 #include <string.h>
 10 #include <sys/types.h>
 11 #include <sys/inotify.h>
 12 #include <limits.h>
 13 #include <fcntl.h>
 14 #include <ftw.h>
 15 #include <time.h>
 16 
 17 #define BUF_SIZE (10 *(sizeof(struct inotify_event) + NAME_MAX +1))
 18 #define INOTIFT_EVENT (IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY | IN_MOVED_FROM | IN_MOVED_TO)
 19 
 20 struct pathInfo
 21 {
 22     int wd;
 23     char czPath[256];
 24     struct pathInfo *pNext;
 25 };
 26 
 27 struct eventInfo
 28 {
 29     int event;
 30     char explain[30];
 31 };
 32 
 33 static struct eventInfo g_stEventInfo[] =
 34 {
 35     {IN_CREATE,"create file"},
 36     {IN_DELETE,"delete file"},
 37     {IN_DELETE_SELF,"delete file"},
 38     {IN_MODIFY,"alter file"},
 39     {IN_MOVED_FROM,"lose file"},
 40     {IN_MOVED_TO,"append file"},
 41 };
 42 
 43 int g_inotifyFd;
 44 FILE *g_fp;
 45 struct pathInfo *g_list;
 46 
 47 /*
 48 IN_CREATE               在受監控目錄下建立了文件或目錄
 49 IN_DELETE               在受監控目錄內刪除了文件或目錄
 50 IN_DELETE_SELF          刪除了受監控目錄/文件自己
 51 IN_MODIFY               文件被修改
 52 IN_MOVED_FROM           文件移除受監控目錄
 53 IN_MOVED_TO             將文件移到受監控目錄
 54 */
 55 
 56 int myNfwt(const char *fpath,const struct stat *sb,int flag,struct FTW *ftwbuf)
 57 {
 58     if(flag != FTW_DP)
 59     {
 60         return 0;
 61     }
 62     int wd = inotify_add_watch(g_inotifyFd,fpath,INOTIFT_EVENT);
 63     if(wd == -1)
 64     {
 65         perror("inotify_add_watch");
 66         return -1;
 67     }
 68 
 69     struct pathInfo *pTemp = (struct pathInfo *)malloc(sizeof(struct pathInfo));
 70     memset(pTemp->czPath,0,sizeof(pTemp->czPath));
 71     pTemp->wd = wd;
 72     pTemp->pNext = NULL;
 73     if(strcpy(pTemp->czPath,fpath) == NULL)
 74     {
 75         perror("strcpy");
 76         return -2;
 77     }
 78 
 79     if(g_list == NULL)
 80     {
 81         g_list = pTemp;
 82         return 0;
 83     }
 84     else
 85     {
 86         if(g_list->pNext == NULL)
 87         {
 88             g_list->pNext = pTemp;
 89             return 0;
 90         }
 91         struct pathInfo *p = g_list->pNext;
 92         while(1)
 93         {
 94             if(p->pNext == NULL)
 95             {
 96                 p->pNext = pTemp;
 97                 return 0;
 98             }
 99             p = p->pNext;
100         }
101     }
102 }
103 
104 int watch_object(char *fileName)
105 {
106     int flags = FTW_PHYS | FTW_DEPTH;
107     int ret = nftw(fileName,myNfwt,896,flags);
108     if(ret == -1)
109     {
110         perror("nftw");
111         return -1;
112     }
113 
114     return 0;
115 }
116 
117 char *GetPath(int wd)
118 {
119     if(g_list == NULL)
120     {
121         return NULL;
122     }
123     if(g_list->wd == wd)
124     {
125         return g_list->czPath;
126     }
127     struct pathInfo *pTemp = g_list->pNext;
128 
129     while(1)
130     {
131         if(pTemp == NULL)
132         {
133             break;
134         }
135         if(pTemp->wd == wd)
136         {
137             return pTemp->czPath;
138         }
139         pTemp = pTemp->pNext;
140     }
141     return NULL;
142 }
143 
144 int recordEvent()
145 {
146     int iReadNum;
147     char czBuf[BUF_SIZE+1] = {0};
148     struct inotify_event *pEvent;
149     time_t now;
150     struct tm*tm_now;
151 
152     iReadNum = read(g_inotifyFd,czBuf,BUF_SIZE);
153     if(iReadNum == -1)
154     {
155         printf("read failed\n");
156         return -4;
157     }
158     else if(iReadNum == 0)
159     {
160         return 0;
161     }
162     time(&now);
163     tm_now = localtime(&now);
164     char *p = czBuf;
165     while(1)
166     {
167         if(p >= czBuf+iReadNum)
168         {
169             break;
170         }
171         pEvent = (struct inotify_event *)p;
172         char *pPath = GetPath(pEvent->wd);
173         if(pPath == NULL)
174         {
175             return -5;
176         }
177         for(int index = 0;index < sizeof(g_stEventInfo)/sizeof(struct eventInfo);index++)
178         {
179             if(pEvent->mask & (g_stEventInfo[index].event))
180             {
181                 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));
182                 break;
183             }
184         }
185         fflush(g_fp);
186         p += (sizeof(struct inotify_event) + pEvent->len);
187     }
188 
189     return 0;
190 }
191 
192 int GetFileLine()
193 {
194     char *p;
195     char czBuf[200] = {0};
196     int line = 0;
197     while(1)
198     {
199         p = fgets(czBuf,200,g_fp);
200         if(p == NULL)
201         {
202             return line;
203         }
204         line++;
205     }
206     return -1;
207 }
208 
209 int freeSpace(struct pathInfo **pInfo)
210 {
211     if(*pInfo == NULL)
212     {
213         return 0;
214     }
215     else
216     {
217         if((*pInfo)->pNext == NULL)
218         {
219             if(inotify_rm_watch(g_inotifyFd,(*pInfo)->wd) == -1)
220             {
221                 printf("notify_rm_watch error\n");
222             }
223             free((*pInfo));
224             *pInfo = NULL;
225             return 0;
226         }
227         else
228         {
229             freeSpace(&((*pInfo)->pNext));
230             if(inotify_rm_watch(g_inotifyFd,(*pInfo)->wd) == -1)
231             {
232                 printf("notify_rm_watch error\n");
233             }
234             free(*pInfo);
235             *pInfo = NULL;
236             return 0;
237         }
238     }
239     return -1;
240 }
241 
242 
243 void catch_signal(int sig)
244 {
245     if(sig == SIGINT)
246     {
247         int ret = freeSpace(&g_list);
248         if(ret < 0)
249         {
250             printf("free space failed\n");
251         }
252         close(g_inotifyFd);
253         fclose(g_fp);
254     }
255 }
256 
257 int main(int argc,char *argv[])
258 {
259     if(argc < 2)
260     {
261         printf("please input file/dir name:./a.ot File.txt\n");
262         return -1;
263     }
264 
265     g_inotifyFd = inotify_init();
266     if(g_inotifyFd == -1)
267     {
268         perror("inotify_init");
269         return -2;
270     }
271     int ret = watch_object(argv[1]);
272     if(ret != 0)
273     {
274         return -3;
275     }
276 
277     g_fp = fopen("/home/gc/Record_Jyb","a+");
278     if(g_fp == NULL)
279     {
280         perror("fopen");
281         return -4;
282     }
283 
284     struct sigaction stSign;
285     stSign.sa_handler = catch_signal;
286     sigemptyset(&stSign.sa_mask);
287     stSign.sa_flags = SA_RESETHAND;
288     sigaction(SIGINT,&stSign,0);
289 
290     while(1)
291     {
292         if(GetFileLine() >= 1000)
293         {
294             fclose(g_fp);
295             g_fp = fopen("/home/gc/Record_Jyb","w");
296             if(g_fp == NULL)
297             {
298                 perror("fopen");
299                 return -5;
300             }
301             fclose(g_fp);
302             g_fp = fopen("/home/gc/Record_Jyb","a+");
303             if(g_fp == NULL)
304             {
305                 perror("fopen");
306                 return -6;
307             }
308         }
309         ret = recordEvent();
310         if(ret < 0)
311         {
312             return -5;
313         }
314         sleep(10);
315     }
316 }

 

總的來講,雖然這只是一個很簡單的功能,但仍是爲本身的一小步提高而高興,在此分享給各位一塊兒進步。

單單代碼邏輯可修改的地方就有不少,還望你們見諒。

相關文章
相關標籤/搜索