#include
#include
char * monitored_files [] = {
" ./tmp_file " ,
" ./tmp_dir " ,
" /mnt/sda3/windows_file "
} ;
struct wd_name {
int wd ;
char * name ;
} ;
#define WD_NUM 3
struct wd_name wd_array [ WD_NUM ] ; //用于存储文件路径名和watch描述符
//inotify机制事件对应说明数组
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 ( void )
{
int fd ;
int wd ;
char buffer [ 1024 ] ;
char * offset = NULL ;
struct inotify_event * event ;
int len , tmp_len ;
char strbuf [ 16 ] ;
int i = 0 ;
fd = inotify_init () ;
if ( fd < 0 ) {
printf ( " Fail to initialize inotify. / n " ) ;
exit ( - 1 ) ;
}
for ( i = 0 ; i < WD_NUM ; i ++ ) {
wd_array < I >. name = monitored_files < I >; //存入文件路径名
//给路径wd_array<I>.name添加一个watch,监视所有事件,wd为返回的watch描述符
wd = inotify_add_watch ( fd , wd_array < I >. name , IN_ALL_EVENTS ) ;
if ( wd < 0 ) {
printf ( " Can't add watch for %s. / n " , wd_array < I >. name ) ;
exit ( - 1 ) ;
}
wd_array < I >. wd = wd ;
}
while ( len = read ( fd , buffer , MAX_BUF_SIZE )) { //读取多个事件
offset = buffer ;
printf ( " Some event happens, len = %d. / n " , len ) ; //打印实际读取的长度
event = ( struct inotify_event * ) buffer ; //得到事件
while ((( char * ) event - buffer ) < len ) {
if ( event -> mask & IN_ISDIR ) { //目录
memcpy ( strbuf , " Direcotory " , 11 ) ;
//“Direcotory”字符串长度为11
}
else {
memcpy ( strbuf , " File " , 5 ) ;
//“File”字符串长度为5,包括后面加一个空格
}
printf ( " Object type: %s / n " , strbuf ) ;
for ( i = 0 ; i < WD_NUM ; i ++ ) {
if ( event -> wd != wd_array < I >. wd )
continue ;
printf ( " Object name: %s / n " , wd_array < I >. name ) ;
//打印文件路径名
break ;
}
printf ( " Event mask: %08X / n " , event -> mask ) ; //打印事件掩码
for ( i = 0 ; i < EVENT_NUM ; i ++ ) {
if ( event_array < I > [ 0 ] == '/ 0 ' )
//空字符串行,说明事件对应说明不存在
continue ;
//将事件掩码的位匹配数组成员,如:00000020,即100000,对应i为5
if ( event -> mask & ( 1 << i )) {
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 ;
}
}
}
C Code Snip
Incomplete, for a better example look at the Beagle source code in glue/inotify-glue.c
.
// Initialize Inotify
fd = inotify_init ();
if (fd < 0) return -errno;
// Add a Watch
int wd;
wd = inotify_add_watch (fd, filename, mask);
if (wd < 0) return -errno;
// Read an inotify event (buffer should be at least the size of
static struc inotify_event *buffer = NULL;
buffer_size = sizeof (struct inotify_event);
*nr = read (fd, buffer, buffer_size);
inotify_rm_watch(wd);
PERL Code Snip
Using Linux::Inotify2, this package also allows the use of (really cool) callback functions on the watch. It's then up to the developer to call poll(), see the Linux::Inotify2 page for more information. This sample takes a more procedural approach.
use Linux::Inotify2;
my $inotify = new Linux::Inotify2();
foreach (@ARGV)
{
$inotify->watch($_, IN_ALL_EVENTS);
}
while (1)
{
# By default this will block until something is read
my @events = $inotify->read();
if (scalar(@events)==0)
{
print "read error: $!";
last;
}
foreach (@events)
{
printf "File: %s; Mask: %d/n", $_->fullname, $_->mask;
}
How it works
Inotify is used through a series of system calls specifically created for inotify.
int inotify_init()Creates an inotify instance. Returns a file descriptor which all events are read from.
int inotify_add_watch(int fd, const char* pathname, int mask)Starts watching the inode pointed to by pathname for events contained in mask. Returns a watch descriptor which is unique (within this inotify instance) to the inode pointed to by the pathname (NOTE: Multiple pathnames can point to the same inode/watch descriptor).
int inotify_rm_watch(int fd, int wd)Cancels a watch on the given watch descriptor.
Events generated by inotify contain the following information:
Identifier | Contents |
---|---|
wd | watch descriptor |
mask | event tag |
cookie | cookie used to synchronize between IN_MOVED_FROM and IN_MOVED_TO |
len | length of name field |
name | the (optional) filename associated with this event (local to parent directory) |
Some of the events that can be monitored for are:
- IN_ACCESS - read of the file
- IN_MODIFY - last modification
- IN_ATTRIB - attributes of file change
- IN_OPEN and IN_CLOSE - open or close of file
- IN_MOVED_FROM and IN_MOVED_TO - when the file is moved or renamed
- IN_DELETE - a file/directory deleted
- IN_CREATE - a file/directory created
- IN_DELETE_SELF - file monitored is deleted
}
参考:http://fanqiang.chinaunix.net/program/other/2005-05-10/3225.shtml
http://www.qqread.com/linux/2008/10/u435108_3.html
http://www.linuxjournal.com/article/8478
http://blog.csdn.net/absurd/archive/2007/06/18/1656944.aspx
http://blog.chinaunix.net/u/3425/showart_325415.html
QT 中也有相关的类,但要基于系统