編程之路剛剛開始,錯誤不免,但願你們可以指出。編程
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 }
總的來講,雖然這只是一個很簡單的功能,但仍是爲本身的一小步提高而高興,在此分享給各位一塊兒進步。
單單代碼邏輯可修改的地方就有不少,還望你們見諒。