Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1630710
  • 博文数量: 584
  • 博客积分: 13857
  • 博客等级: 上将
  • 技术积分: 11883
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-16 09:34

分类: LINUX

2010-07-31 12:05:59

一、dnotify机制
 1、使用
  通过对文件描述符设置监听信号实现。
  //设置文件相应信号
  fcntl(fd, F_SETSIG, SIGRTMIN + 1);
  //设置该文件要监听事件
  fcntl(fd, F_NOTIFY, DN_ACCESS|DN_MODIFY|DN_CREATE|DN_RENAME|DN_DELETE|DN_ATTRIB|DN_MULTISHOT);
  剩 下的就是信号处理了。
 2、缺点
  缺点1:dnotify机制对监视的每个文件夹都打开了一个文件描述符,如果文件夹所在文件系统需要 umount就不行了。
  缺点2:dnotify机制只能对文件夹进程监视。
 3、应用
 例子:
  1. // 要用fcntl( fd, F_SETSIG, SIGRTMIN + 1 )就要设置这个宏  
  2. #define _GNU_SOURCE 1  
  3. #include   
  4. #include   
  5. #include   
  6. #include   
  7. #define FOLDER_MAXLEN   128  
  8. static char listen_folder[FOLDER_MAXLEN];  
  9. static void myhandler( int );  
  10. int set_folder_signal( void )  
  11. {  
  12.     struct sigaction act;  
  13.     int fd;  
  14.   
  15.     act.sa_handler = myhandler;  
  16.     sigemptyset( &act.sa_mask );  
  17.     act.sa_flags = 0;  
  18.     sigaction( SIGRTMIN + 1, &act, NULL );  
  19.   
  20.     if(( fd = open( listen_folder, O_RDONLY )) < 0 )  
  21.         return -1;  
  22.     printf( "fd=%d\n", fd );  
  23.     fcntl( fd, F_SETSIG, SIGRTMIN + 1 );  
  24.     fcntl( fd, F_NOTIFY, DN_CREATE );  
  25.     return 0;  
  26. }  
  27. int main(int argc, char *argv[] )  
  28. {  
  29.     if( argc != 2 )  
  30.     {  
  31.         printf( "%s filepath\n", argv[0] );  
  32.         exit( 0 );  
  33.     }  
  34.     strncpy( listen_folder, argv[1], FOLDER_MAXLEN - 1 );   
  35.     if( set_folder_signal( ) < 0 )  
  36.     {  
  37.         printf( "set signal to %s fail\n", argv[1] );  
  38.         exit( 0 );  
  39.     }  
  40.     while( 1 )  
  41.     {  
  42.         pause();  
  43.         printf( "a signal return\n" );  
  44.     }  
  45. }  
  46. static void myhandler( int signo )  
  47. {  
  48.     printf( "signalno=%d,a file was creat\n", signo );  
  49.     set_folder_signal();  
  50. }  

以上例子信号处理函数只能得到信号编号信息。可以通过sa_sigaction信号处理函数来获得更多信息,但也很有限。比如文件描述符。
例 子:

  1. //要用 fcntl( fd, F_SETSIG, SIGRTMIN + 1 )就要设置这个宏  
  2. #define _GNU_SOURCE 1  
  3. #include   
  4. #include   
  5. #include   
  6. #include   
  7. #define FOLDER_MAXLEN   128  
  8. static char listen_folder[FOLDER_MAXLEN];  
  9. static void myhandler(int sig, siginfo_t *si, void *data);  
  10. int set_folder_signal( void )  
  11. {  
  12.     struct sigaction act;  
  13.     int fd;  
  14.   
  15.     act.sa_sigaction = myhandler;  
  16.     sigemptyset( &act.sa_mask );  
  17.     act.sa_flags = SA_SIGINFO;  
  18.     sigaction( SIGRTMIN + 1, &act, NULL );  
  19.   
  20.     if(( fd = open( listen_folder, O_RDONLY )) < 0 )  
  21.         return -1;  
  22.     printf( "fd=%d\n", fd );  
  23.     fcntl( fd, F_SETSIG, SIGRTMIN + 1 );  
  24.     fcntl( fd, F_NOTIFY, DN_CREATE );  
  25.     return 0;  
  26. }  
  27.   
  28. int main(int argc, char *argv[] )  
  29. {  
  30.     if( argc != 2 )  
  31.     {  
  32.         printf( "%s filepath\n", argv[0] );  
  33.         exit( 0 );  
  34.     }  
  35.     strncpy( listen_folder, argv[1], FOLDER_MAXLEN - 1 );   
  36.     if( set_folder_signal( ) < 0 )  
  37.     {  
  38.         printf( "set signal to %s fail\n", argv[1] );  
  39.         exit( 0 );  
  40.     }  
  41.     while( 1 )  
  42.     {  
  43.         pause();  
  44.         printf( "a signal return\n" );  
  45.     }  
  46. }  
  47.   
  48. static void myhandler(int signo, siginfo_t *si, void *data)  
  49. {  
  50.     printf( "signalno=%d=%d,a file was creat\n", signo, si->si_signo );  
  51.     printf( "errno值=%d\n", si->si_errno );  
  52.     printf( "信号产生的原因=%d\n", si->si_code );  
  53.     printf( "产生信号的文件描述符=%d\n", si->si_fd );  
  54.     set_folder_signal();  
  55. }  

