一、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、应用
例子:
-
- #define _GNU_SOURCE 1
- #include
- #include
- #include
- #include
- #define FOLDER_MAXLEN 128
- static char listen_folder[FOLDER_MAXLEN];
- static void myhandler( int );
- int set_folder_signal( void )
- {
- struct sigaction act;
- int fd;
-
- act.sa_handler = myhandler;
- sigemptyset( &act.sa_mask );
- act.sa_flags = 0;
- sigaction( SIGRTMIN + 1, &act, NULL );
-
- if(( fd = open( listen_folder, O_RDONLY )) < 0 )
- return -1;
- printf( "fd=%d\n", fd );
- fcntl( fd, F_SETSIG, SIGRTMIN + 1 );
- fcntl( fd, F_NOTIFY, DN_CREATE );
- return 0;
- }
- int main(int argc, char *argv[] )
- {
- if( argc != 2 )
- {
- printf( "%s filepath\n", argv[0] );
- exit( 0 );
- }
- strncpy( listen_folder, argv[1], FOLDER_MAXLEN - 1 );
- if( set_folder_signal( ) < 0 )
- {
- printf( "set signal to %s fail\n", argv[1] );
- exit( 0 );
- }
- while( 1 )
- {
- pause();
- printf( "a signal return\n" );
- }
- }
- static void myhandler( int signo )
- {
- printf( "signalno=%d,a file was creat\n", signo );
- set_folder_signal();
- }
以上例子信号处理函数只能得到信号编号信息。可以通过sa_sigaction信号处理函数来获得更多信息,但也很有限。比如文件描述符。
例 子:
-
- #define _GNU_SOURCE 1
- #include
- #include
- #include
- #include
- #define FOLDER_MAXLEN 128
- static char listen_folder[FOLDER_MAXLEN];
- static void myhandler(int sig, siginfo_t *si, void *data);
- int set_folder_signal( void )
- {
- struct sigaction act;
- int fd;
-
- act.sa_sigaction = myhandler;
- sigemptyset( &act.sa_mask );
- act.sa_flags = SA_SIGINFO;
- sigaction( SIGRTMIN + 1, &act, NULL );
-
- if(( fd = open( listen_folder, O_RDONLY )) < 0 )
- return -1;
- printf( "fd=%d\n", fd );
- fcntl( fd, F_SETSIG, SIGRTMIN + 1 );
- fcntl( fd, F_NOTIFY, DN_CREATE );
- return 0;
- }
-
- int main(int argc, char *argv[] )
- {
- if( argc != 2 )
- {
- printf( "%s filepath\n", argv[0] );
- exit( 0 );
- }
- strncpy( listen_folder, argv[1], FOLDER_MAXLEN - 1 );
- if( set_folder_signal( ) < 0 )
- {
- printf( "set signal to %s fail\n", argv[1] );
- exit( 0 );
- }
- while( 1 )
- {
- pause();
- printf( "a signal return\n" );
- }
- }
-
- static void myhandler(int signo, siginfo_t *si, void *data)
- {
- printf( "signalno=%d=%d,a file was creat\n", signo, si->si_signo );
- printf( "errno值=%d\n", si->si_errno );
- printf( "信号产生的原因=%d\n", si->si_code );
- printf( "产生信号的文件描述符=%d\n", si->si_fd );
- set_folder_signal();
- }
二、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、应用
例子:
- #include
- #include
- #include
- #include
- #include
-
- char * event_array[] = {
- "File was accessed",
- "File was modified",
- "File attributes were changed",
- "writtable file closed",
- "Unwrittable file closed",
- "File was opened",
- "File was moved from X",
- "File was moved to Y",
- "Subfile was created",
- "Subfile was deleted",
- "Self was deleted",
- "Self was moved",
- "",
- "Backing fs was unmounted",
- "Event queued overflowed",
- "File was ignored"
- };
- #define EVENT_NUM 16
- #define MAX_BUF_SIZE 1024
-
- int main(int argc, char *argv[] )
- {
- int fd, wd;
- char buffer[ MAX_BUF_SIZE + 1 ];
- char * offset = NULL;
- struct inotify_event * event;
- int i, len, tmp_len;
- char strbuf[16];
-
- if( argc != 2 )
- {
- printf( "%s file|folder\n", argv[0] );
- exit( 0 );
- }
- if(( fd = inotify_init()) < 0 )
- {
- printf("Fail to initialize inotify.\n");
- exit( 0 );
- }
- if(( wd = inotify_add_watch(fd, argv[1], IN_ALL_EVENTS)) < 0 )
- {
- printf("Can't add watch for %s.\n", argv[1]);
- exit(0);
- }
- while( len = read(fd, buffer, MAX_BUF_SIZE))
- {
- offset = buffer;
- event = (struct inotify_event *)buffer;
- while(((char *)event - buffer) < len )
- {
- printf( "Object type: %s\n",
- event->mask & IN_ISDIR ? "Direcotory" : "File" );
- if(event->wd != wd)
- continue;
- printf("Object name: %s\n", event->name);
- printf("Event mask: %08X\n", event->mask);
- for(i=0; i
- {
- if (event_array[i][0] == '\0')
- continue;
- if (event->mask & (1<
- {
- printf("Event: %s\n", event_array[i]);
- }
- }
- tmp_len = sizeof(struct inotify_event) + event->len;
- event = (struct inotify_event *)(offset + tmp_len);
- offset += tmp_len;
- }
- }
- }