二、inotify机制(内核2.6.13以上版本才支持,你可以uname -a看看)
 1、使用
  #include
  //初始化inotify机制
  int inotify_init (void);
  //添加目录或文件进程监视
  int inotify_add_watch (int fd, const char *path, __u32 mask);
  //删除一个监视
  int inotify_rm_watch (int fd, __u32 mask);
  //获得监视事件反馈信息struct inotify_event
  size_t len = read (fd, buf, BUF_LEN);

  struct inotify_event {
    __s32           wd;             /* 监视描述符 */
    __u32           mask;           /* 监视掩码 */
    __u32           len;            /* 产生事件对象名称长度 */
    char            name[0];        /* 产生事件对象名称 */
  };

  inotify机制可以监视文件系统事件:
  IN_ACCESS,文件被访问
  IN_MODIFY,文件被 write
  IN_ATTRIB, 文件属性被修改,如 chmod、chown、touch 等
  IN_CLOSE_WRITE,可写文件被 close
  IN_CLOSE_NOWRITE, 不可写文件被 close
  IN_OPEN,文件被 open
  IN_MOVED_FROM,文件被移走,如 mv
  IN_MOVED_TO, 文件被移来,如 mv、cp
  IN_CREATE,创建新文件
  IN_DELETE,文件被删除,如 rm
  IN_DELETE_SELF, 自删除,即一个可执行文件在执行时删除自己
  IN_MOVE_SELF,自移动,即一个可执行文件在执行时移动自己
  IN_UNMOUNT, 宿主文件系统被 umount
  IN_CLOSE,文件被关闭,等同于(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
  IN_MOVE,文件被移动,等同于(IN_MOVED_FROM | IN_MOVED_TO)
 2、 优点
  优点1:inotify不打开目标对象描述符,所以目标umount时不影响,且会产生一个umount事件通知inotify机 制,inotify自动删除该监视。
  优点2:inotify既可以监视文件,也可以监视目录。
  优点3:inotify使用系统调 用而不是信号的方式来通知文件系统事件,效率应该比较高。
  优点4:inotify中的添加监视后产生的是新的文件描述符作为接口,因此可以通 过select和poll来监视文件系统的变化。
 3、应用
 例子:

  1. #include   
  2. #include   
  3. #include   
  4. #include   
  5. #include   
  6.   
  7. char * event_array[] = {  
  8.     "File was accessed",  
  9.     "File was modified",  
  10.     "File attributes were changed",  
  11.     "writtable file closed",  
  12.     "Unwrittable file closed",  
  13.     "File was opened",  
  14.     "File was moved from X",  
  15.     "File was moved to Y",  
  16.     "Subfile was created",  
  17.     "Subfile was deleted",  
  18.     "Self was deleted",  
  19.     "Self was moved",  
  20.     "",  
  21.     "Backing fs was unmounted",  
  22.     "Event queued overflowed",  
  23.     "File was ignored"  
  24. };  
  25. #define EVENT_NUM 16  
  26. #define MAX_BUF_SIZE 1024  
  27.   
  28. int main(int argc, char *argv[] )  
  29. {  
  30.     int fd, wd;  
  31.     char buffer[ MAX_BUF_SIZE + 1 ];  
  32.     char * offset = NULL;  
  33.     struct inotify_event * event;  
  34.     int i, len, tmp_len;  
  35.     char strbuf[16];  
  36.   
  37.     if( argc != 2 )  
  38.     {  
  39.         printf( "%s file|folder\n", argv[0] );  
  40.         exit( 0 );  
  41.     }  
  42.     if(( fd = inotify_init()) < 0 )  
  43.     {  
  44.         printf("Fail to initialize inotify.\n");  
  45.         exit( 0 );  
  46.     }  
  47.     if(( wd = inotify_add_watch(fd, argv[1], IN_ALL_EVENTS)) < 0 )  
  48.     {  
  49.             printf("Can't add watch for %s.\n", argv[1]);  
  50.             exit(0);  
  51.     }  
  52.     while( len = read(fd, buffer, MAX_BUF_SIZE))   
  53.     {  
  54.         offset = buffer;  
  55.         event = (struct inotify_event *)buffer;  
  56.         while(((char *)event - buffer) < len )   
  57.         {  
  58.             printf( "Object type: %s\n",   
  59.                 event->mask & IN_ISDIR ? "Direcotory" : "File" );  
  60.             if(event->wd != wd)   
  61.                 continue;  
  62.             printf("Object name: %s\n"event->name);  
  63.             printf("Event mask: %08X\n"event->mask);  
  64.             for(i=0; i
  65.             {  
  66.                 if (event_array[i][0] == '\0')   
  67.                     continue;  
  68.                 if (event->mask & (1<
  69.                 {  
  70.                     printf("Event: %s\n", event_array[i]);  
  71.                 }  
  72.             }  
  73.             tmp_len = sizeof(struct inotify_event) + event->len;  
  74.             event = (struct inotify_event *)(offset + tmp_len);   
  75.             offset += tmp_len;  
  76.         }  
  77.     }  

阅读(1256) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~